added array::replace() (closes #109)

also:
- minor parser cleanup
- updated conformance tests
- documentation fixes
This commit is contained in:
Mark Gillard 2021-11-06 18:59:47 +02:00
parent 16d7ba8480
commit aa645dd88c
23 changed files with 3817 additions and 3571 deletions

View File

@ -138,21 +138,21 @@ assured that I fully support it being added, and welcome [pull requests](./CONTR
A number of configurable options are exposed in the form of preprocessor `#defines` Most likely you
won't need to mess with these at all, but if you do, set them before including toml++.
| Option | Type | Default | Description |
|-----------------------------------|:--------------:|--------------------------|---------------------------------------------------------------------------------------------------------------|
| `TOML_API` | define | undefined | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). |
| `TOML_ASSERT(expr)` | function macro | `assert()` | Sets the assert function used by the library. |
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
| `TOML_ENABLE_FORMATTERS` | boolean | `1` | Enables the formatters. Set to `0` if you don't need them to improve compile times and binary size. |
| `TOML_ENABLE_PARSER` | boolean | `1` | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. |
| `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | `0` | Enables support for [unreleased TOML language features. |
| `TOML_ENABLE_WINDOWS_COMPAT` | boolean | `1` on Windows | Enables support for transparent conversion between wide and narrow strings. |
| `TOML_EXCEPTIONS` | boolean | match compiler settings | Sets whether the library uses exceptions. |
| `TOML_HEADER_ONLY` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). |
| `TOML_IMPLEMENTATION` | define | undefined | Define this to enable compilation of the library's implementation when `TOML_HEADER_ONLY` == `0`. |
| `TOML_OPTIONAL_TYPE` | type name | undefined | Overrides the `optional<T>` type used by the library if you need [something better than std::optional]. |
| `TOML_SMALL_FLOAT_TYPE` | type name | undefined | If your codebase has an additional 'small' float type (e.g. half-precision), this tells toml++ about it. |
| `TOML_SMALL_INT_TYPE` | type name | undefined | If your codebase has an additional 'small' integer type (e.g. 24-bits), this tells toml++ about it. |
| Option | Type | Description | Default |
|-----------------------------------|:--------------:|----------------------------------------------------------------------------------------------------------|------------------------|
| `TOML_API` | define | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). | undefined |
| `TOML_ASSERT(expr)` | function macro | Sets the assert function used by the library. | `assert()` |
| `TOML_CONFIG_HEADER` | string literal | Includes the given header file before the rest of the library. | undefined |
| `TOML_ENABLE_FORMATTERS` | boolean | Enables the formatters. Set to `0` if you don't need them to improve compile times and binary size. | `1` |
| `TOML_ENABLE_PARSER` | boolean | Enables the parser. Set to `0` if you don't need it to improve compile times and binary size. | `1` |
| `TOML_ENABLE_UNRELEASED_FEATURES` | boolean | Enables support for [unreleased TOML language features. | `0` |
| `TOML_ENABLE_WINDOWS_COMPAT` | boolean | Enables support for transparent conversion between wide and narrow strings. | `1` on Windows |
| `TOML_EXCEPTIONS` | boolean | Sets whether the library uses exceptions. | per compiler settings |
| `TOML_HEADER_ONLY` | boolean | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library).| `1` |
| `TOML_IMPLEMENTATION` | define | Define this to enable compilation of the library's implementation when `TOML_HEADER_ONLY` == `0`. | undefined |
| `TOML_OPTIONAL_TYPE` | type name | Overrides the `optional<T>` type used by the library if you need [something better than std::optional]. | undefined |
| `TOML_SMALL_FLOAT_TYPE` | type name | If your codebase has a custom 'small float' type (e.g. half-precision), this tells toml++ about it. | undefined |
| `TOML_SMALL_INT_TYPE` | type name | If your codebase has a custom 'small integer' type (e.g. 24-bits), this tells toml++ about it. | undefined |
> &#xFE0F; _A number of these have ABI implications; the library uses inline namespaces to prevent you from accidentally
linking incompatible combinations together._
@ -173,7 +173,7 @@ defines `TOML_LANG_MAJOR`, `TOML_LANG_MINOR` and `TOML_LANG_PATCH`.
- [#644]: Support `+` in key names
- [#671]: Local time of day format should support `09:30` as opposed to `09:30:00`
- [#687]: Relax bare key restrictions to allow additional unicode characters
- [#709]: Include an \xHH escape code sequence
- [#796]: Include an \xHH escape code sequence
> &#xFE0F; _`#define TOML_ENABLE_UNRELEASED_FEATURES 1` to enable these features (see [Configuration](#Configuration))._
@ -263,8 +263,7 @@ though you're welcome to reach out via other means. In order of likely response
[#665]: https://github.com/toml-lang/toml/issues/665
[#671]: https://github.com/toml-lang/toml/issues/671
[#687]: https://github.com/toml-lang/toml/issues/687
[#709]: https://github.com/toml-lang/toml/pull/709
[#796]: https://github.com/toml-lang/toml/pull/796
[#766]: https://github.com/toml-lang/toml/issues/766
[LICENSE-utf8-decoder]: ./LICENSE-utf8-decoder
[something better than std::optional]: https://github.com/TartanLlama/optional
[m.css]: https://mcss.mosra.cz/documentation/doxygen

View File

@ -6,8 +6,6 @@
// This example is just a short-n-shiny benchmark.
#include "examples.h"
#define TOML_ENABLE_UNRELEASED_FEATURES 0
#include <toml++/toml.h>
using namespace std::string_view_literals;
@ -50,7 +48,7 @@ int main(int argc, char** argv)
#if TOML_EXCEPTIONS
try
{
const auto result = toml::parse(file_content);
const auto result = toml::parse(file_content, file_path);
}
catch (const toml::parse_error& err)
{
@ -58,7 +56,7 @@ int main(int argc, char** argv)
return 1;
}
#else
const auto result = toml::parse(file_content);
const auto result = toml::parse(file_content, file_path);
if (!result)
std::cerr << result.error() << "\n";
return 1;
@ -67,15 +65,13 @@ int main(int argc, char** argv)
// run the benchmark
std::cout << "Parsing '"sv << file_path << "' "sv << iterations << " times...\n"sv;
std::chrono::nanoseconds cumulative;
const auto start = std::chrono::steady_clock::now();
for (size_t i = 0; i < iterations; i++)
{
const auto start = std::chrono::steady_clock::now();
const auto result = toml::parse(file_content);
cumulative += std::chrono::steady_clock::now() - start;
}
const auto cumulative_sec = std::chrono::duration_cast<std::chrono::duration<double>>(cumulative).count();
const auto mean_sec = cumulative_sec / static_cast<double>(iterations);
std::ignore = toml::parse_file(file_path);
const auto cumulative_sec =
std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - start).count();
const auto mean_sec = cumulative_sec / static_cast<double>(iterations);
std::cout << " total: "sv << cumulative_sec << " s\n"sv
<< " mean: "sv << mean_sec << " s\n"sv;

2
external/toml-test vendored

@ -1 +1 @@
Subproject commit 643fd7585441148f5d7ff6d1eb1de62292fa900f
Subproject commit 982482f73a95c65a9daf1af7d49e0845206f9111

View File

@ -4,10 +4,10 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "value.h"
#include "std_utility.h"
#include "std_vector.h"
#include "std_initializer_list.h"
#include "value.h"
#include "make_node.h"
#include "header_start.h"
@ -80,13 +80,13 @@ TOML_IMPL_NAMESPACE_START
return out;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
reference operator*() const noexcept
{
return *raw_->get();
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
pointer operator->() const noexcept
{
return raw_->get();
@ -122,49 +122,49 @@ TOML_IMPL_NAMESPACE_START
return { lhs.raw_ - rhs };
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ - rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ == rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ != rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ < rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ <= rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ > rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ >= rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
reference operator[](ptrdiff_t idx) const noexcept
{
return *(raw_ + idx)->get();
@ -330,7 +330,6 @@ TOML_NAMESPACE_START
/// \detail \cpp
/// auto arr = toml::array{ 1, 2.0, "three"sv, toml::array{ 4, 5 } };
/// std::cout << arr << "\n";
///
/// \ecpp
///
/// \out
@ -976,6 +975,49 @@ TOML_NAMESPACE_START
return { elems_.emplace(pos.raw_, new impl::wrap_node<type>{ static_cast<Args&&>(args)... }) };
}
/// \brief Replaces the element at a specific position in the array with a different value.
///
/// \detail \cpp
/// auto arr = toml::array{ 1, 2, 3 };
/// std::cout << arr << "\n";
/// arr.replace(arr.cbegin() + 1, "two");
/// std::cout << arr << "\n";
/// \ecpp
///
/// \out
/// [ 1, 2, 3 ]
/// [ 1, 'two', 3 ]
/// \eout
///
/// \tparam ElemType toml::node, toml::node_view, toml::table, toml::array, or a native TOML value type
/// (or a type promotable to one).
/// \param pos The insertion position.
/// \param val The node or value being inserted.
/// \param flags Value flags to apply to new values.
///
/// \returns \conditional_return{Valid input}
/// An iterator to the replaced element.
/// \conditional_return{Input is an empty toml::node_view}
/// end()
///
/// \attention The return value will always be `end()` if the input value was an empty toml::node_view,
/// because no replacement can take place. This is the only circumstance in which this can occur.
template <typename ElemType>
iterator replace(const_iterator pos, ElemType&& val, value_flags flags = preserve_source_value_flags)
{
TOML_ASSERT(pos >= cbegin() && pos < cend());
if constexpr (is_node_view<ElemType>)
{
if (!val)
return end();
}
const auto it = elems_.begin() + (pos.raw_ - elems_.cbegin());
it->reset(impl::make_node(static_cast<ElemType&&>(val), flags));
return iterator{ it };
}
/// \brief Removes the specified element from the array.
///
/// \detail \cpp

View File

@ -4,7 +4,6 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "preprocessor.h"
#include "std_string.h"
#include "std_new.h"
TOML_DISABLE_WARNINGS;

View File

@ -4,8 +4,8 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "forward_declarations.h"
#include "std_utility.h"
#include "forward_declarations.h"
#include "source_region.h"
#include "header_start.h"

View File

@ -4,10 +4,10 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "print_to_stream.h"
#include "node.h"
#include "std_vector.h"
#include "std_initializer_list.h"
#include "print_to_stream.h"
#include "node.h"
#include "header_start.h"
TOML_DISABLE_ARITHMETIC_WARNINGS;

View File

@ -12,8 +12,8 @@
//# }}
#if TOML_ENABLE_PARSER
#include "parser.h"
#include "std_optional.h"
#include "parser.h"
#include "source_region.h"
#include "parse_error.h"
#include "utf8.h"
@ -918,7 +918,7 @@ TOML_ANON_NAMESPACE_START
}
TOML_PURE_INLINE_GETTER
node* get() const noexcept
node* operator->() noexcept
{
return node_;
}
@ -1342,7 +1342,6 @@ TOML_IMPL_NAMESPACE_START
return i;
}
// template <bool MultiLine>
TOML_NODISCARD
std::string parse_basic_string(bool multi_line)
{
@ -1354,7 +1353,7 @@ TOML_IMPL_NAMESPACE_START
// skip the '"'
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
// multi-line strings ignore a single line ending right at the beginning
if (multi_line)
{
consume_line_break();
@ -1363,8 +1362,8 @@ TOML_IMPL_NAMESPACE_START
}
std::string str;
bool escaped = false;
[[maybe_unused]] bool skipping_whitespace = false;
bool escaped = false;
bool skipping_whitespace = false;
do
{
if (escaped)
@ -1398,7 +1397,7 @@ TOML_IMPL_NAMESPACE_START
// unicode scalar sequences
case U'x':
#if TOML_LANG_UNRELEASED // toml/pull/709 (\xHH unicode scalar sequences)
#if TOML_LANG_UNRELEASED // toml/pull/796 (\xHH unicode scalar sequences)
[[fallthrough]];
#else
set_error_and_return_default(
@ -1578,7 +1577,7 @@ TOML_IMPL_NAMESPACE_START
// skip the delimiter
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
// multi-line strings ignore a single line ending right at the beginning
if (multi_line)
{
consume_line_break();
@ -2755,7 +2754,7 @@ TOML_IMPL_NAMESPACE_START
return_if_error({});
val = new value{ i };
reinterpret_cast<value<int64_t>*>(val.get())->flags(flags);
val->ref_cast<int64_t>().flags(flags);
}
else if (has_any(has_e) || (has_any(begins_zero | begins_digit) && chars[1] == U'.'))
val = new value{ parse_float() };
@ -2793,14 +2792,14 @@ TOML_IMPL_NAMESPACE_START
// 0b10
case bzero_msk | has_b:
val = new value{ parse_integer<2>() };
reinterpret_cast<value<int64_t>*>(val.get())->flags(value_flags::format_as_binary);
val->ref_cast<int64_t>().flags(value_flags::format_as_binary);
break;
// octal integers
// 0o10
case bzero_msk | has_o:
val = new value{ parse_integer<8>() };
reinterpret_cast<value<int64_t>*>(val.get())->flags(value_flags::format_as_octal);
val->ref_cast<int64_t>().flags(value_flags::format_as_octal);
break;
// decimal integers
@ -2817,7 +2816,7 @@ TOML_IMPL_NAMESPACE_START
// 0x10
case bzero_msk | has_x:
val = new value{ parse_integer<16>() };
reinterpret_cast<value<int64_t>*>(val.get())->flags(value_flags::format_as_hexadecimal);
val->ref_cast<int64_t>().flags(value_flags::format_as_hexadecimal);
break;
// decimal floats
@ -2980,7 +2979,7 @@ TOML_IMPL_NAMESPACE_START
}
#endif
val.get()->source_ = { begin_pos, current_position(1), reader.source_path() };
val->source_ = { begin_pos, current_position(1), reader.source_path() };
return val.release();
}
@ -3187,7 +3186,7 @@ TOML_IMPL_NAMESPACE_START
// the spec dictates we select the most recently declared element in the array.
TOML_ASSERT(!child->ref_cast<array>().elems_.empty());
TOML_ASSERT(child->ref_cast<array>().elems_.back()->is_table());
parent = &child->ref_cast<array>().elems_.back()->ref_cast<table>();
parent = &child->ref_cast<array>().back().ref_cast<table>();
}
else
{
@ -3215,22 +3214,21 @@ TOML_IMPL_NAMESPACE_START
// set the starting regions, and return the table element
if (is_arr)
{
auto tab_arr =
&parent->map_.emplace(key.segments.back(), new array{}).first->second->ref_cast<array>();
table_arrays.push_back(tab_arr);
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
array& tbl_arr = parent->emplace<array>(key.segments.back()).first->second.ref_cast<array>();
table_arrays.push_back(&tbl_arr);
tbl_arr.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
tab_arr->elems_.emplace_back(new table{});
tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elems_.back()->ref_cast<table>();
table& tbl = tbl_arr.emplace_back<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
// otherwise we're just making a table
else
{
auto tab = &parent->map_.emplace(key.segments.back(), new table{}).first->second->ref_cast<table>();
tab->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return tab;
table& tbl = parent->emplace<table>(key.segments.back()).first->second.ref_cast<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
}
@ -3243,22 +3241,21 @@ TOML_IMPL_NAMESPACE_START
if (is_arr && matching_node->is_array()
&& impl::find(table_arrays.begin(), table_arrays.end(), &matching_node->ref_cast<array>()))
{
auto tab_arr = &matching_node->ref_cast<array>();
tab_arr->elems_.emplace_back(new table{});
tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elems_.back()->ref_cast<table>();
table& tbl = matching_node->ref_cast<array>().emplace_back<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
else if (!is_arr && matching_node->is_table() && !implicit_tables.empty())
{
auto tbl = &matching_node->ref_cast<table>();
if (auto found = impl::find(implicit_tables.begin(), implicit_tables.end(), tbl);
found && (tbl->empty() || tbl->is_homogeneous<table>()))
table& tbl = matching_node->ref_cast<table>();
if (auto found = impl::find(implicit_tables.begin(), implicit_tables.end(), &tbl);
found && (tbl.empty() || tbl.is_homogeneous<table>()))
{
implicit_tables.erase(implicit_tables.cbegin() + (found - implicit_tables.data()));
tbl->source_.begin = header_begin_pos;
tbl->source_.end = header_end_pos;
return tbl;
tbl.source_.begin = header_begin_pos;
tbl.source_.end = header_end_pos;
return &tbl;
}
}
@ -3307,7 +3304,7 @@ TOML_IMPL_NAMESPACE_START
{
child = tab->map_.emplace(std::move(kvp.key.segments[i]), new table{}).first->second.get();
dotted_key_tables.push_back(&child->ref_cast<table>());
child->source_ = kvp.value.get()->source_;
child->source_ = kvp.value->source_;
}
else if (!child->is_table()
|| !(impl::find(dotted_key_tables.begin(),
@ -3321,7 +3318,7 @@ TOML_IMPL_NAMESPACE_START
to_sv(child->type()),
" as dotted key-value pair"sv);
else
child->source_.end = kvp.value.get()->source_.end;
child->source_.end = kvp.value->source_.end;
return_if_error();
tab = &child->ref_cast<table>();
@ -3330,7 +3327,7 @@ TOML_IMPL_NAMESPACE_START
if (auto conflicting_node = tab->get(kvp.key.segments.back()))
{
if (conflicting_node->type() == kvp.value.get()->type())
if (conflicting_node->type() == kvp.value->type())
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
@ -3342,7 +3339,7 @@ TOML_IMPL_NAMESPACE_START
" '"sv,
to_sv(recording_buffer),
"' as "sv,
to_sv(kvp.value.get()->type()));
to_sv(kvp.value->type()));
}
return_if_error();
@ -3408,8 +3405,7 @@ TOML_IMPL_NAMESPACE_START
if (type == node_type::table)
{
auto& tbl = nde.ref_cast<table>();
if (tbl.inline_) // inline tables (and all their inline descendants) are already correctly
// terminated
if (tbl.inline_) // inline tables (and all their inline descendants) are already correctly terminated
return;
auto end = nde.source_.end;
@ -3425,11 +3421,11 @@ TOML_IMPL_NAMESPACE_START
{
auto& arr = nde.ref_cast<array>();
auto end = nde.source_.end;
for (auto& v : arr.elems_)
for (auto& v : arr)
{
update_region_ends(*v);
if (end < v->source_.end)
end = v->source_.end;
update_region_ends(v);
if (end < v.source_.end)
end = v.source_.end;
}
nde.source_.end = end;
}
@ -3488,8 +3484,8 @@ TOML_IMPL_NAMESPACE_START
// skip opening '['
advance_and_return_if_error_or_eof({});
node_ptr arr{ new array{} };
auto& vals = reinterpret_cast<array*>(arr.get())->elems_;
node_ptr arr_ptr{ new array{} };
array& arr = arr_ptr->ref_cast<array>();
enum parse_elem : int
{
none,
@ -3532,14 +3528,14 @@ TOML_IMPL_NAMESPACE_START
continue;
}
prev = val;
if (!vals.capacity())
vals.reserve(4u);
vals.emplace_back(parse_value());
if (!arr.capacity())
arr.reserve(4u);
arr.elems_.emplace_back(parse_value());
}
}
return_if_error({});
return reinterpret_cast<array*>(arr.release());
return reinterpret_cast<array*>(arr_ptr.release());
}
TOML_EXTERNAL_LINKAGE
@ -3553,8 +3549,9 @@ TOML_IMPL_NAMESPACE_START
// skip opening '{'
advance_and_return_if_error_or_eof({});
node_ptr tab{ new table{} };
reinterpret_cast<table*>(tab.get())->inline_ = true;
node_ptr tbl_ptr{ new table{} };
table& tbl = tbl_ptr->ref_cast<table>();
tbl.inline_ = true;
enum parse_elem : int
{
none,
@ -3613,7 +3610,7 @@ TOML_IMPL_NAMESPACE_START
else
{
prev = kvp;
parse_key_value_pair_and_insert(reinterpret_cast<table*>(tab.get()));
parse_key_value_pair_and_insert(&tbl);
}
}
@ -3623,7 +3620,7 @@ TOML_IMPL_NAMESPACE_START
}
return_if_error({});
return reinterpret_cast<table*>(tab.release());
return reinterpret_cast<table*>(tbl_ptr.release());
}
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS

View File

@ -72,7 +72,16 @@
_Pragma("clang diagnostic ignored \"-Wshift-sign-overflow\"") \
static_assert(true)
#if TOML_CLANG >= 10
#define TOML_DISABLE_SPAM_WARNINGS_CLANG_10 \
_Pragma("clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"") \
static_assert(true)
#else
#define TOML_DISABLE_SPAM_WARNINGS_CLANG_10 static_assert(true)
#endif
#define TOML_DISABLE_SPAM_WARNINGS \
TOML_DISABLE_SPAM_WARNINGS_CLANG_10; \
_Pragma("clang diagnostic ignored \"-Wweak-vtables\"") \
_Pragma("clang diagnostic ignored \"-Wweak-template-vtables\"") \
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"") \

View File

@ -4,8 +4,8 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "forward_declarations.h"
#include "std_string.h"
#include "forward_declarations.h"
#include "header_start.h"
TOML_IMPL_NAMESPACE_START

View File

@ -4,9 +4,9 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "forward_declarations.h"
#include "std_optional.h"
#include "std_string.h"
#include "forward_declarations.h"
#include "print_to_stream.h"
#include "header_start.h"

View File

@ -4,10 +4,10 @@
// SPDX-License-Identifier: MIT
#pragma once
#include "array.h"
#include "make_node.h"
#include "std_map.h"
#include "std_initializer_list.h"
#include "array.h"
#include "make_node.h"
#include "node_view.h"
#include "header_start.h"
@ -116,25 +116,25 @@ TOML_IMPL_NAMESPACE_START
return out;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
reference operator*() const noexcept
{
return *get_proxy();
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
pointer operator->() const noexcept
{
return get_proxy();
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator==(const table_iterator& lhs, const table_iterator& rhs) noexcept
{
return lhs.raw_ == rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator!=(const table_iterator& lhs, const table_iterator& rhs) noexcept
{
return lhs.raw_ != rhs.raw_;

View File

@ -7,8 +7,8 @@
#include "preprocessor.h"
#if TOML_ENABLE_FORMATTERS
#include "formatter.h"
#include "std_vector.h"
#include "formatter.h"
#include "header_start.h"
TOML_NAMESPACE_START

View File

@ -89,6 +89,7 @@ TOML_POP_WARNINGS;
#undef TOML_DISABLE_ARITHMETIC_WARNINGS
#undef TOML_DISABLE_CODE_ANALYSIS_WARNINGS
#undef TOML_DISABLE_SPAM_WARNINGS
#undef TOML_DISABLE_SPAM_WARNINGS_CLANG_10
#undef TOML_DISABLE_SUGGEST_ATTR_WARNINGS
#undef TOML_DISABLE_SWITCH_WARNINGS
#undef TOML_DISABLE_WARNINGS

View File

@ -4,25 +4,21 @@
// SPDX-License-Identifier: MIT
//-----
// this file was generated by generate_conformance_tests.py - do not modify it directly
// clang-format off
#include "tests.h"
using namespace toml::impl;
TOML_DISABLE_WARNINGS; // unused variable spam
namespace
{
static constexpr auto array_missing_separator = R"(wrong = [ 1 2 3 ])"sv;
static constexpr auto array_no_close_2 = R"(x = [42 #)"sv;
static constexpr auto array_no_close_table_2 = R"(x = [{ key = 42 #)"sv;
static constexpr auto array_no_close_table = R"(x = [{ key = 42)"sv;
static constexpr auto array_no_close = R"(long_array = [ 1, 2, 3)"sv;
static constexpr auto array_tables_1 = R"(# INVALID TOML DOC
static constexpr auto array_missing_separator = R"(wrong = [ 1 2 3 ])"sv;
static constexpr auto array_no_close_2 = R"(x = [42 #)"sv;
static constexpr auto array_no_close_table_2 = R"(x = [{ key = 42 #)"sv;
static constexpr auto array_no_close_table = R"(x = [{ key = 42)"sv;
static constexpr auto array_no_close = R"(long_array = [ 1, 2, 3)"sv;
static constexpr auto array_tables_1 = R"(# INVALID TOML DOC
fruit = []
[[fruit]] # Not allowed)"sv;
static constexpr auto array_tables_2 = R"(# INVALID TOML DOC
static constexpr auto array_tables_2 = R"(# INVALID TOML DOC
[[fruit]]
name = "apple"
@ -32,7 +28,7 @@ fruit = []
# This table conflicts with the previous table
[fruit.variety]
name = "granny smith")"sv;
static constexpr auto array_text_after_array_entries = R"(array = [
static constexpr auto array_text_after_array_entries = R"(array = [
"Is there life after an array separator?", No
"Entry"
])"sv;
@ -40,21 +36,21 @@ fruit = []
"Is there life before an array separator?" No,
"Entry"
])"sv;
static constexpr auto array_text_in_array = R"(array = [
static constexpr auto array_text_in_array = R"(array = [
"Entry 1",
I don't belong,
"Entry 2",
])"sv;
static constexpr auto bool_mixed_case = R"(valid = False)"sv;
static constexpr auto bool_mixed_case = R"(valid = False)"sv;
static constexpr auto bool_wrong_case_false = R"(b = FALSE)"sv;
static constexpr auto bool_wrong_case_true = R"(a = TRUE)"sv;
static constexpr auto bool_wrong_case_true = R"(a = TRUE)"sv;
static constexpr auto datetime_impossible_date = R"(d = 2006-01-50T00:00:00Z)"sv;
static constexpr auto datetime_impossible_date = R"(d = 2006-01-50T00:00:00Z)"sv;
static constexpr auto datetime_no_leads_with_milli = R"(with-milli = 1987-07-5T17:45:00.12Z)"sv;
static constexpr auto datetime_no_leads = R"(no-leads = 1987-7-05T17:45:00Z)"sv;
static constexpr auto datetime_no_t = R"(no-t = 1987-07-0517:45:00Z)"sv;
static constexpr auto datetime_trailing_t = R"(d = 2006-01-30T)"sv;
static constexpr auto datetime_no_leads = R"(no-leads = 1987-7-05T17:45:00Z)"sv;
static constexpr auto datetime_no_t = R"(no-t = 1987-07-0517:45:00Z)"sv;
static constexpr auto datetime_trailing_t = R"(d = 2006-01-30T)"sv;
#if !TOML_LANG_UNRELEASED
@ -62,48 +58,51 @@ fruit = []
#endif // !TOML_LANG_UNRELEASED
static constexpr auto float_double_point_1 = R"(double-point-1 = 0..1)"sv;
static constexpr auto float_double_point_2 = R"(double-point-2 = 0.1.2)"sv;
static constexpr auto float_exp_double_e_1 = R"(exp-double-e-1 = 1ee2)"sv;
static constexpr auto float_exp_double_e_2 = R"(exp-double-e-2 = 1e2e3)"sv;
static constexpr auto float_exp_double_us = R"(exp-double-us = 1e__23)"sv;
static constexpr auto float_exp_leading_us = R"(exp-leading-us = 1e_23)"sv;
static constexpr auto float_exp_point_1 = R"(exp-point-1 = 1e2.3)"sv;
static constexpr auto float_exp_point_2 = R"(exp-point-2 = 1.e2)"sv;
static constexpr auto float_exp_trailing_us = R"(exp-trailing-us = 1e_23_)"sv;
static constexpr auto float_inf_incomplete_1 = R"(inf-incomplete-1 = in)"sv;
static constexpr auto float_inf_incomplete_2 = R"(inf-incomplete-2 = +in)"sv;
static constexpr auto float_inf_incomplete_3 = R"(inf-incomplete-3 = -in)"sv;
static constexpr auto float_inf_underscore = R"(inf_underscore = in_f)"sv;
static constexpr auto float_leading_point_neg = R"(leading-point-neg = -.12345)"sv;
static constexpr auto float_leading_point_plus = R"(leading-point-plus = +.12345)"sv;
static constexpr auto float_leading_point = R"(leading-point = .12345)"sv;
static constexpr auto float_leading_us = R"(leading-us = _1.2)"sv;
static constexpr auto float_leading_zero_neg = R"(leading-zero-neg = -03.14)"sv;
static constexpr auto float_leading_zero_plus = R"(leading-zero-plus = +03.14)"sv;
static constexpr auto float_leading_zero = R"(leading-zero = 03.14)"sv;
static constexpr auto float_nan_incomplete_1 = R"(nan-incomplete-1 = na)"sv;
static constexpr auto float_nan_incomplete_2 = R"(nan-incomplete-2 = +na)"sv;
static constexpr auto float_nan_incomplete_3 = R"(nan-incomplete-3 = -na)"sv;
static constexpr auto float_nan_underscore = R"(nan_underscore = na_n)"sv;
static constexpr auto float_trailing_point_min = R"(trailing-point-min = -1.)"sv;
static constexpr auto float_double_point_1 = R"(double-point-1 = 0..1)"sv;
static constexpr auto float_double_point_2 = R"(double-point-2 = 0.1.2)"sv;
static constexpr auto float_exp_double_e_1 = R"(exp-double-e-1 = 1ee2)"sv;
static constexpr auto float_exp_double_e_2 = R"(exp-double-e-2 = 1e2e3)"sv;
static constexpr auto float_exp_double_us = R"(exp-double-us = 1e__23)"sv;
static constexpr auto float_exp_leading_us = R"(exp-leading-us = 1e_23)"sv;
static constexpr auto float_exp_point_1 = R"(exp-point-1 = 1e2.3)"sv;
static constexpr auto float_exp_point_2 = R"(exp-point-2 = 1.e2)"sv;
static constexpr auto float_exp_trailing_us = R"(exp-trailing-us = 1e_23_)"sv;
static constexpr auto float_inf_incomplete_1 = R"(inf-incomplete-1 = in)"sv;
static constexpr auto float_inf_incomplete_2 = R"(inf-incomplete-2 = +in)"sv;
static constexpr auto float_inf_incomplete_3 = R"(inf-incomplete-3 = -in)"sv;
static constexpr auto float_inf_underscore = R"(inf_underscore = in_f)"sv;
static constexpr auto float_leading_point_neg = R"(leading-point-neg = -.12345)"sv;
static constexpr auto float_leading_point_plus = R"(leading-point-plus = +.12345)"sv;
static constexpr auto float_leading_point = R"(leading-point = .12345)"sv;
static constexpr auto float_leading_us = R"(leading-us = _1.2)"sv;
static constexpr auto float_leading_zero_neg = R"(leading-zero-neg = -03.14)"sv;
static constexpr auto float_leading_zero_plus = R"(leading-zero-plus = +03.14)"sv;
static constexpr auto float_leading_zero = R"(leading-zero = 03.14)"sv;
static constexpr auto float_nan_incomplete_1 = R"(nan-incomplete-1 = na)"sv;
static constexpr auto float_nan_incomplete_2 = R"(nan-incomplete-2 = +na)"sv;
static constexpr auto float_nan_incomplete_3 = R"(nan-incomplete-3 = -na)"sv;
static constexpr auto float_nan_underscore = R"(nan_underscore = na_n)"sv;
static constexpr auto float_trailing_point_min = R"(trailing-point-min = -1.)"sv;
static constexpr auto float_trailing_point_plus = R"(trailing-point-plus = +1.)"sv;
static constexpr auto float_trailing_point = R"(trailing-point = 1.)"sv;
static constexpr auto float_trailing_us_exp = R"(# trailing underscore in integer part is not allowed
static constexpr auto float_trailing_point = R"(trailing-point = 1.)"sv;
static constexpr auto float_trailing_us_exp = R"(# trailing underscore in integer part is not allowed
trailing-us-exp = 1_e2
# trailing underscore in float part is not allowed
trailing-us-exp2 = 1.2_e2)"sv;
static constexpr auto float_trailing_us = R"(trailing-us = 1.2_)"sv;
static constexpr auto float_us_after_point = R"(us-after-point = 1._2)"sv;
static constexpr auto float_us_before_point = R"(us-before-point = 1_.2)"sv;
static constexpr auto float_trailing_us = R"(trailing-us = 1.2_)"sv;
static constexpr auto float_us_after_point = R"(us-after-point = 1._2)"sv;
static constexpr auto float_us_before_point = R"(us-before-point = 1_.2)"sv;
static constexpr auto inline_table_double_comma = R"(t = {x=3,,y=4})"sv;
static constexpr auto inline_table_empty = R"(t = {,})"sv;
static constexpr auto inline_table_no_comma = R"(t = {x = 3 y = 4})"sv;
static constexpr auto inline_table_double_comma = R"(t = {x=3,,y=4})"sv;
static constexpr auto inline_table_duplicate_key = R"(# Duplicate keys within an inline table are invalid
a={b=1, b=2})"sv;
static constexpr auto inline_table_empty = R"(t = {,})"sv;
static constexpr auto inline_table_no_comma = R"(t = {x = 3 y = 4})"sv;
#if !TOML_LANG_UNRELEASED
static constexpr auto inline_table_linebreak_1 = R"(# No newlines are allowed between the curly braces unless they are valid within
static constexpr auto inline_table_linebreak_1 =
R"(# No newlines are allowed between the curly braces unless they are valid within
# a value.
simple = { a = 1
})"sv;
@ -115,77 +114,78 @@ b=2})"sv;
first = "Tom",
last = "Preston-Werner"
})"sv;
static constexpr auto inline_table_trailing_comma = R"(# A terminating comma (also called trailing comma) is not permitted after the
static constexpr auto inline_table_trailing_comma =
R"(# A terminating comma (also called trailing comma) is not permitted after the
# last key/value pair in an inline table
abc = { abc = 123, })"sv;
#endif // !TOML_LANG_UNRELEASED
static constexpr auto integer_capital_bin = R"(capital-bin = 0B0)"sv;
static constexpr auto integer_capital_hex = R"(capital-hex = 0X1)"sv;
static constexpr auto integer_capital_oct = R"(capital-oct = 0O0)"sv;
static constexpr auto integer_double_sign_nex = R"(double-sign-nex = --99)"sv;
static constexpr auto integer_double_sign_plus = R"(double-sign-plus = ++99)"sv;
static constexpr auto integer_double_us = R"(double-us = 1__23)"sv;
static constexpr auto integer_invalid_bin = R"(invalid-bin = 0b0012)"sv;
static constexpr auto integer_invalid_hex = R"(invalid-hex = 0xaafz)"sv;
static constexpr auto integer_invalid_oct = R"(invalid-oct = 0o778)"sv;
static constexpr auto integer_leading_us_bin = R"(leading-us-bin = _0o1)"sv;
static constexpr auto integer_leading_us_hex = R"(leading-us-hex = _0o1)"sv;
static constexpr auto integer_leading_us_oct = R"(leading-us-oct = _0o1)"sv;
static constexpr auto integer_leading_us = R"(leading-us = _123)"sv;
static constexpr auto integer_leading_zero_1 = R"(leading-zero-1 = 01)"sv;
static constexpr auto integer_leading_zero_2 = R"(leading-zero-2 = 00)"sv;
static constexpr auto integer_capital_bin = R"(capital-bin = 0B0)"sv;
static constexpr auto integer_capital_hex = R"(capital-hex = 0X1)"sv;
static constexpr auto integer_capital_oct = R"(capital-oct = 0O0)"sv;
static constexpr auto integer_double_sign_nex = R"(double-sign-nex = --99)"sv;
static constexpr auto integer_double_sign_plus = R"(double-sign-plus = ++99)"sv;
static constexpr auto integer_double_us = R"(double-us = 1__23)"sv;
static constexpr auto integer_invalid_bin = R"(invalid-bin = 0b0012)"sv;
static constexpr auto integer_invalid_hex = R"(invalid-hex = 0xaafz)"sv;
static constexpr auto integer_invalid_oct = R"(invalid-oct = 0o778)"sv;
static constexpr auto integer_leading_us_bin = R"(leading-us-bin = _0o1)"sv;
static constexpr auto integer_leading_us_hex = R"(leading-us-hex = _0o1)"sv;
static constexpr auto integer_leading_us_oct = R"(leading-us-oct = _0o1)"sv;
static constexpr auto integer_leading_us = R"(leading-us = _123)"sv;
static constexpr auto integer_leading_zero_1 = R"(leading-zero-1 = 01)"sv;
static constexpr auto integer_leading_zero_2 = R"(leading-zero-2 = 00)"sv;
static constexpr auto integer_leading_zero_sign_1 = R"(leading-zero-sign-1 = -01)"sv;
static constexpr auto integer_leading_zero_sign_2 = R"(leading-zero-sign-2 = +01)"sv;
static constexpr auto integer_negative_bin = R"(negative-bin = -0b11010110)"sv;
static constexpr auto integer_negative_hex = R"(negative-hex = -0xff)"sv;
static constexpr auto integer_negative_oct = R"(negative-oct = -0o99)"sv;
static constexpr auto integer_positive_bin = R"(positive-bin = +0b11010110)"sv;
static constexpr auto integer_positive_hex = R"(positive-hex = +0xff)"sv;
static constexpr auto integer_positive_oct = R"(positive-oct = +0o99)"sv;
static constexpr auto integer_text_after_integer = R"(answer = 42 the ultimate answer?)"sv;
static constexpr auto integer_trailing_us_bin = R"(trailing-us-bin = 0b1_)"sv;
static constexpr auto integer_trailing_us_hex = R"(trailing-us-hex = 0x1_)"sv;
static constexpr auto integer_trailing_us_oct = R"(trailing-us-oct = 0o1_)"sv;
static constexpr auto integer_trailing_us = R"(trailing-us = 123_)"sv;
static constexpr auto integer_us_after_bin = R"(us-after-bin = 0b_1)"sv;
static constexpr auto integer_us_after_hex = R"(us-after-hex = 0x_1)"sv;
static constexpr auto integer_us_after_oct = R"(us-after-oct = 0o_1)"sv;
static constexpr auto integer_negative_bin = R"(negative-bin = -0b11010110)"sv;
static constexpr auto integer_negative_hex = R"(negative-hex = -0xff)"sv;
static constexpr auto integer_negative_oct = R"(negative-oct = -0o99)"sv;
static constexpr auto integer_positive_bin = R"(positive-bin = +0b11010110)"sv;
static constexpr auto integer_positive_hex = R"(positive-hex = +0xff)"sv;
static constexpr auto integer_positive_oct = R"(positive-oct = +0o99)"sv;
static constexpr auto integer_text_after_integer = R"(answer = 42 the ultimate answer?)"sv;
static constexpr auto integer_trailing_us_bin = R"(trailing-us-bin = 0b1_)"sv;
static constexpr auto integer_trailing_us_hex = R"(trailing-us-hex = 0x1_)"sv;
static constexpr auto integer_trailing_us_oct = R"(trailing-us-oct = 0o1_)"sv;
static constexpr auto integer_trailing_us = R"(trailing-us = 123_)"sv;
static constexpr auto integer_us_after_bin = R"(us-after-bin = 0b_1)"sv;
static constexpr auto integer_us_after_hex = R"(us-after-hex = 0x_1)"sv;
static constexpr auto integer_us_after_oct = R"(us-after-oct = 0o_1)"sv;
static constexpr auto key_after_array = R"([[agencies]] owner = "S Cjelli")"sv;
static constexpr auto key_after_table = R"([error] this = "should not be here")"sv;
static constexpr auto key_after_value = R"(first = "Tom" last = "Preston-Werner" # INVALID)"sv;
static constexpr auto key_after_array = R"([[agencies]] owner = "S Cjelli")"sv;
static constexpr auto key_after_table = R"([error] this = "should not be here")"sv;
static constexpr auto key_after_value = R"(first = "Tom" last = "Preston-Werner" # INVALID)"sv;
static constexpr auto key_bare_invalid_character = R"(bare!key = 123)"sv;
static constexpr auto key_dotted_redefine_table = R"(# Defined a.b as int
static constexpr auto key_dotted_redefine_table = R"(# Defined a.b as int
a.b = 1
# Tries to access it as table: error
a.b.c = 2)"sv;
static constexpr auto key_duplicate_keys = R"(dupe = false
static constexpr auto key_duplicate_keys = R"(dupe = false
dupe = true)"sv;
static constexpr auto key_duplicate = R"(# DO NOT DO THIS
static constexpr auto key_duplicate = R"(# DO NOT DO THIS
name = "Tom"
name = "Pradyun")"sv;
static constexpr auto key_empty = R"(= 1)"sv;
static constexpr auto key_escape = R"(\u00c0 = "latin capital letter A with grave")"sv;
static constexpr auto key_hash = R"(a# = 1)"sv;
static constexpr auto key_multiline = R"("""long
static constexpr auto key_empty = R"(= 1)"sv;
static constexpr auto key_escape = R"(\u00c0 = "latin capital letter A with grave")"sv;
static constexpr auto key_hash = R"(a# = 1)"sv;
static constexpr auto key_multiline = R"("""long
key""" = 1)"sv;
static constexpr auto key_newline = R"(barekey
static constexpr auto key_newline = R"(barekey
= 123)"sv;
static constexpr auto key_no_eol = R"(a = 1 b = 2)"sv;
static constexpr auto key_open_bracket = R"([abc = 1)"sv;
static constexpr auto key_partial_quoted = R"(partial"quoted" = 5)"sv;
static constexpr auto key_single_open_bracket = R"([)"sv;
static constexpr auto key_space = R"(a b = 1)"sv;
static constexpr auto key_start_bracket = R"([a]
static constexpr auto key_no_eol = R"(a = 1 b = 2)"sv;
static constexpr auto key_open_bracket = R"([abc = 1)"sv;
static constexpr auto key_partial_quoted = R"(partial"quoted" = 5)"sv;
static constexpr auto key_single_open_bracket = R"([)"sv;
static constexpr auto key_space = R"(a b = 1)"sv;
static constexpr auto key_start_bracket = R"([a]
[xyz = 5
[b])"sv;
static constexpr auto key_two_equals = R"(key= = 1)"sv;
static constexpr auto key_two_equals2 = R"(a==1)"sv;
static constexpr auto key_two_equals3 = R"(a=b=1)"sv;
static constexpr auto key_without_value_1 = R"(key)"sv;
static constexpr auto key_without_value_2 = R"(key =)"sv;
static constexpr auto key_two_equals = R"(key= = 1)"sv;
static constexpr auto key_two_equals2 = R"(a==1)"sv;
static constexpr auto key_two_equals3 = R"(a=b=1)"sv;
static constexpr auto key_without_value_1 = R"(key)"sv;
static constexpr auto key_without_value_2 = R"(key =)"sv;
#if !TOML_LANG_UNRELEASED && UNICODE_LITERALS_OK
@ -194,34 +194,36 @@ key""" = 1)"sv;
#endif // !TOML_LANG_UNRELEASED && UNICODE_LITERALS_OK
static constexpr auto string_bad_byte_escape = R"(naughty = "\xAg")"sv;
static constexpr auto string_bad_codepoint = R"(invalid-codepoint = "This string contains a non scalar unicode codepoint \uD801")"sv;
static constexpr auto string_bad_concat = R"(no_concat = "first" "second")"sv;
static constexpr auto string_bad_escape = R"(invalid-escape = "This string has a bad \a escape character.")"sv;
static constexpr auto string_bad_codepoint =
R"(invalid-codepoint = "This string contains a non scalar unicode codepoint \uD801")"sv;
static constexpr auto string_bad_concat = R"(no_concat = "first" "second")"sv;
static constexpr auto string_bad_escape = R"(invalid-escape = "This string has a bad \a escape character.")"sv;
static constexpr auto string_bad_multiline = R"(multi = "first line
second line")"sv;
static constexpr auto string_bad_slash_escape = R"(invalid-escape = "This string has a bad \/ escape character.")"sv;
static constexpr auto string_bad_uni_esc = R"(str = "val\ue")"sv;
static constexpr auto string_bad_slash_escape =
R"(invalid-escape = "This string has a bad \/ escape character.")"sv;
static constexpr auto string_bad_uni_esc = R"(str = "val\ue")"sv;
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_1 = R"(a = """\UFFFFFFFF""")"sv;
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_2 = R"(a = """\U00D80000""")"sv;
static constexpr auto string_basic_multiline_quotes = R"(str5 = """Here are three quotation marks: """.""")"sv;
static constexpr auto string_basic_multiline_unknown_escape = R"(a = """\@""")"sv;
static constexpr auto string_basic_multiline_unknown_escape = R"(a = """\@""")"sv;
static constexpr auto string_basic_out_of_range_unicode_escape_1 = R"(a = "\UFFFFFFFF")"sv;
static constexpr auto string_basic_out_of_range_unicode_escape_2 = R"(a = "\U00D80000")"sv;
static constexpr auto string_basic_unknown_escape = R"(a = "\@")"sv;
static constexpr auto string_literal_multiline_quotes_1 = R"(a = '''6 apostrophes: '''''')"sv;
static constexpr auto string_literal_multiline_quotes_2 = R"(a = '''15 apostrophes: '''''''''''''''''')"sv;
static constexpr auto string_missing_quotes = R"(name = value)"sv;
static constexpr auto string_multiline_escape_space = R"(a = """
static constexpr auto string_basic_unknown_escape = R"(a = "\@")"sv;
static constexpr auto string_literal_multiline_quotes_1 = R"(a = '''6 apostrophes: '''''')"sv;
static constexpr auto string_literal_multiline_quotes_2 = R"(a = '''15 apostrophes: '''''''''''''''''')"sv;
static constexpr auto string_missing_quotes = R"(name = value)"sv;
static constexpr auto string_multiline_escape_space = R"(a = """
foo \ \n
bar""")"sv;
static constexpr auto string_multiline_no_close_2 = R"(x=""")"sv;
static constexpr auto string_multiline_no_close = R"(invalid = """
static constexpr auto string_multiline_no_close_2 = R"(x=""")"sv;
static constexpr auto string_multiline_no_close = R"(invalid = """
this will fail)"sv;
static constexpr auto string_multiline_quotes_1 = R"(a = """6 quotes: """""")"sv;
static constexpr auto string_multiline_quotes_2 = R"(a = """6 quotes: """""")"sv;
static constexpr auto string_no_close = R"(no-ending-quote = "One time, at band camp)"sv;
static constexpr auto string_multiline_quotes_1 = R"(a = """6 quotes: """""")"sv;
static constexpr auto string_multiline_quotes_2 = R"(a = """6 quotes: """""")"sv;
static constexpr auto string_no_close = R"(no-ending-quote = "One time, at band camp)"sv;
static constexpr auto string_text_after_string = R"(string = "Is there life after strings?" No.)"sv;
static constexpr auto string_wrong_close = R"(bad-ending-quote = "double and single')"sv;
static constexpr auto string_wrong_close = R"(bad-ending-quote = "double and single')"sv;
#if !TOML_LANG_UNRELEASED
@ -231,7 +233,8 @@ second line")"sv;
static constexpr auto table_array_empty = R"([[]]
name = "Born to Run")"sv;
static constexpr auto table_array_implicit = R"(# This test is a bit tricky. It should fail because the first use of
static constexpr auto table_array_implicit =
R"(# This test is a bit tricky. It should fail because the first use of
# `[[albums.songs]]` without first declaring `albums` implies that `albums`
# must be a table. The alternative would be quite weird. Namely, it wouldn't
# comply with the TOML spec: "Each double-bracketed sub-table will belong to
@ -245,59 +248,57 @@ name = "Glory Days"
[[albums]]
name = "Born in the USA")"sv;
static constexpr auto table_array_missing_bracket = R"([[albums]
static constexpr auto table_array_missing_bracket = R"([[albums]
name = "Born to Run")"sv;
static constexpr auto table_duplicate_key_table = R"([fruit]
static constexpr auto table_duplicate_key_table = R"([fruit]
type = "apple"
[fruit.type]
apple = "yes")"sv;
static constexpr auto table_duplicate_table_array = R"([tbl]
static constexpr auto table_duplicate_table_array = R"([tbl]
[[tbl]])"sv;
static constexpr auto table_duplicate_table_array2 = R"([[tbl]]
[tbl])"sv;
static constexpr auto table_duplicate = R"([a]
static constexpr auto table_duplicate = R"([a]
b = 1
[a]
c = 2)"sv;
static constexpr auto table_empty_implicit_table = R"([naughty..naughty])"sv;
static constexpr auto table_empty = R"([])"sv;
static constexpr auto table_equals_sign = R"([name=bad])"sv;
static constexpr auto table_injection_1 = R"([a.b.c]
static constexpr auto table_empty_implicit_table = R"([naughty..naughty])"sv;
static constexpr auto table_empty = R"([])"sv;
static constexpr auto table_equals_sign = R"([name=bad])"sv;
static constexpr auto table_injection_1 = R"([a.b.c]
z = 9
[a]
b.c.t = "Using dotted keys to add to [a.b.c] after explicitly defining it above is not allowed"
# see https://github.com/toml-lang/toml/issues/846)"sv;
static constexpr auto table_injection_2 = R"([a.b.c.d]
static constexpr auto table_injection_2 = R"([a.b.c.d]
z = 9
[a]
b.c.d.k.t = "Using dotted keys to add to [a.b.c.d] after explicitly defining it above is not allowed"
# see https://github.com/toml-lang/toml/issues/846)"sv;
static constexpr auto table_llbrace = R"([ [table]])"sv;
static constexpr auto table_nested_brackets_close = R"([a]b]
static constexpr auto table_llbrace = R"([ [table]])"sv;
static constexpr auto table_nested_brackets_close = R"([a]b]
zyx = 42)"sv;
static constexpr auto table_nested_brackets_open = R"([a[b]
static constexpr auto table_nested_brackets_open = R"([a[b]
zyx = 42)"sv;
static constexpr auto table_quoted_no_close = R"(["where will it end]
static constexpr auto table_quoted_no_close = R"(["where will it end]
name = value)"sv;
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
[a]
b = 1
[a.b]
c = 2)"sv;
static constexpr auto table_rrbrace = R"([[table] ])"sv;
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
static constexpr auto table_whitespace = R"([invalid key])"sv;
static constexpr auto table_with_pound = R"([key#group]
static constexpr auto table_rrbrace = R"([[table] ])"sv;
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
static constexpr auto table_whitespace = R"([invalid key])"sv;
static constexpr auto table_with_pound = R"([key#group]
answer = 42)"sv;
}
TOML_ENABLE_WARNINGS;
TEST_CASE("conformance - burntsushi/invalid")
{
parsing_should_fail(FILE_LINE_ARGS, array_missing_separator); // array-missing-separator
@ -406,6 +407,8 @@ TEST_CASE("conformance - burntsushi/invalid")
parsing_should_fail(FILE_LINE_ARGS, inline_table_double_comma); // inline-table-double-comma
parsing_should_fail(FILE_LINE_ARGS, inline_table_duplicate_key); // inline-table-duplicate-key
parsing_should_fail(FILE_LINE_ARGS, inline_table_empty); // inline-table-empty
parsing_should_fail(FILE_LINE_ARGS, inline_table_no_comma); // inline-table-no-comma
@ -552,17 +555,23 @@ TEST_CASE("conformance - burntsushi/invalid")
parsing_should_fail(FILE_LINE_ARGS, string_bad_uni_esc); // string-bad-uni-esc
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
parsing_should_fail(
FILE_LINE_ARGS,
string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
parsing_should_fail(
FILE_LINE_ARGS,
string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_quotes); // string-basic-multiline-quotes
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_unknown_escape); // string-basic-multiline-unknown-escape
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
parsing_should_fail(FILE_LINE_ARGS,
string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
parsing_should_fail(FILE_LINE_ARGS,
string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
parsing_should_fail(FILE_LINE_ARGS, string_basic_unknown_escape); // string-basic-unknown-escape
@ -636,4 +645,3 @@ TEST_CASE("conformance - burntsushi/invalid")
parsing_should_fail(FILE_LINE_ARGS, table_with_pound); // table-with-pound
}

File diff suppressed because it is too large Load Diff

View File

@ -4,12 +4,8 @@
// SPDX-License-Identifier: MIT
//-----
// this file was generated by generate_conformance_tests.py - do not modify it directly
// clang-format off
#include "tests.h"
using namespace toml::impl;
TOML_DISABLE_WARNINGS; // unused variable spam
namespace
{
@ -46,7 +42,7 @@ type = { edible = false } # INVALID)"sv;
#endif // !TOML_LANG_UNRELEASED
static constexpr auto int_0_padded = R"(int = 0123)"sv;
static constexpr auto int_0_padded = R"(int = 0123)"sv;
static constexpr auto int_signed_bin = R"(bin = +0b10)"sv;
static constexpr auto int_signed_hex = R"(hex = +0xab)"sv;
static constexpr auto int_signed_oct = R"(oct = +0o23)"sv;
@ -62,23 +58,24 @@ fruit.apple = 1
# But then this treats fruit.apple like it's a table.
# You can't turn an integer into a table.
fruit.apple.smooth = true)"sv;
static constexpr auto multiple_key = R"(# DO NOT DO THIS
static constexpr auto multiple_key = R"(# DO NOT DO THIS
name = "Tom"
name = "Pradyun")"sv;
static constexpr auto no_key_name = R"(= "no key name" # INVALID)"sv;
static constexpr auto string_basic_multiline_invalid_backslash = R"(a = """
static constexpr auto string_basic_multiline_invalid_backslash = R"(a = """
foo \ \n
bar""")"sv;
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_1 = R"(a = """\UFFFFFFFF""")"sv;
static constexpr auto string_basic_multiline_out_of_range_unicode_escape_2 = R"(a = """\U00D80000""")"sv;
static constexpr auto string_basic_multiline_quotes = R"(str5 = """Here are three quotation marks: """.""")"sv;
static constexpr auto string_basic_multiline_unknown_escape = R"(a = """\@""")"sv;
static constexpr auto string_basic_multiline_unknown_escape = R"(a = """\@""")"sv;
static constexpr auto string_basic_out_of_range_unicode_escape_1 = R"(a = "\UFFFFFFFF")"sv;
static constexpr auto string_basic_out_of_range_unicode_escape_2 = R"(a = "\U00D80000")"sv;
static constexpr auto string_basic_unknown_escape = R"(a = "\@")"sv;
static constexpr auto string_literal_multiline_quotes = R"(apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID)"sv;
static constexpr auto string_basic_unknown_escape = R"(a = "\@")"sv;
static constexpr auto string_literal_multiline_quotes =
R"(apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID)"sv;
static constexpr auto table_1 = R"(# DO NOT DO THIS
@ -104,7 +101,8 @@ apple.color = "red"
apple.taste.sweet = true
[fruit.apple.taste] # INVALID)"sv;
static constexpr auto table_invalid_1 = R"([fruit.physical] # subtable, but to which parent element should it belong?
static constexpr auto table_invalid_1 =
R"([fruit.physical] # subtable, but to which parent element should it belong?
color = "red"
shape = "round"
@ -145,8 +143,6 @@ fruit = []
color = "green")"sv;
}
TOML_ENABLE_WARNINGS;
TEST_CASE("conformance - iarna/invalid")
{
parsing_should_fail(FILE_LINE_ARGS, array_of_tables_1); // array-of-tables-1
@ -187,19 +183,26 @@ TEST_CASE("conformance - iarna/invalid")
parsing_should_fail(FILE_LINE_ARGS, no_key_name); // no-key-name
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_invalid_backslash); // string-basic-multiline-invalid-backslash
parsing_should_fail(FILE_LINE_ARGS,
string_basic_multiline_invalid_backslash); // string-basic-multiline-invalid-backslash
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
parsing_should_fail(
FILE_LINE_ARGS,
string_basic_multiline_out_of_range_unicode_escape_1); // string-basic-multiline-out-of-range-unicode-escape-1
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
parsing_should_fail(
FILE_LINE_ARGS,
string_basic_multiline_out_of_range_unicode_escape_2); // string-basic-multiline-out-of-range-unicode-escape-2
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_quotes); // string-basic-multiline-quotes
parsing_should_fail(FILE_LINE_ARGS, string_basic_multiline_unknown_escape); // string-basic-multiline-unknown-escape
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
parsing_should_fail(FILE_LINE_ARGS,
string_basic_out_of_range_unicode_escape_1); // string-basic-out-of-range-unicode-escape-1
parsing_should_fail(FILE_LINE_ARGS, string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
parsing_should_fail(FILE_LINE_ARGS,
string_basic_out_of_range_unicode_escape_2); // string-basic-out-of-range-unicode-escape-2
parsing_should_fail(FILE_LINE_ARGS, string_basic_unknown_escape); // string-basic-unknown-escape
@ -221,4 +224,3 @@ TEST_CASE("conformance - iarna/invalid")
parsing_should_fail(FILE_LINE_ARGS, table_invalid_4); // table-invalid-4
}

File diff suppressed because it is too large Load Diff

View File

@ -409,6 +409,15 @@ TEST_CASE("arrays - insertion and erasure")
CHECK(*arr.get_as<double>(5u) == 3.0);
}
// iterator replace(const_iterator pos, ElemType&& elem) noexcept
{
arr.clear();
arr.insert(arr.begin(), { 1, 2, 3 });
CHECK(arr == array{ 1, 2, 3 });
arr.replace(arr.begin() + 1u, "two"sv);
CHECK(arr == array{ 1, "two"sv, 3 });
}
#if TOML_ENABLE_WINDOWS_COMPAT
arr.clear();

View File

@ -155,7 +155,7 @@ str = ''''That's still pointless', she said.'''
parse_expected_value(FILE_LINE_ARGS, R"("\"\u03B1\u03B2\u03B3\"")"sv, "\"\u03B1\u03B2\u03B3\""sv);
// toml/pull/709 (\xHH unicode scalars)
// toml/pull/796 (\xHH unicode scalars)
#if TOML_LANG_UNRELEASED
parse_expected_value(FILE_LINE_ARGS,
R"("\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv,

157
toml.hpp
View File

@ -108,7 +108,16 @@
_Pragma("clang diagnostic ignored \"-Wshift-sign-overflow\"") \
static_assert(true)
#if TOML_CLANG >= 10
#define TOML_DISABLE_SPAM_WARNINGS_CLANG_10 \
_Pragma("clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"") \
static_assert(true)
#else
#define TOML_DISABLE_SPAM_WARNINGS_CLANG_10 static_assert(true)
#endif
#define TOML_DISABLE_SPAM_WARNINGS \
TOML_DISABLE_SPAM_WARNINGS_CLANG_10; \
_Pragma("clang diagnostic ignored \"-Wweak-vtables\"") \
_Pragma("clang diagnostic ignored \"-Wweak-template-vtables\"") \
_Pragma("clang diagnostic ignored \"-Wdouble-promotion\"") \
@ -4727,13 +4736,13 @@ TOML_IMPL_NAMESPACE_START
return out;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
reference operator*() const noexcept
{
return *raw_->get();
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
pointer operator->() const noexcept
{
return raw_->get();
@ -4769,49 +4778,49 @@ TOML_IMPL_NAMESPACE_START
return { lhs.raw_ - rhs };
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend ptrdiff_t operator-(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ - rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator==(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ == rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator!=(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ != rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator<(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ < rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator<=(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ <= rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator>(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ > rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator>=(const array_iterator& lhs, const array_iterator& rhs) noexcept
{
return lhs.raw_ >= rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
reference operator[](ptrdiff_t idx) const noexcept
{
return *(raw_ + idx)->get();
@ -5344,6 +5353,22 @@ TOML_NAMESPACE_START
return { elems_.emplace(pos.raw_, new impl::wrap_node<type>{ static_cast<Args&&>(args)... }) };
}
template <typename ElemType>
iterator replace(const_iterator pos, ElemType&& val, value_flags flags = preserve_source_value_flags)
{
TOML_ASSERT(pos >= cbegin() && pos < cend());
if constexpr (is_node_view<ElemType>)
{
if (!val)
return end();
}
const auto it = elems_.begin() + (pos.raw_ - elems_.cbegin());
it->reset(impl::make_node(static_cast<ElemType&&>(val), flags));
return iterator{ it };
}
iterator erase(const_iterator pos) noexcept
{
return { elems_.erase(pos.raw_) };
@ -5635,25 +5660,25 @@ TOML_IMPL_NAMESPACE_START
return out;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
reference operator*() const noexcept
{
return *get_proxy();
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
pointer operator->() const noexcept
{
return get_proxy();
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator==(const table_iterator& lhs, const table_iterator& rhs) noexcept
{
return lhs.raw_ == rhs.raw_;
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
friend bool operator!=(const table_iterator& lhs, const table_iterator& rhs) noexcept
{
return lhs.raw_ != rhs.raw_;
@ -10492,7 +10517,7 @@ TOML_ANON_NAMESPACE_START
}
TOML_PURE_INLINE_GETTER
node* get() const noexcept
node* operator->() noexcept
{
return node_;
}
@ -10916,7 +10941,6 @@ TOML_IMPL_NAMESPACE_START
return i;
}
// template <bool MultiLine>
TOML_NODISCARD
std::string parse_basic_string(bool multi_line)
{
@ -10928,7 +10952,7 @@ TOML_IMPL_NAMESPACE_START
// skip the '"'
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
// multi-line strings ignore a single line ending right at the beginning
if (multi_line)
{
consume_line_break();
@ -10937,8 +10961,8 @@ TOML_IMPL_NAMESPACE_START
}
std::string str;
bool escaped = false;
[[maybe_unused]] bool skipping_whitespace = false;
bool escaped = false;
bool skipping_whitespace = false;
do
{
if (escaped)
@ -10972,7 +10996,7 @@ TOML_IMPL_NAMESPACE_START
// unicode scalar sequences
case U'x':
#if TOML_LANG_UNRELEASED // toml/pull/709 (\xHH unicode scalar sequences)
#if TOML_LANG_UNRELEASED // toml/pull/796 (\xHH unicode scalar sequences)
[[fallthrough]];
#else
set_error_and_return_default(
@ -11152,7 +11176,7 @@ TOML_IMPL_NAMESPACE_START
// skip the delimiter
advance_and_return_if_error_or_eof({});
// multiline strings ignore a single line ending right at the beginning
// multi-line strings ignore a single line ending right at the beginning
if (multi_line)
{
consume_line_break();
@ -12329,7 +12353,7 @@ TOML_IMPL_NAMESPACE_START
return_if_error({});
val = new value{ i };
reinterpret_cast<value<int64_t>*>(val.get())->flags(flags);
val->ref_cast<int64_t>().flags(flags);
}
else if (has_any(has_e) || (has_any(begins_zero | begins_digit) && chars[1] == U'.'))
val = new value{ parse_float() };
@ -12367,14 +12391,14 @@ TOML_IMPL_NAMESPACE_START
// 0b10
case bzero_msk | has_b:
val = new value{ parse_integer<2>() };
reinterpret_cast<value<int64_t>*>(val.get())->flags(value_flags::format_as_binary);
val->ref_cast<int64_t>().flags(value_flags::format_as_binary);
break;
// octal integers
// 0o10
case bzero_msk | has_o:
val = new value{ parse_integer<8>() };
reinterpret_cast<value<int64_t>*>(val.get())->flags(value_flags::format_as_octal);
val->ref_cast<int64_t>().flags(value_flags::format_as_octal);
break;
// decimal integers
@ -12391,7 +12415,7 @@ TOML_IMPL_NAMESPACE_START
// 0x10
case bzero_msk | has_x:
val = new value{ parse_integer<16>() };
reinterpret_cast<value<int64_t>*>(val.get())->flags(value_flags::format_as_hexadecimal);
val->ref_cast<int64_t>().flags(value_flags::format_as_hexadecimal);
break;
// decimal floats
@ -12554,7 +12578,7 @@ TOML_IMPL_NAMESPACE_START
}
#endif
val.get()->source_ = { begin_pos, current_position(1), reader.source_path() };
val->source_ = { begin_pos, current_position(1), reader.source_path() };
return val.release();
}
@ -12761,7 +12785,7 @@ TOML_IMPL_NAMESPACE_START
// the spec dictates we select the most recently declared element in the array.
TOML_ASSERT(!child->ref_cast<array>().elems_.empty());
TOML_ASSERT(child->ref_cast<array>().elems_.back()->is_table());
parent = &child->ref_cast<array>().elems_.back()->ref_cast<table>();
parent = &child->ref_cast<array>().back().ref_cast<table>();
}
else
{
@ -12789,22 +12813,21 @@ TOML_IMPL_NAMESPACE_START
// set the starting regions, and return the table element
if (is_arr)
{
auto tab_arr =
&parent->map_.emplace(key.segments.back(), new array{}).first->second->ref_cast<array>();
table_arrays.push_back(tab_arr);
tab_arr->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
array& tbl_arr = parent->emplace<array>(key.segments.back()).first->second.ref_cast<array>();
table_arrays.push_back(&tbl_arr);
tbl_arr.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
tab_arr->elems_.emplace_back(new table{});
tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elems_.back()->ref_cast<table>();
table& tbl = tbl_arr.emplace_back<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
// otherwise we're just making a table
else
{
auto tab = &parent->map_.emplace(key.segments.back(), new table{}).first->second->ref_cast<table>();
tab->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return tab;
table& tbl = parent->emplace<table>(key.segments.back()).first->second.ref_cast<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
}
@ -12817,22 +12840,21 @@ TOML_IMPL_NAMESPACE_START
if (is_arr && matching_node->is_array()
&& impl::find(table_arrays.begin(), table_arrays.end(), &matching_node->ref_cast<array>()))
{
auto tab_arr = &matching_node->ref_cast<array>();
tab_arr->elems_.emplace_back(new table{});
tab_arr->elems_.back()->source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tab_arr->elems_.back()->ref_cast<table>();
table& tbl = matching_node->ref_cast<array>().emplace_back<table>();
tbl.source_ = { header_begin_pos, header_end_pos, reader.source_path() };
return &tbl;
}
else if (!is_arr && matching_node->is_table() && !implicit_tables.empty())
{
auto tbl = &matching_node->ref_cast<table>();
if (auto found = impl::find(implicit_tables.begin(), implicit_tables.end(), tbl);
found && (tbl->empty() || tbl->is_homogeneous<table>()))
table& tbl = matching_node->ref_cast<table>();
if (auto found = impl::find(implicit_tables.begin(), implicit_tables.end(), &tbl);
found && (tbl.empty() || tbl.is_homogeneous<table>()))
{
implicit_tables.erase(implicit_tables.cbegin() + (found - implicit_tables.data()));
tbl->source_.begin = header_begin_pos;
tbl->source_.end = header_end_pos;
return tbl;
tbl.source_.begin = header_begin_pos;
tbl.source_.end = header_end_pos;
return &tbl;
}
}
@ -12881,7 +12903,7 @@ TOML_IMPL_NAMESPACE_START
{
child = tab->map_.emplace(std::move(kvp.key.segments[i]), new table{}).first->second.get();
dotted_key_tables.push_back(&child->ref_cast<table>());
child->source_ = kvp.value.get()->source_;
child->source_ = kvp.value->source_;
}
else if (!child->is_table()
|| !(impl::find(dotted_key_tables.begin(),
@ -12895,7 +12917,7 @@ TOML_IMPL_NAMESPACE_START
to_sv(child->type()),
" as dotted key-value pair"sv);
else
child->source_.end = kvp.value.get()->source_.end;
child->source_.end = kvp.value->source_.end;
return_if_error();
tab = &child->ref_cast<table>();
@ -12904,7 +12926,7 @@ TOML_IMPL_NAMESPACE_START
if (auto conflicting_node = tab->get(kvp.key.segments.back()))
{
if (conflicting_node->type() == kvp.value.get()->type())
if (conflicting_node->type() == kvp.value->type())
set_error("cannot redefine existing "sv,
to_sv(conflicting_node->type()),
" '"sv,
@ -12916,7 +12938,7 @@ TOML_IMPL_NAMESPACE_START
" '"sv,
to_sv(recording_buffer),
"' as "sv,
to_sv(kvp.value.get()->type()));
to_sv(kvp.value->type()));
}
return_if_error();
@ -12982,8 +13004,7 @@ TOML_IMPL_NAMESPACE_START
if (type == node_type::table)
{
auto& tbl = nde.ref_cast<table>();
if (tbl.inline_) // inline tables (and all their inline descendants) are already correctly
// terminated
if (tbl.inline_) // inline tables (and all their inline descendants) are already correctly terminated
return;
auto end = nde.source_.end;
@ -12999,11 +13020,11 @@ TOML_IMPL_NAMESPACE_START
{
auto& arr = nde.ref_cast<array>();
auto end = nde.source_.end;
for (auto& v : arr.elems_)
for (auto& v : arr)
{
update_region_ends(*v);
if (end < v->source_.end)
end = v->source_.end;
update_region_ends(v);
if (end < v.source_.end)
end = v.source_.end;
}
nde.source_.end = end;
}
@ -13062,8 +13083,8 @@ TOML_IMPL_NAMESPACE_START
// skip opening '['
advance_and_return_if_error_or_eof({});
node_ptr arr{ new array{} };
auto& vals = reinterpret_cast<array*>(arr.get())->elems_;
node_ptr arr_ptr{ new array{} };
array& arr = arr_ptr->ref_cast<array>();
enum parse_elem : int
{
none,
@ -13106,14 +13127,14 @@ TOML_IMPL_NAMESPACE_START
continue;
}
prev = val;
if (!vals.capacity())
vals.reserve(4u);
vals.emplace_back(parse_value());
if (!arr.capacity())
arr.reserve(4u);
arr.elems_.emplace_back(parse_value());
}
}
return_if_error({});
return reinterpret_cast<array*>(arr.release());
return reinterpret_cast<array*>(arr_ptr.release());
}
TOML_EXTERNAL_LINKAGE
@ -13127,8 +13148,9 @@ TOML_IMPL_NAMESPACE_START
// skip opening '{'
advance_and_return_if_error_or_eof({});
node_ptr tab{ new table{} };
reinterpret_cast<table*>(tab.get())->inline_ = true;
node_ptr tbl_ptr{ new table{} };
table& tbl = tbl_ptr->ref_cast<table>();
tbl.inline_ = true;
enum parse_elem : int
{
none,
@ -13187,7 +13209,7 @@ TOML_IMPL_NAMESPACE_START
else
{
prev = kvp;
parse_key_value_pair_and_insert(reinterpret_cast<table*>(tab.get()));
parse_key_value_pair_and_insert(&tbl);
}
}
@ -13196,7 +13218,7 @@ TOML_IMPL_NAMESPACE_START
}
return_if_error({});
return reinterpret_cast<table*>(tab.release());
return reinterpret_cast<table*>(tbl_ptr.release());
}
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
@ -14416,6 +14438,7 @@ TOML_POP_WARNINGS;
#undef TOML_DISABLE_ARITHMETIC_WARNINGS
#undef TOML_DISABLE_CODE_ANALYSIS_WARNINGS
#undef TOML_DISABLE_SPAM_WARNINGS
#undef TOML_DISABLE_SPAM_WARNINGS_CLANG_10
#undef TOML_DISABLE_SUGGEST_ATTR_WARNINGS
#undef TOML_DISABLE_SWITCH_WARNINGS
#undef TOML_DISABLE_WARNINGS

View File

@ -6,7 +6,6 @@
import sys
import utils
import io
import re
import json
import yaml
@ -14,6 +13,7 @@ import math
import dateutil.parser
from pathlib import Path
from datetime import datetime, date, time
from io import StringIO
@ -51,35 +51,31 @@ def python_value_to_tomlpp(val):
return str(val)
elif isinstance(val, (TomlPPArray, TomlPPTable)):
return str(val)
elif isinstance(val, datetime):
offset = None
if val.tzinfo is not None:
offset = val.tzinfo.utcoffset(val)
mins = offset.total_seconds() / 60
offset = (int(mins / 60), int(mins % 60))
return 'toml::date_time{{ {{ {}, {}, {} }}, {{ {}, {}, {}, {}u }}{} }}'.format(
val.year,
val.month,
val.day,
val.hour,
val.minute,
val.second,
val.microsecond*1000,
'' if offset is None else ', {{ {}, {} }}'.format(offset[0], offset[1])
)
elif isinstance(val, date):
return 'toml::date{{ {}, {}, {} }}'.format(
val.year,
val.month,
val.day
)
elif isinstance(val, time):
return 'toml::time{{ {}, {}, {}, {} }}'.format(
val.hour,
val.minute,
val.second,
val.microsecond*1000
)
elif isinstance(val, (date, time, datetime)):
date_args = None
if isinstance(val, (date, datetime)):
date_args = rf'{val.year}, {val.month}, {val.day}'
time_args = None
if isinstance(val, (time, datetime)):
time_args = rf'{val.hour}, {val.minute}'
if val.second and val.microsecond:
time_args = rf'{time_args}, {val.second}, {val.microsecond*1000}'
elif val.second:
time_args = rf'{time_args}, {val.second}'
elif val.microsecond:
time_args = rf'{time_args}, 0, {val.microsecond*1000}'
if isinstance(val, datetime):
offset_init = ''
if val.tzinfo is not None:
offset = val.tzinfo.utcoffset(val)
mins = offset.total_seconds() / 60
offset = (int(mins / 60), int(mins % 60))
offset_init = rf', {{ {offset[0]}, {offset[1]} }}'
return rf'toml::date_time{{ {{ {date_args} }}, {{ {time_args} }}{offset_init} }}'
elif isinstance(val, time):
return rf'toml::time{{ {time_args} }}'
elif isinstance(val, date):
return rf'toml::date{{ {date_args} }}'
else:
raise ValueError(str(type(val)))
@ -407,9 +403,8 @@ def write_test_file(name, all_tests):
all_tests = tests_by_group
test_file_path = Path(utils.entry_script_dir(), '..', 'tests', rf'conformance_{sanitize(name.strip())}.cpp').resolve()
print(rf'Writing to {test_file_path}')
with open(test_file_path, 'w', encoding='utf-8', newline='\n') as test_file:
write = lambda txt,end='\n': print(txt, file=test_file, end=end)
with StringIO() as test_file_buffer:
write = lambda txt,end='\n': print(txt, file=test_file_buffer, end=end)
# preamble
write(r'// This file is a part of toml++ and is subject to the the terms of the MIT license.')
@ -418,15 +413,12 @@ def write_test_file(name, all_tests):
write(r'// SPDX-License-Identifier: MIT')
write(r'//-----')
write(r'// this file was generated by generate_conformance_tests.py - do not modify it directly')
write(r'// clang-format off')
#write(r'// clang-format off')
write(r'')
write(r'#include "tests.h"')
write(r'using namespace toml::impl;')
write(r'')
# test data
write('TOML_DISABLE_WARNINGS; // unused variable spam')
write('')
write(r'')
write('namespace')
write('{', end='')
for group, conditions in all_tests.items():
@ -441,11 +433,9 @@ def write_test_file(name, all_tests):
write('')
write(f'#endif // {condition}');
write('}')
write('')
write('TOML_ENABLE_WARNINGS;')
write('')
# tests
write('')
write(f'TEST_CASE("conformance - {name}")')
write('{', end='')
for group, conditions in all_tests.items():
@ -474,6 +464,17 @@ def write_test_file(name, all_tests):
write('}')
write('')
test_file_content = test_file_buffer.getvalue()
# clang-format
print(f"Running clang-format for {test_file_path}")
test_file_content = utils.apply_clang_format(test_file_content, cwd=test_file_path.parent)
# write to disk
print(rf'Writing {test_file_path}')
with open(test_file_path, 'w', encoding='utf-8', newline='\n') as test_file:
test_file.write(test_file_content)
def main():

View File

@ -5,10 +5,11 @@
# SPDX-License-Identifier: MIT
import sys
import subprocess
from pathlib import Path
from misk import *
def repeat_pattern(pattern, count):
if len(pattern) == 1:
return pattern * count
@ -31,6 +32,17 @@ def make_divider(text = None, text_col = 40, pattern = '-', line_length = 120):
def apply_clang_format(text, cwd=None):
return subprocess.run(
'clang-format --style=file'.split(),
check=True,
capture_output=True,
cwd=str(Path.cwd() if cwd is None else cwd),
encoding='utf-8',
input=text
).stdout
def run(main_func, verbose=False):
try:
result = main_func()