added operator[], begin(), end() to parse_result in noexcept-mode

also:
- added note about `#include <fstream>` requirements README
- added tests for parse_result
- added array and table iterators to the toml namespace
This commit is contained in:
Mark Gillard 2020-04-03 16:33:02 +03:00
parent 764e6dd032
commit 358ac66669
28 changed files with 326 additions and 61 deletions

View File

@ -33,6 +33,9 @@ cpp = 17
``` ```
Reading it in C++ is easy with `toml++`: Reading it in C++ is easy with `toml++`:
```cpp ```cpp
#include <toml.hpp>
#include <fstream> //required for toml::parse_file()
auto config = toml::parse_file( "configuration.toml" ); auto config = toml::parse_file( "configuration.toml" );
// get key-value pairs // get key-value pairs
@ -48,7 +51,7 @@ config.insert_or_assign("alternatives", toml::array{
}); });
// iterate & visit over the data // iterate & visit over the data
for (auto [k, v] : config) for (auto&& [k, v] : config)
{ {
v.visit([](auto& node) noexcept v.visit([](auto& node) noexcept
{ {
@ -176,8 +179,8 @@ though you're welcome to reach out via other means. In order of likely response
[char8_t]: https://en.cppreference.com/w/cpp/keyword/char8_t [char8_t]: https://en.cppreference.com/w/cpp/keyword/char8_t
[TOML master]: https://github.com/toml-lang/toml/blob/master/README.md [TOML master]: https://github.com/toml-lang/toml/blob/master/README.md
[TOML issues list]: https://github.com/toml-lang/toml/issues [TOML issues list]: https://github.com/toml-lang/toml/issues
[TOML v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/README.md [TOML v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md
[v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/README.md [v1.0.0-rc.1]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md
[CONTRIBUTING]: ./CONTRIBUTING.md [CONTRIBUTING]: ./CONTRIBUTING.md
[LICENSE]: ./LICENSE [LICENSE]: ./LICENSE
[Flexible and Economical UTF-8 Decoder]: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ [Flexible and Economical UTF-8 Decoder]: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/

View File

@ -86,8 +86,8 @@
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/// ///
/// \section mainpage-features Features /// \section mainpage-features Features
/// - [TOML v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/README.md), plus optional support for some /// - [TOML v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md),
/// unreleased TOML features /// plus optional support for some unreleased TOML features
/// - C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings) /// - C++17 (plus some C++20 features where available, e.g. experimental support for char8_t strings)
/// - Proper UTF-8 handling (incl. BOM) /// - Proper UTF-8 handling (incl. BOM)
/// - Works with or without exceptions /// - Works with or without exceptions
@ -252,6 +252,8 @@
/// ... exactly as above, but twice /// ... exactly as above, but twice
/// \eout /// \eout
/// ///
/// The error-handling semantics are the same as for toml::parse_file.
///
/// \see toml::parse() /// \see toml::parse()
/// ///
/////////////////////////////////// ///////////////////////////////////
@ -347,7 +349,7 @@
/// auto tbl = toml::table{{ /// auto tbl = toml::table{{
/// { "lib", "toml++" }, /// { "lib", "toml++" },
/// { "cpp", toml::array{ 17, 20, "and beyond" } }, /// { "cpp", toml::array{ 17, 20, "and beyond" } },
/// { "toml", toml::array{ "1.0.0", "and beyond" } }, /// { "toml", toml::array{ "1.0.0-rc.1", "and beyond" } },
/// { "repo", "https://github.com/marzer/tomlplusplus/" }, /// { "repo", "https://github.com/marzer/tomlplusplus/" },
/// { "author", toml::table{{ /// { "author", toml::table{{
/// { "name", "Mark Gillard" }, /// { "name", "Mark Gillard" },
@ -374,7 +376,7 @@
/// cpp = [17, 20, "and beyond"] /// cpp = [17, 20, "and beyond"]
/// lib = "toml++" /// lib = "toml++"
/// repo = "https://github.com/marzer/tomlplusplus/" /// repo = "https://github.com/marzer/tomlplusplus/"
/// toml = ["1.0.0", "and beyond"] /// toml = ["1.0.0-rc.1", "and beyond"]
/// ///
/// [author] /// [author]
/// github = "https://github.com/marzer" /// github = "https://github.com/marzer"
@ -397,7 +399,7 @@
/// "lib" : "toml++", /// "lib" : "toml++",
/// "repo" : "https://github.com/marzer/tomlplusplus/", /// "repo" : "https://github.com/marzer/tomlplusplus/",
/// "toml" : [ /// "toml" : [
/// "1.0.0", /// "1.0.0-rc.1",
/// "and beyond" /// "and beyond"
/// ] /// ]
/// } /// }

View File

@ -186,6 +186,12 @@ namespace toml
template <typename Char> template <typename Char>
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const array&); std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const array&);
/// \brief A RandomAccessIterator for iterating over nodes in a toml::array.
using array_iterator = impl::array_iterator<false>;
/// \brief A RandomAccessIterator for iterating over const nodes in a toml::array.
using const_array_iterator = impl::array_iterator<true>;
/// \brief A TOML array. /// \brief A TOML array.
/// ///
/// \detail The interface of this type is modeled after std::vector, with some /// \detail The interface of this type is modeled after std::vector, with some
@ -242,10 +248,10 @@ namespace toml
using reference = node&; using reference = node&;
using const_reference = const node&; using const_reference = const node&;
/// \brief A RandomAccessIterator for iterating over the nodes in an array. /// \brief A RandomAccessIterator for iterating over nodes in a toml::array.
using iterator = impl::array_iterator<false>; using iterator = array_iterator;
/// \brief A const RandomAccessIterator for iterating over the nodes in an array. /// \brief A RandomAccessIterator for iterating over const nodes in a toml::array.
using const_iterator = impl::array_iterator<true>; using const_iterator = const_array_iterator;
/// \brief Default constructor. /// \brief Default constructor.
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR

View File

@ -175,7 +175,7 @@ namespace toml
}; };
//values, arrays, and inline tables/table arrays //values, arrays, and inline tables/table arrays
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
const auto type = v.type(); const auto type = v.type();
if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline()) if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline())
@ -196,7 +196,7 @@ namespace toml
} }
//non-inline tables //non-inline tables
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
const auto type = v.type(); const auto type = v.type();
if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline()) if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline())
@ -208,7 +208,7 @@ namespace toml
size_t child_value_count{}; //includes inline tables and non-table arrays size_t child_value_count{}; //includes inline tables and non-table arrays
size_t child_table_count{}; size_t child_table_count{};
size_t child_table_array_count{}; size_t child_table_array_count{};
for (auto [child_k, child_v] : child_tbl) for (auto&& [child_k, child_v] : child_tbl)
{ {
const auto child_type = child_v.type(); const auto child_type = child_v.type();
switch (child_type) switch (child_type)
@ -258,7 +258,7 @@ namespace toml
} }
//table arrays //table arrays
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
if (!is_non_inline_array_of_tables(v)) if (!is_non_inline_array_of_tables(v))
continue; continue;
@ -345,7 +345,7 @@ namespace toml
impl::print_to_stream("{ "sv, base::stream()); impl::print_to_stream("{ "sv, base::stream());
bool first = false; bool first = false;
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
if (first) if (first)
impl::print_to_stream(", "sv, base::stream()); impl::print_to_stream(", "sv, base::stream());

