mirror of
https://github.com/marzer/tomlplusplus.git
synced 2024-10-06 06:49:43 +00:00
fixed inconsistent error messages for overlong ints/floats (closes #133)
also: - added `at_path()` (closes #118) - added `node_view::operator==` - updated conformance tests
This commit is contained in:
parent
47241d003e
commit
3f4a540ca6
@ -29,9 +29,11 @@ AttributeMacros:
|
||||
- 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:
|
||||
|
39
CHANGELOG.md
39
CHANGELOG.md
@ -17,29 +17,35 @@ template:
|
||||
|
||||
## Unreleased
|
||||
|
||||
This release will be a major version bump, so it's ABI breaks all around. Any API changes that might necessitate
|
||||
code changes at callsites or in build systems are indicated with ⚠️.
|
||||
This release will be a major version bump, so it's ABI breaks all around.
|
||||
Any changes that might cause code or build systems to break are indicated with ⚠️.
|
||||
|
||||
Highlights are indicated with ❤️.
|
||||
|
||||
#### Fixes:
|
||||
- ⚠️ fixed incorrect `noexcept` specifications on many functions
|
||||
- ⚠️ 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 `TOML_API` + extern templates causing linker errors in some circumstances
|
||||
- fixed a number of spec conformance issues (#127, #128, #129, #130, #131, #132) (@moorereason)
|
||||
- fixed an illegal table redefinition edge case (#112) (@python36)
|
||||
- fixed documentation issues
|
||||
- fixed incorrect source position in redefinition error messages
|
||||
- fixed incorrect handling of vertical whitespace in keys when printing TOML to streams
|
||||
- fixed incorrect source position in redefinition error messages
|
||||
- fixed memory leak during parse failures when compiled using GCC (#123, #124) (@rsmmr, @ronalabraham)
|
||||
- fixed missing `#include <initializer_list>`
|
||||
- fixed missing `#include <utility>`
|
||||
- fixed missing `TOML_API` on interfaces
|
||||
- fixed parser not correctly round-tripping the format of binary and octal integers in some cases
|
||||
- fixed strong exception guarantee edge-cases in `toml::table` and `toml::array`
|
||||
- fixed some incorrect unicode scalar sequence transformations (#125)
|
||||
- fixed a number of spec conformance issues (#127, #128, #129, #130, #131, #132) (@moorereason)
|
||||
- fixed strong exception guarantee edge-cases in `toml::table` and `toml::array`
|
||||
|
||||
#### Additions:
|
||||
- added `operator->` to `toml::value` for class types
|
||||
- ❤️ added `operator->` to `toml::value` for class types
|
||||
- ❤️ added `toml::at_path()`, `toml::node::at_path()` and `toml::node_view::at_path()` for qualified path-based lookups (#118) (@ben-crowhurst)
|
||||
- ❤️ added `toml::key` - provides a facility to access the source_regions of parsed keys (#82) (@vaartis)
|
||||
- ❤️ added `toml::yaml_formatter`
|
||||
- ❤️ added support for Unicode 14.0
|
||||
- added `parse_benchmark` example
|
||||
- added `toml::array::at()` (same semantics as `std::vector::at()`)
|
||||
- added `toml::array::prune()`
|
||||
@ -51,22 +57,19 @@ code changes at callsites or in build systems are indicated with ⚠️.
|
||||
- added `toml::format_flags::allow_octal_integers`
|
||||
- added `toml::format_flags::allow_real_tabs_in_strings`
|
||||
- added `toml::format_flags::allow_unicode_strings`
|
||||
- added `toml::format_flags::indent_array_elements`
|
||||
- added `toml::format_flags::indent_sub_tables`
|
||||
- added `toml::format_flags::indent_array_elements` (#120) (@W4RH4WK)
|
||||
- added `toml::format_flags::indent_sub_tables` (#120) (@W4RH4WK)
|
||||
- added `toml::format_flags::quote_infinities_and_nans`
|
||||
- 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::node_view::operator==`
|
||||
- added `toml::table::at()` (same semantics as `std::map::at()`)
|
||||
- added `toml::table::emplace_hint()` (same semantics as `std::map::emplace_hint()`)
|
||||
- added `toml::table::lower_bound()` (same semantics as `std::map::lower_bound()`)
|
||||
- added `toml::table::prune()`
|
||||
- added `toml::value` copy+move constructor overloads with flags override
|
||||
- added `toml::yaml_formatter`
|
||||
- added `TOML_ENABLE_FORMATTERS` option
|
||||
- added clang's enum annotation attributes to all enums
|
||||
- added formatter indentation flags (#120) (@W4RH4WK)
|
||||
- added magic `toml::value_flags` constant `toml::preserve_source_value_flags`
|
||||
- added support for Unicode 14.0
|
||||
- added value flags to array + table insert methods (#44) (@levicki)
|
||||
|
||||
#### Changes:
|
||||
@ -79,14 +82,14 @@ code changes at callsites or in build systems are indicated with ⚠️.
|
||||
- ⚠️ 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)
|
||||
- `toml::node::ref()` now supports explicit ref categories and cv-qualifiers
|
||||
- applied clang-format to all the things 🎉️
|
||||
- ❤️ `toml::node::ref()` now supports explicit ref categories and cv-qualifiers
|
||||
- ❤️ 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
|
||||
- exposed `TOML_NAMESPACE_START` and `TOML_NAMESPACE_END` macros to help with ADL specialization scenarios
|
||||
|
||||
#### Removals:
|
||||
- ⚠️ removed `toml::format_flags::allow_value_format_flags`
|
||||
|
2
cpp.hint
2
cpp.hint
@ -33,3 +33,5 @@
|
||||
#define TOML_RETURNS_BY_THROWING
|
||||
#define TOML_TRIVIAL_ABI
|
||||
#define TOML_UNLIKELY(...) (__VA_ARGS__)
|
||||
#define TOML_LIKELY_CASE
|
||||
#define TOML_UNLIKELY_CASE
|
||||
|
@ -98,7 +98,7 @@ namespace
|
||||
R"(val = 01 )"sv,
|
||||
|
||||
"########## floats"sv,
|
||||
R"(val = 9999999999999999999999999999999999999999999999999999999999999995.0)"sv,
|
||||
R"(val = 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0)"sv,
|
||||
};
|
||||
|
||||
inline constexpr auto divider =
|
||||
|
2
external/toml-test
vendored
2
external/toml-test
vendored
@ -1 +1 @@
|
||||
Subproject commit 4634fdf3a6ecd6aaea5f4cdcd98b2733c2694993
|
||||
Subproject commit 442dea55c5173bc89c2afa1b023ecbf0e042ceac
|
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
|
||||
///
|
||||
///
|
||||
/// \warning 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 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"
|
@ -140,7 +140,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
case '\'': traits |= formatted_string_traits::single_quotes; break;
|
||||
default:
|
||||
{
|
||||
if (is_control_character(c))
|
||||
if TOML_UNLIKELY(is_control_character(c))
|
||||
traits |= formatted_string_traits::control_chars;
|
||||
|
||||
if (!is_ascii_bare_key_character(static_cast<char32_t>(c)))
|
||||
@ -191,7 +191,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
case U'\'': traits |= formatted_string_traits::single_quotes; break;
|
||||
default:
|
||||
{
|
||||
if (is_control_character(decoder.codepoint)
|
||||
if TOML_UNLIKELY(is_control_character(decoder.codepoint)
|
||||
|| is_non_ascii_vertical_whitespace(decoder.codepoint))
|
||||
traits |= formatted_string_traits::control_chars;
|
||||
|
||||
|
@ -1051,7 +1051,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
inline const T& min(const T& a, const T& b) noexcept //
|
||||
constexpr const T& min(const T& a, const T& b) noexcept //
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
@ -296,12 +296,14 @@ TOML_NAMESPACE_START
|
||||
/// \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
|
||||
{
|
||||
@ -313,12 +315,14 @@ TOML_NAMESPACE_START
|
||||
/// \name Iterators (ADL)
|
||||
/// @{
|
||||
|
||||
/// \brief Returns an iterator to the first character in a key's backing string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend const_iterator begin(const key& k) noexcept
|
||||
{
|
||||
return k.begin();
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator to one-past-the-last character in a key's backing string.
|
||||
TOML_PURE_INLINE_GETTER
|
||||
friend const_iterator end(const key& k) noexcept
|
||||
{
|
||||
|
@ -655,14 +655,6 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD
|
||||
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 node's underlying data.
|
||||
///
|
||||
/// \warning This function is dangerous if used carelessly and **WILL** break your code if the
|
||||
@ -968,9 +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"
|
||||
|
@ -13,6 +13,10 @@
|
||||
|
||||
#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
|
||||
@ -51,7 +55,62 @@ TOML_NAMESPACE_START
|
||||
|
||||
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"
|
||||
|
@ -68,7 +68,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class TOML_NAMESPACE::node_view;
|
||||
friend class node_view;
|
||||
|
||||
mutable viewed_type* node_ = nullptr;
|
||||
|
||||
@ -587,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
|
||||
@ -686,7 +703,16 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
/// \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
|
||||
@ -704,7 +730,18 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
/// \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
|
||||
@ -720,7 +757,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto arr = this->as_array())
|
||||
return node_view{ arr->get(index) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -767,12 +804,12 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
inline node::operator node_view<node>() noexcept
|
||||
{
|
||||
return node_view<node>(this);
|
||||
return node_view<node>{ this };
|
||||
}
|
||||
|
||||
inline node::operator node_view<const node>() const noexcept
|
||||
{
|
||||
return node_view<const node>(this);
|
||||
return node_view<const node>{ this };
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
@ -495,7 +495,7 @@ TOML_ANON_NAMESPACE_START
|
||||
class TOML_EMPTY_BASES utf8_buffered_reader
|
||||
{
|
||||
public:
|
||||
static constexpr size_t max_history_length = 72;
|
||||
static constexpr size_t max_history_length = 128;
|
||||
|
||||
private:
|
||||
static constexpr size_t history_buffer_size = max_history_length - 1; //'head' is stored in the reader
|
||||
@ -619,40 +619,40 @@ TOML_ANON_NAMESPACE_START
|
||||
template <>
|
||||
struct parse_integer_traits<2>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "binary integer"sv;
|
||||
static constexpr auto is_digit = impl::is_binary_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto buffer_length = 63;
|
||||
static constexpr auto prefix_codepoint = U'b';
|
||||
static constexpr auto prefix = "b"sv;
|
||||
static constexpr auto scope_qualifier = "binary integer"sv;
|
||||
static constexpr auto is_digit = impl::is_binary_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto min_buffer_length = 63;
|
||||
static constexpr auto prefix_codepoint = U'b';
|
||||
static constexpr auto prefix = "b"sv;
|
||||
};
|
||||
template <>
|
||||
struct parse_integer_traits<8>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "octal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_octal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto buffer_length = 21; // strlen("777777777777777777777")
|
||||
static constexpr auto prefix_codepoint = U'o';
|
||||
static constexpr auto prefix = "o"sv;
|
||||
static constexpr auto scope_qualifier = "octal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_octal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto min_buffer_length = 21; // strlen("777777777777777777777")
|
||||
static constexpr auto prefix_codepoint = U'o';
|
||||
static constexpr auto prefix = "o"sv;
|
||||
};
|
||||
template <>
|
||||
struct parse_integer_traits<10>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "decimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_decimal_digit;
|
||||
static constexpr auto is_signed = true;
|
||||
static constexpr auto buffer_length = 19; // strlen("9223372036854775807")
|
||||
static constexpr auto scope_qualifier = "decimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_decimal_digit;
|
||||
static constexpr auto is_signed = true;
|
||||
static constexpr auto min_buffer_length = 19; // strlen("9223372036854775807")
|
||||
};
|
||||
template <>
|
||||
struct parse_integer_traits<16>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "hexadecimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_hexadecimal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto buffer_length = 16; // strlen("7FFFFFFFFFFFFFFF")
|
||||
static constexpr auto prefix_codepoint = U'x';
|
||||
static constexpr auto prefix = "x"sv;
|
||||
static constexpr auto scope_qualifier = "hexadecimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_hexadecimal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto min_buffer_length = 16; // strlen("7FFFFFFFFFFFFFFF")
|
||||
static constexpr auto prefix_codepoint = U'x';
|
||||
static constexpr auto prefix = "x"sv;
|
||||
};
|
||||
|
||||
TOML_PURE_GETTER
|
||||
@ -1157,11 +1157,11 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
advance_and_return_if_error({}); // skip \r
|
||||
|
||||
if (is_eof())
|
||||
set_error_and_return_default("expected \\n, saw EOF"sv);
|
||||
if TOML_UNLIKELY(is_eof())
|
||||
set_error_and_return_default("expected \\n after \\r, saw EOF"sv);
|
||||
|
||||
if (*cp != U'\n')
|
||||
set_error_and_return_default("expected \\n, saw '"sv, to_sv(*cp), "'"sv);
|
||||
if TOML_UNLIKELY(*cp != U'\n')
|
||||
set_error_and_return_default("expected \\n after \\r, saw '"sv, to_sv(*cp), "'"sv);
|
||||
}
|
||||
else if (*cp != U'\n')
|
||||
return false;
|
||||
@ -1204,18 +1204,19 @@ TOML_IMPL_NAMESPACE_START
|
||||
return true;
|
||||
return_if_error({});
|
||||
|
||||
if constexpr (TOML_LANG_AT_LEAST(1, 0, 0))
|
||||
{
|
||||
// toml/issues/567 (disallow non-TAB control characters in comments)
|
||||
if (is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"control characters other than TAB (U+0009) are explicitly prohibited in comments"sv);
|
||||
#if TOML_LANG_AT_LEAST(1, 0, 0)
|
||||
|
||||
// toml/issues/567 (disallow non-TAB control characters in comments)
|
||||
if TOML_UNLIKELY(is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"control characters other than TAB (U+0009) are explicitly prohibited in comments"sv);
|
||||
|
||||
// toml/pull/720 (disallow surrogates in comments)
|
||||
else if TOML_UNLIKELY(is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited in comments"sv);
|
||||
#endif
|
||||
|
||||
// toml/pull/720 (disallow surrogates in comments)
|
||||
else if (is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited in comments"sv);
|
||||
}
|
||||
advance_and_return_if_error({});
|
||||
}
|
||||
|
||||
@ -1312,9 +1313,11 @@ TOML_IMPL_NAMESPACE_START
|
||||
if (multi_line && is_whitespace(*cp))
|
||||
{
|
||||
consume_leading_whitespace();
|
||||
if (!consume_line_break())
|
||||
|
||||
if TOML_UNLIKELY(!consume_line_break())
|
||||
set_error_and_return_default(
|
||||
"line-ending backslashes must be the last non-whitespace character on the line"sv);
|
||||
|
||||
skipping_whitespace = true;
|
||||
return_if_error({});
|
||||
continue;
|
||||
@ -1354,17 +1357,19 @@ TOML_IMPL_NAMESPACE_START
|
||||
while (place_value)
|
||||
{
|
||||
set_error_and_return_if_eof({});
|
||||
if (!is_hexadecimal_digit(*cp))
|
||||
|
||||
if TOML_UNLIKELY(!is_hexadecimal_digit(*cp))
|
||||
set_error_and_return_default("expected hex digit, saw '"sv, to_sv(*cp), "'"sv);
|
||||
|
||||
sequence_value += place_value * hex_to_dec(*cp);
|
||||
place_value /= 16u;
|
||||
advance_and_return_if_error({});
|
||||
}
|
||||
|
||||
if (is_unicode_surrogate(sequence_value))
|
||||
if TOML_UNLIKELY(is_unicode_surrogate(sequence_value))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 - U+DFFF) are explicitly prohibited"sv);
|
||||
else if (sequence_value > 0x10FFFFu)
|
||||
else if TOML_UNLIKELY(sequence_value > 0x10FFFFu)
|
||||
set_error_and_return_default("values greater than U+10FFFF are invalid"sv);
|
||||
|
||||
if (sequence_value < 0x80)
|
||||
@ -1392,7 +1397,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
break;
|
||||
}
|
||||
|
||||
// ???
|
||||
// ???
|
||||
TOML_UNLIKELY_CASE
|
||||
default: set_error_and_return_default("unknown escape sequence '\\"sv, to_sv(*cp), "'"sv);
|
||||
}
|
||||
|
||||
@ -1475,17 +1481,17 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
// handle control characters
|
||||
if (is_nontab_control_character(*cp))
|
||||
if TOML_UNLIKELY(is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"unescaped control characters other than TAB (U+0009) are explicitly prohibited"sv);
|
||||
|
||||
// handle surrogates in strings (1.0.0 and later)
|
||||
if constexpr (TOML_LANG_AT_LEAST(1, 0, 0))
|
||||
{
|
||||
if (is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unescaped unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited"sv);
|
||||
}
|
||||
#if TOML_LANG_AT_LEAST(1, 0, 0)
|
||||
|
||||
// handle surrogates in strings
|
||||
if TOML_UNLIKELY(is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unescaped unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited"sv);
|
||||
#endif
|
||||
|
||||
if (multi_line)
|
||||
{
|
||||
@ -1590,17 +1596,16 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
// handle control characters
|
||||
if (is_nontab_control_character(*cp))
|
||||
if TOML_UNLIKELY(is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"control characters other than TAB (U+0009) are explicitly prohibited"sv);
|
||||
|
||||
// handle surrogates in strings (1.0.0 and later)
|
||||
if constexpr (TOML_LANG_AT_LEAST(1, 0, 0))
|
||||
{
|
||||
if (is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 - U+DFFF) are explicitly prohibited"sv);
|
||||
}
|
||||
#if TOML_LANG_AT_LEAST(1, 0, 0)
|
||||
|
||||
// handle surrogates in strings
|
||||
if TOML_UNLIKELY(is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default("unicode surrogates (U+D800 - U+DFFF) are explicitly prohibited"sv);
|
||||
#endif
|
||||
|
||||
str.append(cp->bytes, cp->count);
|
||||
advance_and_return_if_error({});
|
||||
@ -1746,13 +1751,19 @@ TOML_IMPL_NAMESPACE_START
|
||||
advance_and_return_if_error_or_eof({});
|
||||
|
||||
// consume value chars
|
||||
char chars[64];
|
||||
char chars[utf8_buffered_reader::max_history_length];
|
||||
size_t length = {};
|
||||
const utf8_codepoint* prev = {};
|
||||
bool seen_decimal = false, seen_exponent = false;
|
||||
char first_integer_part = '\0';
|
||||
while (!is_eof() && !is_value_terminator(*cp))
|
||||
{
|
||||
if TOML_UNLIKELY(length == sizeof(chars))
|
||||
set_error_and_return_default("exceeds maximum length of "sv,
|
||||
static_cast<uint64_t>(sizeof(chars)),
|
||||
" characters"sv,
|
||||
(seen_exponent ? ""sv : " (consider using exponent notation)"sv));
|
||||
|
||||
if (*cp == U'_')
|
||||
{
|
||||
if (!prev || !is_decimal_digit(*prev))
|
||||
@ -1819,11 +1830,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
else
|
||||
set_error_and_return_default("expected decimal digit, saw '"sv, to_sv(*cp), "'"sv);
|
||||
|
||||
if (length == sizeof(chars))
|
||||
set_error_and_return_default("exceeds maximum length of "sv,
|
||||
static_cast<uint64_t>(sizeof(chars)),
|
||||
" characters"sv);
|
||||
|
||||
chars[length++] = static_cast<char>(cp->bytes[0]);
|
||||
prev = cp;
|
||||
advance_and_return_if_error({});
|
||||
@ -1851,6 +1857,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
auto fc_result = std::from_chars(chars, chars + length, result);
|
||||
switch (fc_result.ec)
|
||||
{
|
||||
TOML_LIKELY_CASE
|
||||
case std::errc{}: // ok
|
||||
return result * sign;
|
||||
|
||||
@ -2103,7 +2110,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
// consume value chars
|
||||
char chars[traits::buffer_length];
|
||||
static constexpr size_t underscore_padding = 32;
|
||||
static constexpr size_t buffer_length = traits::min_buffer_length + underscore_padding;
|
||||
char chars[buffer_length];
|
||||
size_t length = {};
|
||||
const utf8_codepoint* prev = {};
|
||||
while (!is_eof() && !is_value_terminator(*cp))
|
||||
@ -2609,7 +2618,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
advance_count++;
|
||||
eof_while_scanning = is_eof();
|
||||
}
|
||||
while (advance_count < utf8_buffered_reader::max_history_length && !is_eof()
|
||||
while (advance_count < (utf8_buffered_reader::max_history_length - 1u) && !is_eof()
|
||||
&& !is_value_terminator(*cp));
|
||||
};
|
||||
scan();
|
||||
@ -2658,8 +2667,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
// set the reader back to where we started
|
||||
go_back(advance_count);
|
||||
if (char_count < utf8_buffered_reader::max_history_length - 1u)
|
||||
chars[char_count] = U'\0';
|
||||
|
||||
// if after scanning ahead we still only have one value character,
|
||||
// the only valid value type is an integer.
|
||||
@ -2765,7 +2772,23 @@ TOML_IMPL_NAMESPACE_START
|
||||
case bzero_msk: [[fallthrough]];
|
||||
case bdigit_msk: [[fallthrough]];
|
||||
case begins_sign | has_digits | has_minus: [[fallthrough]];
|
||||
case begins_sign | has_digits | has_plus: val.reset(new value{ parse_integer<10>() }); break;
|
||||
case begins_sign | has_digits | has_plus:
|
||||
{
|
||||
// if the value was so long we exhausted the history buffer it's reasonable to assume
|
||||
// there was more and the value's actual type is impossible to identify without making the
|
||||
// buffer bigger (since it could have actually been a float), so emit an error.
|
||||
//
|
||||
// (this will likely only come up during fuzzing and similar scenarios)
|
||||
static constexpr size_t max_numeric_value_length =
|
||||
utf8_buffered_reader::max_history_length - 2u;
|
||||
if TOML_UNLIKELY(!eof_while_scanning && advance_count > max_numeric_value_length)
|
||||
set_error_and_return_default("numeric value too long to identify type - cannot exceed "sv,
|
||||
max_numeric_value_length,
|
||||
" characters"sv);
|
||||
|
||||
val.reset(new value{ parse_integer<10>() });
|
||||
break;
|
||||
}
|
||||
|
||||
// hexadecimal integers
|
||||
// 0x10
|
||||
@ -2923,17 +2946,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
return_after_error({});
|
||||
}
|
||||
|
||||
#if !TOML_LANG_AT_LEAST(1, 0, 0) // toml/issues/665 (heterogeneous arrays)
|
||||
{
|
||||
if (auto arr = val->as_array(); arr && !arr->is_homogeneous())
|
||||
{
|
||||
delete arr;
|
||||
set_error_at(begin_pos, "arrays cannot contain values of different types before TOML 1.0.0"sv);
|
||||
return_after_error({});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
val->source_ = { begin_pos, current_position(1), reader.source_path() };
|
||||
return val;
|
||||
}
|
||||
|
@ -358,7 +358,6 @@
|
||||
#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
|
||||
#endif
|
||||
#undef TOML_CPP_VERSION
|
||||
|
||||
//#====================================================================================================================
|
||||
//# USER CONFIGURATION
|
||||
@ -621,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]]
|
||||
|
@ -678,29 +678,29 @@ TOML_NAMESPACE_START
|
||||
/// node ["a"] was an integer with value 42
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
/// \tparam T One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
impl::wrap_node<ValueType>* get_as(std::string_view key) noexcept
|
||||
impl::wrap_node<T>* get_as(std::string_view key) noexcept
|
||||
{
|
||||
const auto n = this->get(key);
|
||||
return n ? n->template as<ValueType>() : nullptr;
|
||||
return n ? n->template as<T>() : nullptr;
|
||||
}
|
||||
|
||||
/// \brief Gets the node at a specific key if it is a particular type (const overload).
|
||||
///
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
/// \tparam T One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
const impl::wrap_node<ValueType>* get_as(std::string_view key) const noexcept
|
||||
const impl::wrap_node<T>* get_as(std::string_view key) const noexcept
|
||||
{
|
||||
return const_cast<table&>(*this).template get_as<ValueType>(key);
|
||||
return const_cast<table&>(*this).template get_as<T>(key);
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
@ -709,33 +709,33 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
/// \tparam T One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
impl::wrap_node<ValueType>* get_as(std::wstring_view key)
|
||||
impl::wrap_node<T>* get_as(std::wstring_view key)
|
||||
{
|
||||
if (empty())
|
||||
return nullptr;
|
||||
|
||||
return get_as<ValueType>(impl::narrow(key));
|
||||
return get_as<T>(impl::narrow(key));
|
||||
}
|
||||
|
||||
/// \brief Gets the node at a specific key if it is a particular type (const overload).
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
/// \tparam ValueType One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
/// \tparam T One of the TOML node or value types.
|
||||
/// \param key The node's key.
|
||||
///
|
||||
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
const impl::wrap_node<ValueType>* get_as(std::wstring_view key) const
|
||||
const impl::wrap_node<T>* get_as(std::wstring_view key) const
|
||||
{
|
||||
return const_cast<table&>(*this).template get_as<ValueType>(key);
|
||||
return const_cast<table&>(*this).template get_as<T>(key);
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
@ -1571,7 +1571,7 @@ TOML_NAMESPACE_START
|
||||
/// \name Node views
|
||||
/// @{
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair.
|
||||
/// \brief Gets a node_view for the selected value.
|
||||
///
|
||||
/// \param key The key used for the lookup.
|
||||
///
|
||||
@ -1588,7 +1588,7 @@ TOML_NAMESPACE_START
|
||||
return node_view<node>{ get(key) };
|
||||
}
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair (const overload).
|
||||
/// \brief Gets a node_view for the selected value (const overload).
|
||||
///
|
||||
/// \param key The key used for the lookup.
|
||||
///
|
||||
@ -1607,7 +1607,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair.
|
||||
/// \brief Gets a node_view for the selected value.
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
@ -1626,7 +1626,7 @@ TOML_NAMESPACE_START
|
||||
return node_view<node>{ get(key) };
|
||||
}
|
||||
|
||||
/// \brief Gets a node_view for the selected key-value pair (const overload).
|
||||
/// \brief Gets a node_view for the selected value (const overload).
|
||||
///
|
||||
/// \availability This overload is only available when #TOML_ENABLE_WINDOWS_COMPAT is enabled.
|
||||
///
|
||||
@ -1700,39 +1700,6 @@ TOML_NAMESPACE_START
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
//# template <typename T>
|
||||
//# inline std::vector<T> node::select_exact() const noexcept
|
||||
//# {
|
||||
//# using namespace impl;
|
||||
//#
|
||||
//# static_assert(
|
||||
//# !is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
//# "Retrieving values as wide-character strings with node::select_exact() is only "
|
||||
//# "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::select_exact()")
|
||||
//# );
|
||||
//# }
|
||||
|
||||
//# template <typename T>
|
||||
//# inline std::vector<T> node::select() const noexcept
|
||||
//# {
|
||||
//# using namespace impl;
|
||||
//#
|
||||
//# static_assert(
|
||||
//# !is_wide_string<T> || TOML_ENABLE_WINDOWS_COMPAT,
|
||||
//# "Retrieving values as wide-character strings with node::select() is only "
|
||||
//# "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::select()")
|
||||
//# );
|
||||
//# }
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
|
@ -16,13 +16,18 @@ TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SPAM_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
|
||||
|
||||
// misc warning false-positives
|
||||
#if TOML_MSVC
|
||||
#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch (false-positive)
|
||||
#elif TOML_CLANG && !TOML_HEADER_ONLY && TOML_IMPLEMENTATION
|
||||
#pragma clang diagnostic ignored "-Wheader-hygiene" // false-positive
|
||||
#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" // false-positive
|
||||
#pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "impl/std_new.h"
|
||||
@ -32,6 +37,7 @@ TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
|
||||
#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/node_view.h"
|
||||
#include "impl/value.h"
|
||||
@ -54,6 +60,7 @@ TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
|
||||
#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"
|
||||
@ -92,6 +99,7 @@ TOML_POP_WARNINGS;
|
||||
#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
|
||||
@ -138,6 +146,7 @@ TOML_POP_WARNINGS;
|
||||
#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
|
||||
@ -172,6 +181,7 @@ TOML_POP_WARNINGS;
|
||||
#undef TOML_TRIVIAL_ABI
|
||||
#undef TOML_UINT128
|
||||
#undef TOML_UNLIKELY
|
||||
#undef TOML_UNLIKELY_CASE
|
||||
#undef TOML_UNREACHABLE
|
||||
#undef TOML_UNUSED
|
||||
#endif
|
||||
|
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
|
||||
}
|
||||
}
|
@ -46,29 +46,34 @@ fruit = []
|
||||
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 control_bare_null = "bare-null = \"some value\" \x00"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 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;
|
||||
@ -169,6 +174,9 @@ trailing-us-exp2 = 1.2_e2)"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;
|
||||
@ -206,6 +214,9 @@ abc = { abc = 123, })"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;
|
||||
@ -436,8 +447,14 @@ 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, 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
|
||||
@ -590,6 +607,8 @@ TEST_CASE("conformance - burntsushi/invalid")
|
||||
|
||||
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
|
||||
@ -626,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
|
||||
|
@ -446,6 +446,11 @@ notunicode3 = "This string does not have a unicode \\u0075 escape."
|
||||
notunicode4 = "This string does not have a unicode \\\u0075 escape."
|
||||
delete = "This string has a \u007F delete control code."
|
||||
unitseparator = "This string has a \u001F unit separator control code.")"sv;
|
||||
static constexpr auto string_multiline_escaped_crlf =
|
||||
"# The following line should be an unescaped backslash followed by a Windows\r\n"
|
||||
"# newline sequence (\"\\r\\n\")\r\n"
|
||||
"0=\"\"\"\\\r\n"
|
||||
"\"\"\""sv;
|
||||
static constexpr auto string_multiline_quotes =
|
||||
R"(# Make sure that quotes inside multiline strings are allowed, including right
|
||||
# after the opening '''/""" and before the closing '''/"""
|
||||
@ -2141,7 +2146,7 @@ another line)"sv },
|
||||
{ R"(backspace)"sv, "This string has a \x08 backspace character."sv },
|
||||
{ R"(carriage)"sv, "This string has a \r carriage return character."sv },
|
||||
{ R"(delete)"sv, "This string has a \x7F delete control code."sv },
|
||||
{ R"(formfeed)"sv, "This string has a \x0C form feed character."sv },
|
||||
{ R"(formfeed)"sv, "This string has a \f form feed character."sv },
|
||||
{ R"(newline)"sv, R"(This string has a
|
||||
new line character.)"sv },
|
||||
{ R"(notunicode1)"sv, R"(This string does not have a unicode \u escape.)"sv },
|
||||
@ -2155,6 +2160,16 @@ another line)"sv },
|
||||
REQUIRE(tbl == expected);
|
||||
});
|
||||
|
||||
parsing_should_succeed(FILE_LINE_ARGS,
|
||||
string_multiline_escaped_crlf,
|
||||
[](toml::table&& tbl) // string-multiline-escaped-crlf
|
||||
{
|
||||
const auto expected = toml::table{
|
||||
{ R"(0)"sv, ""sv },
|
||||
};
|
||||
REQUIRE(tbl == expected);
|
||||
});
|
||||
|
||||
parsing_should_succeed(
|
||||
FILE_LINE_ARGS,
|
||||
string_multiline_quotes,
|
||||
|
@ -1466,7 +1466,7 @@ Violets are blue)"sv },
|
||||
[](toml::table&& tbl) // spec-string-escape-4
|
||||
{
|
||||
const auto expected = toml::table{
|
||||
{ R"(a)"sv, "\x0C"sv },
|
||||
{ R"(a)"sv, "\f"sv },
|
||||
};
|
||||
REQUIRE(tbl == expected);
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
test_sources = [
|
||||
'at_path.cpp',
|
||||
'conformance_burntsushi_invalid.cpp',
|
||||
'conformance_burntsushi_valid.cpp',
|
||||
'conformance_iarna_invalid.cpp',
|
||||
|
@ -95,7 +95,7 @@ TEST_CASE("user feedback")
|
||||
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c' 'ml'\n\n%\x87");
|
||||
parsing_should_fail(
|
||||
FILE_LINE_ARGS,
|
||||
R"(t =[ 9, 2, 1,"r", 9999999999999999999999999999999999999999999999999999999999999995.0 ])");
|
||||
R"(t =[ 9, 2, 1,"r", 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 ])");
|
||||
}
|
||||
|
||||
SECTION("github/issues/67") // https://github.com/marzer/tomlplusplus/issues/67
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -73,6 +73,7 @@
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
@ -37,6 +37,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\toml++\impl\array.h" />
|
||||
<ClInclude Include="include\toml++\impl\array.inl" />
|
||||
<ClInclude Include="include\toml++\impl\at_path.h" />
|
||||
<ClInclude Include="include\toml++\impl\date_time.h" />
|
||||
<ClInclude Include="include\toml++\impl\key.h" />
|
||||
<ClInclude Include="include\toml++\impl\simd.h" />
|
||||
@ -96,6 +97,7 @@
|
||||
<None Include="CHANGELOG.md" />
|
||||
<None Include="CODE_OF_CONDUCT.md" />
|
||||
<None Include="CONTRIBUTING.md" />
|
||||
<None Include="include\toml++\impl\at_path.inl" />
|
||||
<None Include="include\toml++\impl\unicode.inl" />
|
||||
<None Include="include\toml++\impl\node_view_extern.inl" />
|
||||
<None Include="include\toml++\impl\yaml_formatter.inl" />
|
||||
|
@ -136,6 +136,9 @@
|
||||
<ClInclude Include="include\toml++\impl\key.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\toml++\impl\at_path.h">
|
||||
<Filter>include\impl</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="toml++.props" />
|
||||
@ -220,6 +223,9 @@
|
||||
<None Include=".github\ISSUE_TEMPLATE\spec_bug_report.md">
|
||||
<Filter>.github</Filter>
|
||||
</None>
|
||||
<None Include="include\toml++\impl\at_path.inl">
|
||||
<Filter>include\impl</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include=".circleci">
|
||||
|
@ -2,19 +2,20 @@
|
||||
|
||||
> ℹ️ _The contents of this directory relate to testing with the [toml-test] suite, **not** anything to do with running the library's unit-tests.
|
||||
> For information about running the unit-tests see [CONTRIBUTING](../CONTRIBUTING.md)._
|
||||
>
|
||||
> ℹ️ _All command snippets in this document assume the working directory is the toml++ repository root._
|
||||
|
||||
<br>
|
||||
|
||||
## Prequisites
|
||||
For this document to make sense, you will need to:
|
||||
1. Install some recent version of Go
|
||||
2. Follow the installation instructions from the [toml-test] README to compile the `toml-test` runner
|
||||
3. Add `toml-test` as an alias or have it on the system PATH
|
||||
4. Clone the toml++ repository's [nlohmann/json] submodule:
|
||||
1. Follow the installation instructions from the [toml-test] README to compile the `toml-test` runner
|
||||
2. Add `toml-test` as an alias or have it on the system PATH
|
||||
3. Clone the toml++ repository's [nlohmann/json] submodule:
|
||||
```bash
|
||||
git submodule update --init --depth 1 external/json
|
||||
```
|
||||
5. **Linux only:** Install `ninja` and `meson`:
|
||||
4. **Linux only:** Install `ninja` and `meson`:
|
||||
```bash
|
||||
sudo apt update && sudo apt install -y locales python3 python3-pip ninja-build
|
||||
sudo pip3 install meson
|
||||
@ -23,7 +24,6 @@ sudo pip3 install meson
|
||||
<br>
|
||||
|
||||
## Building and Testing the Encoder and Decoder
|
||||
> ℹ️ _Commands in this section assume the starting directory is the toml++ repository root directory._
|
||||
|
||||
### Windows with Visual Studio
|
||||
Open `toml++.sln` and build the two projects in the `toml-test` solution folder. They'll be compiled in some target-specific subfolder under `/bin` in the repo root. Then run `toml-test` against them:
|
||||
|
619
toml.hpp
619
toml.hpp
@ -377,7 +377,6 @@
|
||||
#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
|
||||
#endif
|
||||
#undef TOML_CPP_VERSION
|
||||
|
||||
#ifdef TOML_CONFIG_HEADER
|
||||
#include TOML_CONFIG_HEADER
|
||||
@ -631,19 +630,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]]
|
||||
@ -942,13 +957,18 @@ TOML_PUSH_WARNINGS;
|
||||
TOML_DISABLE_SPAM_WARNINGS;
|
||||
TOML_DISABLE_SWITCH_WARNINGS;
|
||||
TOML_DISABLE_SUGGEST_ATTR_WARNINGS;
|
||||
|
||||
// misc warning false-positives
|
||||
#if TOML_MSVC
|
||||
#pragma warning(disable : 5031) // #pragma warning(pop): likely mismatch (false-positive)
|
||||
#elif TOML_CLANG && !TOML_HEADER_ONLY && TOML_IMPLEMENTATION
|
||||
#pragma clang diagnostic ignored "-Wheader-hygiene" // false-positive
|
||||
#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" // false-positive
|
||||
#pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//******** impl/std_new.h ********************************************************************************************
|
||||
@ -1956,7 +1976,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
inline const T& min(const T& a, const T& b) noexcept //
|
||||
constexpr const T& min(const T& a, const T& b) noexcept //
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
@ -2524,6 +2544,32 @@ TOML_NAMESPACE_END;
|
||||
#endif
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
//******** impl/at_path.h ********************************************************************************************
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(node & root, std::string_view path) noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(const node& root, std::string_view path) noexcept;
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(node & root, std::wstring_view path);
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(const node& root, std::wstring_view path);
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
//******** impl/node.h ***********************************************************************************************
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
@ -3086,10 +3132,38 @@ TOML_NAMESPACE_START
|
||||
|
||||
TOML_NODISCARD
|
||||
explicit operator node_view<const node>() const noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(std::string_view path) noexcept;
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(std::string_view path) const noexcept;
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<node> at_path(std::wstring_view path);
|
||||
|
||||
TOML_NODISCARD
|
||||
TOML_API
|
||||
node_view<const node> at_path(std::wstring_view path) const;
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
};
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
|
||||
TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
TOML_PURE_GETTER
|
||||
TOML_API
|
||||
bool node_deep_equality(const node*, const node*) noexcept;
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pop_macro("min")
|
||||
#pragma pop_macro("max")
|
||||
@ -3127,7 +3201,7 @@ TOML_NAMESPACE_START
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class TOML_NAMESPACE::node_view;
|
||||
friend class node_view;
|
||||
|
||||
mutable viewed_type* node_ = nullptr;
|
||||
|
||||
@ -3417,6 +3491,22 @@ TOML_NAMESPACE_START
|
||||
return return_type{};
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
friend bool operator==(const node_view& lhs, const table& rhs) noexcept
|
||||
{
|
||||
@ -3499,7 +3589,13 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
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
|
||||
@ -3509,7 +3605,13 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto tbl = this->as_table())
|
||||
return node_view{ tbl->get(key) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
TOML_NODISCARD
|
||||
node_view at_path(std::wstring_view path) const
|
||||
{
|
||||
return node_ ? node_->at_path(path) : node_view{};
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
@ -3519,7 +3621,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
if (auto arr = this->as_array())
|
||||
return node_view{ arr->get(index) };
|
||||
return node_view{ nullptr };
|
||||
return {};
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_FORMATTERS
|
||||
@ -3618,12 +3720,12 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
inline node::operator node_view<node>() noexcept
|
||||
{
|
||||
return node_view<node>(this);
|
||||
return node_view<node>{ this };
|
||||
}
|
||||
|
||||
inline node::operator node_view<const node>() const noexcept
|
||||
{
|
||||
return node_view<const node>(this);
|
||||
return node_view<const node>{ this };
|
||||
}
|
||||
}
|
||||
TOML_NAMESPACE_END;
|
||||
@ -6627,38 +6729,38 @@ TOML_NAMESPACE_START
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
impl::wrap_node<ValueType>* get_as(std::string_view key) noexcept
|
||||
impl::wrap_node<T>* get_as(std::string_view key) noexcept
|
||||
{
|
||||
const auto n = this->get(key);
|
||||
return n ? n->template as<ValueType>() : nullptr;
|
||||
return n ? n->template as<T>() : nullptr;
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_PURE_GETTER
|
||||
const impl::wrap_node<ValueType>* get_as(std::string_view key) const noexcept
|
||||
const impl::wrap_node<T>* get_as(std::string_view key) const noexcept
|
||||
{
|
||||
return const_cast<table&>(*this).template get_as<ValueType>(key);
|
||||
return const_cast<table&>(*this).template get_as<T>(key);
|
||||
}
|
||||
|
||||
#if TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
impl::wrap_node<ValueType>* get_as(std::wstring_view key)
|
||||
impl::wrap_node<T>* get_as(std::wstring_view key)
|
||||
{
|
||||
if (empty())
|
||||
return nullptr;
|
||||
|
||||
return get_as<ValueType>(impl::narrow(key));
|
||||
return get_as<T>(impl::narrow(key));
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
const impl::wrap_node<ValueType>* get_as(std::wstring_view key) const
|
||||
const impl::wrap_node<T>* get_as(std::wstring_view key) const
|
||||
{
|
||||
return const_cast<table&>(*this).template get_as<ValueType>(key);
|
||||
return const_cast<table&>(*this).template get_as<T>(key);
|
||||
}
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
@ -9719,9 +9821,64 @@ TOML_NAMESPACE_START
|
||||
|
||||
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;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pop_macro("min")
|
||||
#pragma pop_macro("max")
|
||||
@ -9810,6 +9967,231 @@ TOML_NAMESPACE_END;
|
||||
#endif
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
//******** impl/at_path.inl ******************************************************************************************
|
||||
|
||||
TOML_DISABLE_WARNINGS;
|
||||
#if TOML_INT_CHARCONV
|
||||
#include <charconv>
|
||||
#else
|
||||
#include <sstream>
|
||||
#endif
|
||||
TOML_ENABLE_WARNINGS;
|
||||
TOML_PUSH_WARNINGS;
|
||||
#ifdef _MSC_VER
|
||||
#pragma push_macro("min")
|
||||
#pragma push_macro("max")
|
||||
#undef min
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pop_macro("min")
|
||||
#pragma pop_macro("max")
|
||||
#endif
|
||||
TOML_POP_WARNINGS;
|
||||
|
||||
//******** impl/value.inl ********************************************************************************************
|
||||
|
||||
TOML_PUSH_WARNINGS;
|
||||
@ -11115,7 +11497,7 @@ TOML_ANON_NAMESPACE_START
|
||||
class TOML_EMPTY_BASES utf8_buffered_reader
|
||||
{
|
||||
public:
|
||||
static constexpr size_t max_history_length = 72;
|
||||
static constexpr size_t max_history_length = 128;
|
||||
|
||||
private:
|
||||
static constexpr size_t history_buffer_size = max_history_length - 1; //'head' is stored in the reader
|
||||
@ -11235,40 +11617,40 @@ TOML_ANON_NAMESPACE_START
|
||||
template <>
|
||||
struct parse_integer_traits<2>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "binary integer"sv;
|
||||
static constexpr auto is_digit = impl::is_binary_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto buffer_length = 63;
|
||||
static constexpr auto prefix_codepoint = U'b';
|
||||
static constexpr auto prefix = "b"sv;
|
||||
static constexpr auto scope_qualifier = "binary integer"sv;
|
||||
static constexpr auto is_digit = impl::is_binary_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto min_buffer_length = 63;
|
||||
static constexpr auto prefix_codepoint = U'b';
|
||||
static constexpr auto prefix = "b"sv;
|
||||
};
|
||||
template <>
|
||||
struct parse_integer_traits<8>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "octal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_octal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto buffer_length = 21; // strlen("777777777777777777777")
|
||||
static constexpr auto prefix_codepoint = U'o';
|
||||
static constexpr auto prefix = "o"sv;
|
||||
static constexpr auto scope_qualifier = "octal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_octal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto min_buffer_length = 21; // strlen("777777777777777777777")
|
||||
static constexpr auto prefix_codepoint = U'o';
|
||||
static constexpr auto prefix = "o"sv;
|
||||
};
|
||||
template <>
|
||||
struct parse_integer_traits<10>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "decimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_decimal_digit;
|
||||
static constexpr auto is_signed = true;
|
||||
static constexpr auto buffer_length = 19; // strlen("9223372036854775807")
|
||||
static constexpr auto scope_qualifier = "decimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_decimal_digit;
|
||||
static constexpr auto is_signed = true;
|
||||
static constexpr auto min_buffer_length = 19; // strlen("9223372036854775807")
|
||||
};
|
||||
template <>
|
||||
struct parse_integer_traits<16>
|
||||
{
|
||||
static constexpr auto scope_qualifier = "hexadecimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_hexadecimal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto buffer_length = 16; // strlen("7FFFFFFFFFFFFFFF")
|
||||
static constexpr auto prefix_codepoint = U'x';
|
||||
static constexpr auto prefix = "x"sv;
|
||||
static constexpr auto scope_qualifier = "hexadecimal integer"sv;
|
||||
static constexpr auto is_digit = impl::is_hexadecimal_digit;
|
||||
static constexpr auto is_signed = false;
|
||||
static constexpr auto min_buffer_length = 16; // strlen("7FFFFFFFFFFFFFFF")
|
||||
static constexpr auto prefix_codepoint = U'x';
|
||||
static constexpr auto prefix = "x"sv;
|
||||
};
|
||||
|
||||
TOML_PURE_GETTER
|
||||
@ -11773,11 +12155,11 @@ TOML_IMPL_NAMESPACE_START
|
||||
{
|
||||
advance_and_return_if_error({}); // skip \r
|
||||
|
||||
if (is_eof())
|
||||
set_error_and_return_default("expected \\n, saw EOF"sv);
|
||||
if TOML_UNLIKELY(is_eof())
|
||||
set_error_and_return_default("expected \\n after \\r, saw EOF"sv);
|
||||
|
||||
if (*cp != U'\n')
|
||||
set_error_and_return_default("expected \\n, saw '"sv, to_sv(*cp), "'"sv);
|
||||
if TOML_UNLIKELY(*cp != U'\n')
|
||||
set_error_and_return_default("expected \\n after \\r, saw '"sv, to_sv(*cp), "'"sv);
|
||||
}
|
||||
else if (*cp != U'\n')
|
||||
return false;
|
||||
@ -11820,18 +12202,19 @@ TOML_IMPL_NAMESPACE_START
|
||||
return true;
|
||||
return_if_error({});
|
||||
|
||||
if constexpr (TOML_LANG_AT_LEAST(1, 0, 0))
|
||||
{
|
||||
// toml/issues/567 (disallow non-TAB control characters in comments)
|
||||
if (is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"control characters other than TAB (U+0009) are explicitly prohibited in comments"sv);
|
||||
#if TOML_LANG_AT_LEAST(1, 0, 0)
|
||||
|
||||
// toml/issues/567 (disallow non-TAB control characters in comments)
|
||||
if TOML_UNLIKELY(is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"control characters other than TAB (U+0009) are explicitly prohibited in comments"sv);
|
||||
|
||||
// toml/pull/720 (disallow surrogates in comments)
|
||||
else if TOML_UNLIKELY(is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited in comments"sv);
|
||||
#endif
|
||||
|
||||
// toml/pull/720 (disallow surrogates in comments)
|
||||
else if (is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited in comments"sv);
|
||||
}
|
||||
advance_and_return_if_error({});
|
||||
}
|
||||
|
||||
@ -11928,9 +12311,11 @@ TOML_IMPL_NAMESPACE_START
|
||||
if (multi_line && is_whitespace(*cp))
|
||||
{
|
||||
consume_leading_whitespace();
|
||||
if (!consume_line_break())
|
||||
|
||||
if TOML_UNLIKELY(!consume_line_break())
|
||||
set_error_and_return_default(
|
||||
"line-ending backslashes must be the last non-whitespace character on the line"sv);
|
||||
|
||||
skipping_whitespace = true;
|
||||
return_if_error({});
|
||||
continue;
|
||||
@ -11970,17 +12355,19 @@ TOML_IMPL_NAMESPACE_START
|
||||
while (place_value)
|
||||
{
|
||||
set_error_and_return_if_eof({});
|
||||
if (!is_hexadecimal_digit(*cp))
|
||||
|
||||
if TOML_UNLIKELY(!is_hexadecimal_digit(*cp))
|
||||
set_error_and_return_default("expected hex digit, saw '"sv, to_sv(*cp), "'"sv);
|
||||
|
||||
sequence_value += place_value * hex_to_dec(*cp);
|
||||
place_value /= 16u;
|
||||
advance_and_return_if_error({});
|
||||
}
|
||||
|
||||
if (is_unicode_surrogate(sequence_value))
|
||||
if TOML_UNLIKELY(is_unicode_surrogate(sequence_value))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 - U+DFFF) are explicitly prohibited"sv);
|
||||
else if (sequence_value > 0x10FFFFu)
|
||||
else if TOML_UNLIKELY(sequence_value > 0x10FFFFu)
|
||||
set_error_and_return_default("values greater than U+10FFFF are invalid"sv);
|
||||
|
||||
if (sequence_value < 0x80)
|
||||
@ -12008,7 +12395,8 @@ TOML_IMPL_NAMESPACE_START
|
||||
break;
|
||||
}
|
||||
|
||||
// ???
|
||||
// ???
|
||||
TOML_UNLIKELY_CASE
|
||||
default: set_error_and_return_default("unknown escape sequence '\\"sv, to_sv(*cp), "'"sv);
|
||||
}
|
||||
|
||||
@ -12091,17 +12479,17 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
// handle control characters
|
||||
if (is_nontab_control_character(*cp))
|
||||
if TOML_UNLIKELY(is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"unescaped control characters other than TAB (U+0009) are explicitly prohibited"sv);
|
||||
|
||||
// handle surrogates in strings (1.0.0 and later)
|
||||
if constexpr (TOML_LANG_AT_LEAST(1, 0, 0))
|
||||
{
|
||||
if (is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unescaped unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited"sv);
|
||||
}
|
||||
#if TOML_LANG_AT_LEAST(1, 0, 0)
|
||||
|
||||
// handle surrogates in strings
|
||||
if TOML_UNLIKELY(is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unescaped unicode surrogates (U+D800 to U+DFFF) are explicitly prohibited"sv);
|
||||
#endif
|
||||
|
||||
if (multi_line)
|
||||
{
|
||||
@ -12206,17 +12594,16 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
// handle control characters
|
||||
if (is_nontab_control_character(*cp))
|
||||
if TOML_UNLIKELY(is_nontab_control_character(*cp))
|
||||
set_error_and_return_default(
|
||||
"control characters other than TAB (U+0009) are explicitly prohibited"sv);
|
||||
|
||||
// handle surrogates in strings (1.0.0 and later)
|
||||
if constexpr (TOML_LANG_AT_LEAST(1, 0, 0))
|
||||
{
|
||||
if (is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default(
|
||||
"unicode surrogates (U+D800 - U+DFFF) are explicitly prohibited"sv);
|
||||
}
|
||||
#if TOML_LANG_AT_LEAST(1, 0, 0)
|
||||
|
||||
// handle surrogates in strings
|
||||
if TOML_UNLIKELY(is_unicode_surrogate(*cp))
|
||||
set_error_and_return_default("unicode surrogates (U+D800 - U+DFFF) are explicitly prohibited"sv);
|
||||
#endif
|
||||
|
||||
str.append(cp->bytes, cp->count);
|
||||
advance_and_return_if_error({});
|
||||
@ -12362,13 +12749,19 @@ TOML_IMPL_NAMESPACE_START
|
||||
advance_and_return_if_error_or_eof({});
|
||||
|
||||
// consume value chars
|
||||
char chars[64];
|
||||
char chars[utf8_buffered_reader::max_history_length];
|
||||
size_t length = {};
|
||||
const utf8_codepoint* prev = {};
|
||||
bool seen_decimal = false, seen_exponent = false;
|
||||
char first_integer_part = '\0';
|
||||
while (!is_eof() && !is_value_terminator(*cp))
|
||||
{
|
||||
if TOML_UNLIKELY(length == sizeof(chars))
|
||||
set_error_and_return_default("exceeds maximum length of "sv,
|
||||
static_cast<uint64_t>(sizeof(chars)),
|
||||
" characters"sv,
|
||||
(seen_exponent ? ""sv : " (consider using exponent notation)"sv));
|
||||
|
||||
if (*cp == U'_')
|
||||
{
|
||||
if (!prev || !is_decimal_digit(*prev))
|
||||
@ -12435,11 +12828,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
else
|
||||
set_error_and_return_default("expected decimal digit, saw '"sv, to_sv(*cp), "'"sv);
|
||||
|
||||
if (length == sizeof(chars))
|
||||
set_error_and_return_default("exceeds maximum length of "sv,
|
||||
static_cast<uint64_t>(sizeof(chars)),
|
||||
" characters"sv);
|
||||
|
||||
chars[length++] = static_cast<char>(cp->bytes[0]);
|
||||
prev = cp;
|
||||
advance_and_return_if_error({});
|
||||
@ -12467,6 +12855,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
auto fc_result = std::from_chars(chars, chars + length, result);
|
||||
switch (fc_result.ec)
|
||||
{
|
||||
TOML_LIKELY_CASE
|
||||
case std::errc{}: // ok
|
||||
return result * sign;
|
||||
|
||||
@ -12719,7 +13108,9 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
|
||||
// consume value chars
|
||||
char chars[traits::buffer_length];
|
||||
static constexpr size_t underscore_padding = 32;
|
||||
static constexpr size_t buffer_length = traits::min_buffer_length + underscore_padding;
|
||||
char chars[buffer_length];
|
||||
size_t length = {};
|
||||
const utf8_codepoint* prev = {};
|
||||
while (!is_eof() && !is_value_terminator(*cp))
|
||||
@ -13224,7 +13615,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
advance_count++;
|
||||
eof_while_scanning = is_eof();
|
||||
}
|
||||
while (advance_count < utf8_buffered_reader::max_history_length && !is_eof()
|
||||
while (advance_count < (utf8_buffered_reader::max_history_length - 1u) && !is_eof()
|
||||
&& !is_value_terminator(*cp));
|
||||
};
|
||||
scan();
|
||||
@ -13273,8 +13664,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
|
||||
// set the reader back to where we started
|
||||
go_back(advance_count);
|
||||
if (char_count < utf8_buffered_reader::max_history_length - 1u)
|
||||
chars[char_count] = U'\0';
|
||||
|
||||
// if after scanning ahead we still only have one value character,
|
||||
// the only valid value type is an integer.
|
||||
@ -13380,7 +13769,23 @@ TOML_IMPL_NAMESPACE_START
|
||||
case bzero_msk: [[fallthrough]];
|
||||
case bdigit_msk: [[fallthrough]];
|
||||
case begins_sign | has_digits | has_minus: [[fallthrough]];
|
||||
case begins_sign | has_digits | has_plus: val.reset(new value{ parse_integer<10>() }); break;
|
||||
case begins_sign | has_digits | has_plus:
|
||||
{
|
||||
// if the value was so long we exhausted the history buffer it's reasonable to assume
|
||||
// there was more and the value's actual type is impossible to identify without making the
|
||||
// buffer bigger (since it could have actually been a float), so emit an error.
|
||||
//
|
||||
// (this will likely only come up during fuzzing and similar scenarios)
|
||||
static constexpr size_t max_numeric_value_length =
|
||||
utf8_buffered_reader::max_history_length - 2u;
|
||||
if TOML_UNLIKELY(!eof_while_scanning && advance_count > max_numeric_value_length)
|
||||
set_error_and_return_default("numeric value too long to identify type - cannot exceed "sv,
|
||||
max_numeric_value_length,
|
||||
" characters"sv);
|
||||
|
||||
val.reset(new value{ parse_integer<10>() });
|
||||
break;
|
||||
}
|
||||
|
||||
// hexadecimal integers
|
||||
// 0x10
|
||||
@ -13538,17 +13943,6 @@ TOML_IMPL_NAMESPACE_START
|
||||
return_after_error({});
|
||||
}
|
||||
|
||||
#if !TOML_LANG_AT_LEAST(1, 0, 0) // toml/issues/665 (heterogeneous arrays)
|
||||
{
|
||||
if (auto arr = val->as_array(); arr && !arr->is_homogeneous())
|
||||
{
|
||||
delete arr;
|
||||
set_error_at(begin_pos, "arrays cannot contain values of different types before TOML 1.0.0"sv);
|
||||
return_after_error({});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
val->source_ = { begin_pos, current_position(1), reader.source_path() };
|
||||
return val;
|
||||
}
|
||||
@ -14556,7 +14950,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
case '\'': traits |= formatted_string_traits::single_quotes; break;
|
||||
default:
|
||||
{
|
||||
if (is_control_character(c))
|
||||
if TOML_UNLIKELY(is_control_character(c))
|
||||
traits |= formatted_string_traits::control_chars;
|
||||
|
||||
if (!is_ascii_bare_key_character(static_cast<char32_t>(c)))
|
||||
@ -14607,7 +15001,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
case U'\'': traits |= formatted_string_traits::single_quotes; break;
|
||||
default:
|
||||
{
|
||||
if (is_control_character(decoder.codepoint)
|
||||
if TOML_UNLIKELY(is_control_character(decoder.codepoint)
|
||||
|| is_non_ascii_vertical_whitespace(decoder.codepoint))
|
||||
traits |= formatted_string_traits::control_chars;
|
||||
|
||||
@ -15625,6 +16019,7 @@ TOML_POP_WARNINGS;
|
||||
#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
|
||||
@ -15671,6 +16066,7 @@ TOML_POP_WARNINGS;
|
||||
#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
|
||||
@ -15705,6 +16101,7 @@ TOML_POP_WARNINGS;
|
||||
#undef TOML_TRIVIAL_ABI
|
||||
#undef TOML_UINT128
|
||||
#undef TOML_UNLIKELY
|
||||
#undef TOML_UNLIKELY_CASE
|
||||
#undef TOML_UNREACHABLE
|
||||
#undef TOML_UNUSED
|
||||
#endif
|
||||
|
@ -82,10 +82,14 @@ def make_string_literal(val, escape_all = False, escape_any = False):
|
||||
buf.write(r'\"')
|
||||
elif c_ord == 0x5C: # \
|
||||
buf.write(r'\\')
|
||||
elif c_ord == 0x0D: # \r
|
||||
buf.write(r'\r')
|
||||
elif c_ord == 0x0A: # \n
|
||||
buf.write('\\n"\n\t\t"')
|
||||
elif c_ord == 0x0B: # \v
|
||||
buf.write(r'\v')
|
||||
elif c_ord == 0x0C: # \f
|
||||
buf.write(r'\f')
|
||||
elif c_ord == 0x0D: # \r
|
||||
buf.write(r'\r')
|
||||
elif is_problematic_control_char(c_ord):
|
||||
if c_ord <= 0xFF:
|
||||
buf.write(rf'\x{c_ord:02X}')
|
||||
@ -105,10 +109,10 @@ def make_string_literal(val, escape_all = False, escape_any = False):
|
||||
|
||||
def python_value_to_tomlpp(val):
|
||||
if isinstance(val, str):
|
||||
if re.fullmatch(r'^[+-]?[0-9]+[eE][+-]?[0-9]+$', val, re.M):
|
||||
return str(float(val))
|
||||
elif not val:
|
||||
if not val:
|
||||
return r'""sv'
|
||||
elif re.fullmatch(r'^[+-]?[0-9]+[eE][+-]?[0-9]+$', val, re.M):
|
||||
return str(float(val))
|
||||
else:
|
||||
return rf'{make_string_literal(val, escape_any = has_problematic_control_chars(val))}sv'
|
||||
elif isinstance(val, bool):
|
||||
@ -399,6 +403,8 @@ def load_tests(source_folder, is_valid_set, ignore_list = None):
|
||||
for f,n in files:
|
||||
ignored = False
|
||||
for ignore in ignore_list:
|
||||
if ignore is None:
|
||||
continue
|
||||
if isinstance(ignore, str):
|
||||
if n == ignore:
|
||||
ignored = True
|
||||
@ -411,10 +417,7 @@ def load_tests(source_folder, is_valid_set, ignore_list = None):
|
||||
files = files_
|
||||
tests = []
|
||||
for f,n in files:
|
||||
#try:
|
||||
tests.append(TomlTest(f, n, is_valid_set))
|
||||
#except Exception as e:
|
||||
#print(rf'Error reading {f}, skipping...', file=sys.stderr)
|
||||
tests.append(TomlTest(f, n, is_valid_set))
|
||||
return tests
|
||||
|
||||
|
||||
|
@ -116,6 +116,7 @@ def main():
|
||||
<LocalDebuggerWorkingDirectory>$(ProjectDir)..\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\at_path.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_invalid.cpp" />
|
||||
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
|
||||
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
|
||||
|
Loading…
Reference in New Issue
Block a user