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

@ -134,9 +134,9 @@ against it directly. You should instead make your changes in the relevant source
that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file.''') that contributed to this header can be found at the beginnings and ends of the corresponding sections of this file.''')
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')))
# write the output file # write the output file

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

@ -16,9 +16,9 @@
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// //
// 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

@ -67,7 +67,8 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</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,7 +69,8 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</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,7 +68,8 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</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,7 +70,8 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</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

@ -51,7 +51,7 @@
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>TOML_CHAR_8_STRINGS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>false</ExceptionHandling> <ExceptionHandling>false</ExceptionHandling>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
@ -69,17 +69,18 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</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\parsing_arrays.cpp" /> <ClCompile Include="..\tests\manipulating_parse_result.cpp" />
<ClCompile Include="..\tests\parsing_booleans.cpp" /> <ClCompile Include="..\tests\parsing_arrays.cpp" />
<ClCompile Include="..\tests\parsing_comments.cpp" /> <ClCompile Include="..\tests\parsing_booleans.cpp" />
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" /> <ClCompile Include="..\tests\parsing_comments.cpp" />
<ClCompile Include="..\tests\parsing_floats.cpp" /> <ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
<ClCompile Include="..\tests\parsing_integers.cpp" /> <ClCompile Include="..\tests\parsing_floats.cpp" />
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" /> <ClCompile Include="..\tests\parsing_integers.cpp" />
<ClCompile Include="..\tests\parsing_spec_example.cpp" /> <ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
<ClCompile Include="..\tests\parsing_strings.cpp" /> <ClCompile Include="..\tests\parsing_spec_example.cpp" />
<ClCompile Include="..\tests\parsing_tables.cpp" /> <ClCompile Include="..\tests\parsing_strings.cpp" />
<ClCompile Include="..\tests\parsing_tables.cpp" />
<ClCompile Include="..\tests\tests.cpp"> <ClCompile Include="..\tests\tests.cpp">
<PrecompiledHeader>Create</PrecompiledHeader> <PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile> </ClCompile>

View File

@ -68,7 +68,8 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</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,7 +70,8 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
</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" />