View File

@ -72,7 +72,7 @@ namespace toml::impl
if (n.empty()) if (n.empty())
return 2_sz; // "{}" return 2_sz; // "{}"
size_t weight = 3_sz; // "{ }" size_t weight = 3_sz; // "{ }"
for (auto [k, v] : n) for (auto&& [k, v] : n)
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", " weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
return weight; return weight;
} }

View File

@ -131,7 +131,7 @@ namespace toml
impl::print_to_stream('{', base::stream()); impl::print_to_stream('{', base::stream());
base::increase_indent(); base::increase_indent();
bool first = false; bool first = false;
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
if (first) if (first)
impl::print_to_stream(", "sv, base::stream()); impl::print_to_stream(", "sv, base::stream());

View File

@ -65,7 +65,7 @@ namespace toml
friend class toml::table; friend class toml::table;
template <typename U> friend class toml::node_view; template <typename U> friend class toml::node_view;
mutable viewed_type* node_; mutable viewed_type* node_ = nullptr;
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
node_view(viewed_type* node) noexcept node_view(viewed_type* node) noexcept
@ -78,6 +78,10 @@ namespace toml
public: public:
/// \brief Constructs an empty node view.
TOML_NODISCARD_CTOR
node_view() noexcept = default;
/// \brief Returns true if the view references a node. /// \brief Returns true if the view references a node.
[[nodiscard]] explicit operator bool() const noexcept { return node_ != nullptr; } [[nodiscard]] explicit operator bool() const noexcept { return node_ != nullptr; }
/// \brief Returns the node that's being referenced by the view. /// \brief Returns the node that's being referenced by the view.

View File

@ -36,6 +36,11 @@ namespace toml
/// (error occurred at line 1, column 13 of 'config.toml') /// (error occurred at line 1, column 13 of 'config.toml')
/// \eout /// \eout
/// ///
/// Getting node_views (`operator[]`) and using the iterator accessor functions (`begin(), end()` etc.) are
/// unconditionally safe; when parsing fails these just return 'empty' values. A ranged-for loop on a failed
/// parse_result is also safe since `begin()` and `end()` return the same iterator and will not lead to any
/// dereferences and iterations.
///
/// \attention <strong>This type only exists when exceptions are not enabled.</strong> /// \attention <strong>This type only exists when exceptions are not enabled.</strong>
/// Otherwise parse_result is just an alias for toml::table: \cpp /// Otherwise parse_result is just an alias for toml::table: \cpp
/// #if TOML_EXCEPTIONS /// #if TOML_EXCEPTIONS
@ -63,6 +68,12 @@ namespace toml
public: public:
/// \brief A BidirectionalIterator for iterating over key-value pairs in a wrapped toml::table.
using iterator = table_iterator;
/// \brief A BidirectionalIterator for iterating over const key-value pairs in a wrapped toml::table.
using const_iterator = const_table_iterator;
/// \brief Returns true if parsing succeeeded. /// \brief Returns true if parsing succeeeded.
[[nodiscard]] bool succeeded() const noexcept { return !is_err; } [[nodiscard]] bool succeeded() const noexcept { return !is_err; }
/// \brief Returns true if parsing failed. /// \brief Returns true if parsing failed.
@ -136,7 +147,6 @@ namespace toml
::new (&storage) parse_error{ std::move(err) }; ::new (&storage) parse_error{ std::move(err) };
} }
/// \brief Move constructor. /// \brief Move constructor.
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
parse_result(parse_result&& res) noexcept parse_result(parse_result&& res) noexcept
@ -175,6 +185,67 @@ namespace toml
{ {
destroy(); destroy();
} }
/// \brief Gets a node_view for the selected key-value pair in the wrapped table.
///
/// \param key The key used for the lookup.
///
/// \returns A view of the value at the given key if parsing was successful and a matching key existed,
/// or an empty node view.
///
/// \see toml::node_view
[[nodiscard]] node_view<node> operator[] (string_view key) noexcept
{
return is_err ? node_view<node>{} : get()[key];
}
/// \brief Gets a node_view for the selected key-value pair in the wrapped table (const overload).
[[nodiscard]] node_view<const node> operator[] (string_view key) const noexcept
{
return is_err ? node_view<const node>{} : get()[key];
}
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] table_iterator begin() noexcept
{
return is_err ? table_iterator{} : get().begin();
}
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator begin() const noexcept
{
return is_err ? const_table_iterator{} : get().begin();
}
/// \brief Returns an iterator to the first key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator cbegin() const noexcept
{
return is_err ? const_table_iterator{} : get().cbegin();
}
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] table_iterator end() noexcept
{
return is_err ? table_iterator{} : get().end();
}
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator end() const noexcept
{
return is_err ? const_table_iterator{} : get().end();
}
/// \brief Returns an iterator to one-past-the-last key-value pair in the wrapped table.
/// \remarks Returns a default-constructed 'nothing' iterator if the parsing failed.
[[nodiscard]] const_table_iterator cend() const noexcept
{
return is_err ? const_table_iterator{} : get().cend();
}
}; };
#if TOML_ABI_NAMESPACES #if TOML_ABI_NAMESPACES

View File

@ -122,6 +122,12 @@ namespace toml
template <typename Char> template <typename Char>
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const table&); std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const table&);
/// \brief A BidirectionalIterator for iterating over key-value pairs in a toml::table.
using table_iterator = impl::table_iterator<false>;
/// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table.
using const_table_iterator = impl::table_iterator<true>;
/// \brief A TOML table. /// \brief A TOML table.
/// ///
/// \remarks The interface of this type is modeled after std::map, with some /// \remarks The interface of this type is modeled after std::map, with some
@ -141,10 +147,10 @@ namespace toml
public: public:
/// \brief A BidirectionalIterator for iterating over the key-value pairs in a table. /// \brief A BidirectionalIterator for iterating over key-value pairs in a toml::table.
using iterator = impl::table_iterator<false>; using iterator = table_iterator;
/// \brief A const BidirectionalIterator for iterating over the key-value pairs in a table. /// \brief A BidirectionalIterator for iterating over const key-value pairs in a toml::table.
using const_iterator = impl::table_iterator<true>; using const_iterator = const_table_iterator;
/// \brief Default constructor. /// \brief Default constructor.
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR

View File

@ -135,7 +135,7 @@ that contributed to this header can be found at the beginnings and ends of the c
preamble.append(''' preamble.append('''
TOML language specifications: TOML language specifications:
Latest: https://github.com/toml-lang/toml/blob/master/README.md Latest: https://github.com/toml-lang/toml/blob/master/README.md
v1.0.0: https://github.com/toml-lang/toml/blob/master/README.md v1.0.0-rc.1: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md
v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md''') v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md''')
preamble.append(read_all_text_from_file(path.join(get_script_folder(), '..', 'LICENSE'))) preamble.append(read_all_text_from_file(path.join(get_script_folder(), '..', 'LICENSE')))

View File

@ -0,0 +1,107 @@
#include "tests.h"
#if !TOML_EXCEPTIONS
TEST_CASE("parse_result - good parse")
{
auto result = "key = true"_toml;
static_assert(std::is_same_v<decltype(result), parse_result>);
static_assert(!std::is_same_v<decltype(result), table>);
REQUIRE(result.succeeded());
REQUIRE(!result.failed());
REQUIRE(result);
REQUIRE(!result.get().empty());
REQUIRE(result.get().size() == 1);
REQUIRE(!std::move(result).get().empty());
REQUIRE(!static_cast<const parse_result&>(result).get().empty());
REQUIRE(!static_cast<table&>(result).empty());
REQUIRE(!static_cast<table&&>(result).empty());
REQUIRE(!static_cast<const table&>(result).empty());
auto& tbl = static_cast<table&>(result);
CHECK(tbl[S("key"sv)]);
CHECK(result[S("key"sv)]);
CHECK(&result[S("key"sv)].ref<bool>() == &tbl[S("key"sv)].ref<bool>());
CHECK(result.begin() == tbl.begin());
CHECK(result.end() == tbl.end());
CHECK(result.begin() != tbl.end());
CHECK(result.cbegin() == tbl.cbegin());
CHECK(result.cend() == tbl.cend());
CHECK(result.cbegin() != tbl.cend());
auto& cresult = static_cast<const parse_result&>(result);
auto& ctbl = static_cast<const table&>(cresult);
CHECK(cresult.begin() == ctbl.begin());
CHECK(cresult.end() == ctbl.end());
CHECK(cresult.begin() != ctbl.end());
CHECK(cresult.cbegin() == ctbl.cbegin());
CHECK(cresult.cend() == ctbl.cend());
CHECK(cresult.cbegin() != ctbl.cend());
CHECK(ctbl[S("key"sv)]);
CHECK(cresult[S("key"sv)]);
CHECK(&cresult[S("key"sv)].ref<bool>() == &ctbl[S("key"sv)].ref<bool>());
size_t tbl_iterations{};
for (auto&& [k, v] : tbl)
{
(void)k; (void)v;
tbl_iterations++;
}
size_t result_iterations{};
for (auto&& [k, v] : result)
{
(void)k; (void)v;
result_iterations++;
}
size_t cresult_iterations{};
for (auto&& [k, v] : cresult)
{
(void)k; (void)v;
cresult_iterations++;
}
CHECK(tbl_iterations == tbl.size());
CHECK(tbl_iterations == result_iterations);
CHECK(tbl_iterations == cresult_iterations);
}
TEST_CASE("parse_result - bad parse")
{
auto result = "key = trUe"_toml;
static_assert(std::is_same_v<decltype(result), parse_result>);
static_assert(!std::is_same_v<decltype(result), table>);
REQUIRE(!result.succeeded());
REQUIRE(result.failed());
REQUIRE(!result);
CHECK(!result[S("key"sv)]);
CHECK(result.begin() == decltype(result.begin()){});
CHECK(result.end() == decltype(result.end()){});
CHECK(result.cbegin() == decltype(result.cbegin()){});
CHECK(result.cend() == decltype(result.cend()){});
auto& cresult = static_cast<const parse_result&>(result);
CHECK(!result[S("key"sv)]);
CHECK(cresult.begin() == decltype(cresult.begin()){});
CHECK(cresult.end() == decltype(cresult.end()){});
CHECK(cresult.cbegin() == decltype(cresult.cbegin()){});
CHECK(cresult.cend() == decltype(cresult.cend()){});
for (auto&& [k, v] : result)
{
(void)k; (void)v;
FAIL("This code should not run");
}
for (auto&& [k, v] : cresult)
{
(void)k; (void)v;
FAIL("This code should not run");
}
}
#endif //!TOML_EXCEPTIONS

View File

@ -17,7 +17,7 @@
// //
// TOML language specifications: // TOML language specifications:
// Latest: https://github.com/toml-lang/toml/blob/master/README.md // Latest: https://github.com/toml-lang/toml/blob/master/README.md
// v1.0.0: https://github.com/toml-lang/toml/blob/master/README.md // v1.0.0-rc.1: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md
// v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md // v0.5.0: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md
// //
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -2488,6 +2488,9 @@ namespace toml
template <typename Char> template <typename Char>
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const array&); std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const array&);
using array_iterator = impl::array_iterator<false>;
using const_array_iterator = impl::array_iterator<true>;
class TOML_API array final class TOML_API array final
: public node : public node
{ {
@ -2504,8 +2507,8 @@ namespace toml
using difference_type = ptrdiff_t; using difference_type = ptrdiff_t;
using reference = node&; using reference = node&;
using const_reference = const node&; using const_reference = const node&;
using iterator = impl::array_iterator<false>; using iterator = array_iterator;
using const_iterator = impl::array_iterator<true>; using const_iterator = const_array_iterator;
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
array() noexcept; array() noexcept;
@ -2890,6 +2893,9 @@ namespace toml
template <typename Char> template <typename Char>
std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const table&); std::basic_ostream<Char>& operator << (std::basic_ostream<Char>&, const table&);
using table_iterator = impl::table_iterator<false>;
using const_table_iterator = impl::table_iterator<true>;
class TOML_API table final class TOML_API table final
: public node : public node
{ {
@ -2903,8 +2909,8 @@ namespace toml
public: public:
using iterator = impl::table_iterator<false>; using iterator = table_iterator;
using const_iterator = impl::table_iterator<true>; using const_iterator = const_table_iterator;
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
table() noexcept; table() noexcept;
@ -3098,7 +3104,7 @@ namespace toml
friend class toml::table; friend class toml::table;
template <typename U> friend class toml::node_view; template <typename U> friend class toml::node_view;
mutable viewed_type* node_; mutable viewed_type* node_ = nullptr;
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
node_view(viewed_type* node) noexcept node_view(viewed_type* node) noexcept
@ -3111,6 +3117,8 @@ namespace toml
public: public:
TOML_NODISCARD_CTOR
node_view() noexcept = default;
[[nodiscard]] explicit operator bool() const noexcept { return node_ != nullptr; } [[nodiscard]] explicit operator bool() const noexcept { return node_ != nullptr; }
[[nodiscard]] viewed_type* get() const noexcept { return node_; } [[nodiscard]] viewed_type* get() const noexcept { return node_; }
@ -4844,6 +4852,8 @@ namespace toml
public: public:
using iterator = table_iterator;
using const_iterator = const_table_iterator;
[[nodiscard]] bool succeeded() const noexcept { return !is_err; } [[nodiscard]] bool succeeded() const noexcept { return !is_err; }
[[nodiscard]] bool failed() const noexcept { return is_err; } [[nodiscard]] bool failed() const noexcept { return is_err; }
[[nodiscard]] explicit operator bool() const noexcept { return !is_err; } [[nodiscard]] explicit operator bool() const noexcept { return !is_err; }
@ -4935,6 +4945,46 @@ namespace toml
{ {
destroy(); destroy();
} }
[[nodiscard]] node_view<node> operator[] (string_view key) noexcept
{
return is_err ? node_view<node>{} : get()[key];
}
[[nodiscard]] node_view<const node> operator[] (string_view key) const noexcept
{
return is_err ? node_view<const node>{} : get()[key];
}
[[nodiscard]] table_iterator begin() noexcept
{
return is_err ? table_iterator{} : get().begin();
}
[[nodiscard]] const_table_iterator begin() const noexcept
{
return is_err ? const_table_iterator{} : get().begin();
}
[[nodiscard]] const_table_iterator cbegin() const noexcept
{
return is_err ? const_table_iterator{} : get().cbegin();
}
[[nodiscard]] table_iterator end() noexcept
{
return is_err ? table_iterator{} : get().end();
}
[[nodiscard]] const_table_iterator end() const noexcept
{
return is_err ? const_table_iterator{} : get().end();
}
[[nodiscard]] const_table_iterator cend() const noexcept
{
return is_err ? const_table_iterator{} : get().cend();
}
}; };
#if TOML_ABI_NAMESPACES #if TOML_ABI_NAMESPACES
@ -5368,7 +5418,7 @@ namespace toml
}; };
//values, arrays, and inline tables/table arrays //values, arrays, and inline tables/table arrays
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
const auto type = v.type(); const auto type = v.type();
if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline()) if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline())
@ -5389,7 +5439,7 @@ namespace toml
} }
//non-inline tables //non-inline tables
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
const auto type = v.type(); const auto type = v.type();
if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline()) if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline())
@ -5401,7 +5451,7 @@ namespace toml
size_t child_value_count{}; //includes inline tables and non-table arrays size_t child_value_count{}; //includes inline tables and non-table arrays
size_t child_table_count{}; size_t child_table_count{};
size_t child_table_array_count{}; size_t child_table_array_count{};
for (auto [child_k, child_v] : child_tbl) for (auto&& [child_k, child_v] : child_tbl)
{ {
const auto child_type = child_v.type(); const auto child_type = child_v.type();
switch (child_type) switch (child_type)
@ -5451,7 +5501,7 @@ namespace toml
} }
//table arrays //table arrays
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
if (!is_non_inline_array_of_tables(v)) if (!is_non_inline_array_of_tables(v))
continue; continue;
@ -5534,7 +5584,7 @@ namespace toml
impl::print_to_stream("{ "sv, base::stream()); impl::print_to_stream("{ "sv, base::stream());
bool first = false; bool first = false;
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
if (first) if (first)
impl::print_to_stream(", "sv, base::stream()); impl::print_to_stream(", "sv, base::stream());
@ -5693,7 +5743,7 @@ namespace toml
impl::print_to_stream('{', base::stream()); impl::print_to_stream('{', base::stream());
base::increase_indent(); base::increase_indent();
bool first = false; bool first = false;
for (auto [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
if (first) if (first)
impl::print_to_stream(", "sv, base::stream()); impl::print_to_stream(", "sv, base::stream());
@ -9433,7 +9483,7 @@ namespace toml::impl
if (n.empty()) if (n.empty())
return 2_sz; // "{}" return 2_sz; // "{}"
size_t weight = 3_sz; // "{ }" size_t weight = 3_sz; // "{ }"
for (auto [k, v] : n) for (auto&& [k, v] : n)
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", " weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
return weight; return weight;
} }

View File

@ -68,6 +68,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -68,6 +68,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -70,6 +70,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -69,6 +69,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -71,6 +71,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -70,6 +70,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -69,6 +69,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -71,6 +71,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -68,6 +68,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -68,6 +68,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -70,6 +70,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -69,6 +69,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -71,6 +71,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -70,6 +70,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -69,6 +69,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />

View File

@ -71,6 +71,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\tests\manipulating_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_arrays.cpp" />
<ClCompile Include="..\tests\manipulating_tables.cpp" /> <ClCompile Include="..\tests\manipulating_tables.cpp" />
<ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_arrays.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />