mirror of
https://github.com/marzer/tomlplusplus.git
synced 2024-09-04 14:09:11 +00:00
added copy construction/assignment for arrays. tables and values
In service of satisfying #49.
This commit is contained in:
parent
539aad89f4
commit
17d1876529
@ -316,3 +316,9 @@ pre > p.godbolt
|
||||
{
|
||||
float: right;
|
||||
}
|
||||
@media only screen and ((max-width: 575px) or ((hover: none) and (pointer: coarse)))
|
||||
{
|
||||
.godbolt {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -176,16 +176,13 @@ TOML_IMPL_NAMESPACE_START
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(returns_nonnull)
|
||||
TOML_ALWAYS_INLINE
|
||||
auto* make_node(T&& val) noexcept
|
||||
auto* make_node_specialized(T&& val) noexcept
|
||||
{
|
||||
using type = unwrap_node<remove_cvref_t<T>>;
|
||||
static_assert(!std::is_same_v<type, node>);
|
||||
|
||||
if constexpr (is_one_of<type, array, table>)
|
||||
{
|
||||
static_assert(
|
||||
std::is_rvalue_reference_v<decltype(val)>,
|
||||
"Tables and arrays may only be moved (not copied)."
|
||||
);
|
||||
return new type{ std::forward<T>(val) };
|
||||
}
|
||||
else
|
||||
@ -215,7 +212,23 @@ TOML_IMPL_NAMESPACE_START
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(returns_nonnull)
|
||||
TOML_ALWAYS_INLINE
|
||||
auto* make_node(T&& val) noexcept
|
||||
{
|
||||
using type = unwrap_node<remove_cvref_t<T>>;
|
||||
if constexpr (std::is_same_v<type, node>)
|
||||
{
|
||||
return std::forward<T>(val).visit([](auto&& concrete) noexcept
|
||||
{
|
||||
return static_cast<toml::node*>(make_node_specialized(std::forward<decltype(concrete)>(concrete)));
|
||||
});
|
||||
}
|
||||
else
|
||||
return make_node_specialized(std::forward<T>(val));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(returns_nonnull)
|
||||
auto* make_node(inserter<T>&& val) noexcept
|
||||
{
|
||||
return make_node(std::move(val.value));
|
||||
@ -308,10 +321,20 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD_CTOR
|
||||
array() noexcept;
|
||||
|
||||
/// \brief Copy constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
array(const array&) noexcept;
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
array(array&& other) noexcept;
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
array& operator= (const array&) noexcept;
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
array& operator= (array&& rhs) noexcept;
|
||||
|
||||
/// \brief Constructs an array with one or more initial elements.
|
||||
///
|
||||
/// \detail \cpp
|
||||
@ -345,7 +368,10 @@ TOML_NAMESPACE_START
|
||||
/// \tparam ElemTypes One of the TOML node or value types (or a type promotable to one).
|
||||
/// \param val The node or value used to initialize element 0.
|
||||
/// \param vals The nodes or values used to initialize elements 1...N.
|
||||
template <typename ElemType, typename... ElemTypes>
|
||||
template <typename ElemType, typename... ElemTypes, typename = std::enable_if_t<
|
||||
(sizeof...(ElemTypes) > 0_sz)
|
||||
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>
|
||||
>>
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit array(ElemType&& val, ElemTypes&&... vals)
|
||||
{
|
||||
@ -360,11 +386,6 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
array& operator= (array&& rhs) noexcept;
|
||||
|
||||
array(const array&) = delete;
|
||||
array& operator= (const array&) = delete;
|
||||
|
||||
/// \brief Always returns node_type::array for array nodes.
|
||||
[[nodiscard]] node_type type() const noexcept override;
|
||||
|
@ -19,6 +19,49 @@ TOML_DISABLE_PADDING_WARNINGS
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array() noexcept = default;
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(const array& other) noexcept
|
||||
: node{ other }
|
||||
{
|
||||
elements.reserve(other.elements.size());
|
||||
for (const auto& elem : other)
|
||||
elements.emplace_back(impl::make_node(elem));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
elements{ std::move(other.elements) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (const array& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
elements.clear();
|
||||
elements.reserve(rhs.elements.size());
|
||||
for (const auto& elem : rhs)
|
||||
elements.emplace_back(impl::make_node(elem));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (array&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
elements = std::move(rhs.elements);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::preinsertion_resize(size_t idx, size_t count) noexcept
|
||||
{
|
||||
@ -35,23 +78,6 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array() noexcept = default;
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
elements{ std::move(other.elements) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (array&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
elements = std::move(rhs.elements);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
|
||||
|
||||
TOML_MEMBER_ATTR(const) node_type array::type() const noexcept { return node_type::array; }
|
||||
|
@ -75,7 +75,10 @@ TOML_NAMESPACE_START
|
||||
|
||||
protected:
|
||||
|
||||
node() noexcept = default;
|
||||
node(const node&) noexcept = default;
|
||||
node(node&& other) noexcept;
|
||||
node& operator= (const node&) noexcept = default;
|
||||
node& operator= (node&& rhs) noexcept;
|
||||
|
||||
template <typename T>
|
||||
@ -105,10 +108,6 @@ TOML_NAMESPACE_START
|
||||
template <typename N, typename T>
|
||||
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
|
||||
|
||||
node() noexcept = default;
|
||||
node(const node&) = delete;
|
||||
node& operator= (const node&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~node() noexcept = default;
|
||||
|
@ -229,6 +229,20 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD_CTOR
|
||||
table() noexcept;
|
||||
|
||||
/// \brief Copy constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
table(const table&) noexcept;
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
table(table&& other) noexcept;
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
table& operator= (const table&) noexcept;
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
table& operator= (table&& rhs) noexcept;
|
||||
|
||||
/// \brief Constructs a table with one or more initial key-value pairs.
|
||||
///
|
||||
/// \detail \cpp
|
||||
@ -264,15 +278,6 @@ TOML_NAMESPACE_START
|
||||
: table{ arr, N }
|
||||
{}
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
table(table&& other) noexcept;
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
table& operator= (table&& rhs) noexcept;
|
||||
|
||||
table(const table&) = delete;
|
||||
table& operator= (const table&) = delete;
|
||||
|
||||
/// \brief Always returns `node_type::table` for table nodes.
|
||||
[[nodiscard]] node_type type() const noexcept override;
|
||||
|
@ -21,19 +21,16 @@ TOML_DISABLE_PADDING_WARNINGS
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(impl::table_init_pair* pairs, size_t count) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
map.insert_or_assign(
|
||||
std::move(pairs[i].key),
|
||||
std::move(pairs[i].value)
|
||||
);
|
||||
}
|
||||
}
|
||||
table::table() noexcept {}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table() noexcept {}
|
||||
table::table(const table& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
inline_{ other.inline_ }
|
||||
{
|
||||
for (auto&& [k, v] : other)
|
||||
map.emplace_hint(map.end(), k, impl::make_node(v));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(table&& other) noexcept
|
||||
@ -43,14 +40,43 @@ TOML_NAMESPACE_START
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator = (table&& rhs) noexcept
|
||||
table& table::operator= (const table& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
map = std::move(rhs.map);
|
||||
inline_ = rhs.inline_;
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
map.clear();
|
||||
for (auto&& [k, v] : rhs)
|
||||
map.emplace_hint(map.end(), k, impl::make_node(v));
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator= (table&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
map = std::move(rhs.map);
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(impl::table_init_pair* pairs, size_t count) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
map.insert_or_assign(
|
||||
std::move(pairs[i].key),
|
||||
std::move(pairs[i].value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
|
||||
|
||||
TOML_MEMBER_ATTR(const) node_type table::type() const noexcept { return node_type::table; }
|
||||
|
@ -173,6 +173,13 @@ TOML_NAMESPACE_START
|
||||
: val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(std::forward<Args>(args)...))
|
||||
{}
|
||||
|
||||
/// \brief Copy constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(const value& other) noexcept
|
||||
: node{ other },
|
||||
val_{ other.val_ }
|
||||
{}
|
||||
|
||||
/// \brief Move constructor.
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other) noexcept
|
||||
@ -180,16 +187,24 @@ TOML_NAMESPACE_START
|
||||
val_{ std::move(other.val_) }
|
||||
{}
|
||||
|
||||
/// \brief Move-assignment operator.
|
||||
value& operator= (value&& rhs) noexcept
|
||||
/// \brief Copy-assignment operator.
|
||||
value& operator= (const value& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
node::operator=(rhs);
|
||||
val_ = rhs.val_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
value(const value&) = delete;
|
||||
value& operator= (const value&) = delete;
|
||||
/// \brief Move-assignment operator.
|
||||
value& operator= (value&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Returns the value's node type identifier.
|
||||
///
|
||||
|
@ -14,12 +14,7 @@ TEST_CASE("arrays - moving")
|
||||
R"(test = [ "foo" ])"sv,
|
||||
[&](table&& tbl)
|
||||
{
|
||||
CHECK(tbl.source().begin == source_position{ 1, 1 });
|
||||
CHECK(tbl.source().end == source_position{ 1, 17 });
|
||||
CHECK(tbl.source().path);
|
||||
CHECK(*tbl.source().path == filename);
|
||||
CHECK(tbl.size() == 1_sz);
|
||||
|
||||
// sanity-check initial state of a freshly-parsed array
|
||||
auto arr1 = tbl["test"].as<array>();
|
||||
REQUIRE(arr1);
|
||||
CHECK(arr1->size() == 1_sz);
|
||||
@ -30,12 +25,14 @@ TEST_CASE("arrays - moving")
|
||||
REQUIRE(arr1->get_as<std::string>(0_sz));
|
||||
CHECK(*arr1->get_as<std::string>(0_sz) == "foo"sv);
|
||||
|
||||
// sanity-check initial state of default-constructed array
|
||||
array arr2;
|
||||
CHECK(arr2.source().begin == source_position{});
|
||||
CHECK(arr2.source().end == source_position{});
|
||||
CHECK(!arr2.source().path);
|
||||
CHECK(arr2.size() == 0_sz);
|
||||
|
||||
// check the results of move-assignment
|
||||
arr2 = std::move(*arr1);
|
||||
CHECK(arr2.source().begin == source_position{ 1, 8 });
|
||||
CHECK(arr2.source().end == source_position{ 1, 17 });
|
||||
@ -45,14 +42,84 @@ TEST_CASE("arrays - moving")
|
||||
REQUIRE(arr2.get_as<std::string>(0_sz));
|
||||
CHECK(*arr2.get_as<std::string>(0_sz) == "foo"sv);
|
||||
|
||||
// check that moved-from array is now the same as default-constructed
|
||||
CHECK(arr1->source().begin == source_position{});
|
||||
CHECK(arr1->source().end == source_position{});
|
||||
CHECK(!arr1->source().path);
|
||||
CHECK(arr1->size() == 0_sz);
|
||||
|
||||
// check the results of move-construction
|
||||
array arr3{ std::move(arr2) };
|
||||
CHECK(arr3.source().begin == source_position{ 1, 8 });
|
||||
CHECK(arr3.source().end == source_position{ 1, 17 });
|
||||
CHECK(arr3.source().path);
|
||||
CHECK(*arr3.source().path == filename);
|
||||
CHECK(arr3.size() == 1_sz);
|
||||
REQUIRE(arr3.get_as<std::string>(0_sz));
|
||||
CHECK(*arr3.get_as<std::string>(0_sz) == "foo"sv);
|
||||
|
||||
// check that moved-from array is now the same as default-constructed
|
||||
CHECK(arr2.source().begin == source_position{});
|
||||
CHECK(arr2.source().end == source_position{});
|
||||
CHECK(!arr2.source().path);
|
||||
CHECK(arr2.size() == 0_sz);
|
||||
},
|
||||
filename
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("arrays - copying")
|
||||
{
|
||||
static constexpr auto filename = "foo.toml"sv;
|
||||
|
||||
parsing_should_succeed(
|
||||
FILE_LINE_ARGS,
|
||||
R"(test = [ "foo" ])"sv,
|
||||
[&](table&& tbl)
|
||||
{
|
||||
// sanity-check initial state of a freshly-parsed array
|
||||
auto arr1 = tbl["test"].as<array>();
|
||||
REQUIRE(arr1);
|
||||
CHECK(arr1->size() == 1_sz);
|
||||
CHECK(arr1->source().begin == source_position{ 1, 8 });
|
||||
CHECK(arr1->source().end == source_position{ 1, 17 });
|
||||
CHECK(arr1->source().path);
|
||||
CHECK(*arr1->source().path == filename);
|
||||
REQUIRE(arr1->get_as<std::string>(0_sz));
|
||||
CHECK(*arr1->get_as<std::string>(0_sz) == "foo"sv);
|
||||
|
||||
// sanity-check initial state of default-constructed array
|
||||
array arr2;
|
||||
CHECK(arr2.source().begin == source_position{});
|
||||
CHECK(arr2.source().end == source_position{});
|
||||
CHECK(!arr2.source().path);
|
||||
CHECK(arr2.size() == 0_sz);
|
||||
|
||||
// check the results of copy-assignment
|
||||
arr2 = *arr1;
|
||||
CHECK(arr2.source().begin == source_position{ 1, 8 });
|
||||
CHECK(arr2.source().end == source_position{ 1, 17 });
|
||||
CHECK(arr2.source().path);
|
||||
CHECK(*arr2.source().path == filename);
|
||||
CHECK(arr2.size() == 1_sz);
|
||||
REQUIRE(arr2.get_as<std::string>(0_sz));
|
||||
CHECK(*arr2.get_as<std::string>(0_sz) == "foo"sv);
|
||||
CHECK(arr2 == *arr1);
|
||||
|
||||
// check the results of copy-construction
|
||||
array arr3{ arr2 };
|
||||
CHECK(arr3.source().begin == source_position{ 1, 8 });
|
||||
CHECK(arr3.source().end == source_position{ 1, 17 });
|
||||
CHECK(arr3.source().path);
|
||||
CHECK(*arr3.source().path == filename);
|
||||
CHECK(arr3.size() == 1_sz);
|
||||
REQUIRE(arr3.get_as<std::string>(0_sz));
|
||||
CHECK(*arr3.get_as<std::string>(0_sz) == "foo"sv);
|
||||
CHECK(arr3 == *arr1);
|
||||
CHECK(arr3 == arr2);
|
||||
},
|
||||
filename
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("arrays - construction")
|
||||
|
@ -14,19 +14,22 @@ TEST_CASE("tables - moving")
|
||||
R"(test = { val1 = "foo" })"sv,
|
||||
[&](table&& tbl)
|
||||
{
|
||||
CHECK(tbl.source().begin == source_position{ 1, 1 });
|
||||
CHECK(tbl.source().end == source_position{ 1, 24 });
|
||||
CHECK(tbl.source().path);
|
||||
CHECK(*tbl.source().path == filename);
|
||||
CHECK(tbl.size() == 1_sz);
|
||||
|
||||
// sanity-check initial state of a freshly-parsed table
|
||||
REQUIRE(tbl["test"].as<table>());
|
||||
CHECK(tbl["test"].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl["test"].as<table>()->source().begin == source_position{ 1, 8 });
|
||||
CHECK(tbl["test"].as<table>()->source().end == source_position{ 1, 24 });
|
||||
CHECK(tbl["test"]["val1"] == "foo");
|
||||
|
||||
table tbl2 = std::move(tbl);
|
||||
// sanity-check initial state of default-constructed table
|
||||
table tbl2;
|
||||
CHECK(tbl2.source().begin == source_position{});
|
||||
CHECK(tbl2.source().end == source_position{});
|
||||
CHECK(!tbl2.source().path);
|
||||
CHECK(tbl2.size() == 0_sz);
|
||||
|
||||
// check the results of move-assignment
|
||||
tbl2 = std::move(tbl);
|
||||
CHECK(tbl2.source().begin == source_position{ 1, 1 });
|
||||
CHECK(tbl2.source().end == source_position{ 1, 24 });
|
||||
CHECK(tbl2.source().path);
|
||||
@ -36,11 +39,82 @@ TEST_CASE("tables - moving")
|
||||
CHECK(tbl2["test"].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl2["test"]["val1"] == "foo"sv);
|
||||
|
||||
// check that moved-from table is now the same as default-constructed
|
||||
CHECK(tbl.source().begin == source_position{});
|
||||
CHECK(tbl.source().end == source_position{});
|
||||
CHECK(!tbl.source().path);
|
||||
CHECK(tbl.size() == 0_sz);
|
||||
CHECK(!tbl["test"].as<table>());
|
||||
|
||||
// check the results of move-construction
|
||||
table tbl3{ std::move(tbl2) };
|
||||
CHECK(tbl3.source().begin == source_position{ 1, 1 });
|
||||
CHECK(tbl3.source().end == source_position{ 1, 24 });
|
||||
CHECK(tbl3.source().path);
|
||||
CHECK(*tbl3.source().path == filename);
|
||||
CHECK(tbl3.size() == 1_sz);
|
||||
REQUIRE(tbl3["test"].as<table>());
|
||||
CHECK(tbl3["test"].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl3["test"]["val1"] == "foo"sv);
|
||||
|
||||
// check that moved-from table is now the same as default-constructed
|
||||
CHECK(tbl2.source().begin == source_position{});
|
||||
CHECK(tbl2.source().end == source_position{});
|
||||
CHECK(!tbl2.source().path);
|
||||
CHECK(tbl2.size() == 0_sz);
|
||||
CHECK(!tbl2["test"].as<table>());
|
||||
},
|
||||
filename
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("tables - copying")
|
||||
{
|
||||
static constexpr auto filename = "foo.toml"sv;
|
||||
|
||||
parsing_should_succeed(
|
||||
FILE_LINE_ARGS,
|
||||
R"(test = { val1 = "foo" })"sv,
|
||||
[&](table&& tbl)
|
||||
{
|
||||
// sanity-check initial state of a freshly-parsed table
|
||||
REQUIRE(tbl["test"].as<table>());
|
||||
CHECK(tbl["test"].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl["test"].as<table>()->source().begin == source_position{ 1, 8 });
|
||||
CHECK(tbl["test"].as<table>()->source().end == source_position{ 1, 24 });
|
||||
CHECK(tbl["test"]["val1"] == "foo");
|
||||
|
||||
// sanity-check initial state of default-constructed table
|
||||
table tbl2;
|
||||
CHECK(tbl2.source().begin == source_position{});
|
||||
CHECK(tbl2.source().end == source_position{});
|
||||
CHECK(!tbl2.source().path);
|
||||
CHECK(tbl2.size() == 0_sz);
|
||||
|
||||
// check the results of copy-assignment
|
||||
tbl2 = tbl;
|
||||
CHECK(tbl2.source().begin == source_position{ 1, 1 });
|
||||
CHECK(tbl2.source().end == source_position{ 1, 24 });
|
||||
CHECK(tbl2.source().path);
|
||||
CHECK(*tbl2.source().path == filename);
|
||||
CHECK(tbl2.size() == 1_sz);
|
||||
REQUIRE(tbl2["test"].as<table>());
|
||||
CHECK(tbl2["test"].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl2["test"]["val1"] == "foo"sv);
|
||||
CHECK(tbl2 == tbl);
|
||||
|
||||
// check the results of copy-construction
|
||||
table tbl3{ tbl2 };
|
||||
CHECK(tbl3.source().begin == source_position{ 1, 1 });
|
||||
CHECK(tbl3.source().end == source_position{ 1, 24 });
|
||||
CHECK(tbl3.source().path);
|
||||
CHECK(*tbl3.source().path == filename);
|
||||
CHECK(tbl3.size() == 1_sz);
|
||||
REQUIRE(tbl3["test"].as<table>());
|
||||
CHECK(tbl3["test"].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl3["test"]["val1"] == "foo"sv);
|
||||
CHECK(tbl3 == tbl2);
|
||||
CHECK(tbl3 == tbl);
|
||||
},
|
||||
filename
|
||||
);
|
||||
|
@ -75,11 +75,11 @@ TEST_CASE("values - construction")
|
||||
CHECK_VALUE_INIT2(one<DWORDLONG>, int64_t, 1u);
|
||||
|
||||
#if TOML_WINDOWS_COMPAT
|
||||
|
||||
CHECK_VALUE_INIT2(L"kek", std::string, "kek"sv);
|
||||
CHECK_VALUE_INIT2(L"kek"s, std::string, "kek"sv);
|
||||
CHECK_VALUE_INIT2(L"kek"sv, std::string, "kek"sv);
|
||||
CHECK_VALUE_INIT2(L"kek"sv.data(), std::string, "kek"sv);
|
||||
|
||||
CHECK_VALUE_INIT2(L"kek", std::string, "kek"sv);
|
||||
CHECK_VALUE_INIT2(L"kek"s, std::string, "kek"sv);
|
||||
CHECK_VALUE_INIT2(L"kek"sv, std::string, "kek"sv);
|
||||
CHECK_VALUE_INIT2(L"kek"sv.data(), std::string, "kek"sv);
|
||||
|
||||
#endif // TOML_WINDOWS_COMPAT
|
||||
|
||||
|
205
toml.hpp
205
toml.hpp
@ -2087,7 +2087,10 @@ TOML_NAMESPACE_START
|
||||
|
||||
protected:
|
||||
|
||||
node() noexcept = default;
|
||||
node(const node&) noexcept = default;
|
||||
node(node&& other) noexcept;
|
||||
node& operator= (const node&) noexcept = default;
|
||||
node& operator= (node&& rhs) noexcept;
|
||||
|
||||
template <typename T>
|
||||
@ -2117,10 +2120,6 @@ TOML_NAMESPACE_START
|
||||
template <typename N, typename T>
|
||||
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
|
||||
|
||||
node() noexcept = default;
|
||||
node(const node&) = delete;
|
||||
node& operator= (const node&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~node() noexcept = default;
|
||||
@ -2618,21 +2617,34 @@ TOML_NAMESPACE_START
|
||||
: val_(impl::native_value_maker<value_type, std::decay_t<Args>...>::make(std::forward<Args>(args)...))
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
value(const value& other) noexcept
|
||||
: node{ other },
|
||||
val_{ other.val_ }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
val_{ std::move(other.val_) }
|
||||
{}
|
||||
|
||||
value& operator= (value&& rhs) noexcept
|
||||
value& operator= (const value& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
node::operator=(rhs);
|
||||
val_ = rhs.val_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
value(const value&) = delete;
|
||||
value& operator= (const value&) = delete;
|
||||
value& operator= (value&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] node_type type() const noexcept override { return impl::node_type_of<value_type>; }
|
||||
[[nodiscard]] bool is_table() const noexcept override { return false; }
|
||||
@ -3384,16 +3396,13 @@ TOML_IMPL_NAMESPACE_START
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(returns_nonnull)
|
||||
TOML_ALWAYS_INLINE
|
||||
auto* make_node(T&& val) noexcept
|
||||
auto* make_node_specialized(T&& val) noexcept
|
||||
{
|
||||
using type = unwrap_node<remove_cvref_t<T>>;
|
||||
static_assert(!std::is_same_v<type, node>);
|
||||
|
||||
if constexpr (is_one_of<type, array, table>)
|
||||
{
|
||||
static_assert(
|
||||
std::is_rvalue_reference_v<decltype(val)>,
|
||||
"Tables and arrays may only be moved (not copied)."
|
||||
);
|
||||
return new type{ std::forward<T>(val) };
|
||||
}
|
||||
else
|
||||
@ -3423,7 +3432,23 @@ TOML_IMPL_NAMESPACE_START
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(returns_nonnull)
|
||||
TOML_ALWAYS_INLINE
|
||||
auto* make_node(T&& val) noexcept
|
||||
{
|
||||
using type = unwrap_node<remove_cvref_t<T>>;
|
||||
if constexpr (std::is_same_v<type, node>)
|
||||
{
|
||||
return std::forward<T>(val).visit([](auto&& concrete) noexcept
|
||||
{
|
||||
return static_cast<toml::node*>(make_node_specialized(std::forward<decltype(concrete)>(concrete)));
|
||||
});
|
||||
}
|
||||
else
|
||||
return make_node_specialized(std::forward<T>(val));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
TOML_ATTR(returns_nonnull)
|
||||
auto* make_node(inserter<T>&& val) noexcept
|
||||
{
|
||||
return make_node(std::move(val.value));
|
||||
@ -3459,9 +3484,17 @@ TOML_NAMESPACE_START
|
||||
array() noexcept;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
array(array&& other) noexcept;
|
||||
array(const array&) noexcept;
|
||||
|
||||
template <typename ElemType, typename... ElemTypes>
|
||||
TOML_NODISCARD_CTOR
|
||||
array(array&& other) noexcept;
|
||||
array& operator= (const array&) noexcept;
|
||||
array& operator= (array&& rhs) noexcept;
|
||||
|
||||
template <typename ElemType, typename... ElemTypes, typename = std::enable_if_t<
|
||||
(sizeof...(ElemTypes) > 0_sz)
|
||||
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>
|
||||
>>
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit array(ElemType&& val, ElemTypes&&... vals)
|
||||
{
|
||||
@ -3476,11 +3509,6 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
array& operator= (array&& rhs) noexcept;
|
||||
|
||||
array(const array&) = delete;
|
||||
array& operator= (const array&) = delete;
|
||||
|
||||
[[nodiscard]] node_type type() const noexcept override;
|
||||
[[nodiscard]] bool is_table() const noexcept override;
|
||||
[[nodiscard]] bool is_array() const noexcept override;
|
||||
@ -3950,19 +3978,20 @@ TOML_NAMESPACE_START
|
||||
TOML_NODISCARD_CTOR
|
||||
table() noexcept;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
table(const table&) noexcept;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
table(table&& other) noexcept;
|
||||
table& operator= (const table&) noexcept;
|
||||
table& operator= (table&& rhs) noexcept;
|
||||
|
||||
template <size_t N>
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit table(impl::table_init_pair(&& arr)[N]) noexcept
|
||||
: table{ arr, N }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
table(table&& other) noexcept;
|
||||
table& operator= (table&& rhs) noexcept;
|
||||
|
||||
table(const table&) = delete;
|
||||
table& operator= (const table&) = delete;
|
||||
|
||||
[[nodiscard]] node_type type() const noexcept override;
|
||||
[[nodiscard]] bool is_table() const noexcept override;
|
||||
[[nodiscard]] bool is_array() const noexcept override;
|
||||
@ -7294,6 +7323,49 @@ TOML_DISABLE_PADDING_WARNINGS
|
||||
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array() noexcept = default;
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(const array& other) noexcept
|
||||
: node{ other }
|
||||
{
|
||||
elements.reserve(other.elements.size());
|
||||
for (const auto& elem : other)
|
||||
elements.emplace_back(impl::make_node(elem));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
elements{ std::move(other.elements) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (const array& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
elements.clear();
|
||||
elements.reserve(rhs.elements.size());
|
||||
for (const auto& elem : rhs)
|
||||
elements.emplace_back(impl::make_node(elem));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (array&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
elements = std::move(rhs.elements);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
void array::preinsertion_resize(size_t idx, size_t count) noexcept
|
||||
{
|
||||
@ -7310,23 +7382,6 @@ TOML_NAMESPACE_START
|
||||
}
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array() noexcept = default;
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array::array(array&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
elements{ std::move(other.elements) }
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
array& array::operator= (array&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
elements = std::move(rhs.elements);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
|
||||
|
||||
TOML_MEMBER_ATTR(const) node_type array::type() const noexcept { return node_type::array; }
|
||||
@ -7550,19 +7605,16 @@ TOML_DISABLE_PADDING_WARNINGS
|
||||
TOML_NAMESPACE_START
|
||||
{
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(impl::table_init_pair* pairs, size_t count) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
map.insert_or_assign(
|
||||
std::move(pairs[i].key),
|
||||
std::move(pairs[i].value)
|
||||
);
|
||||
}
|
||||
}
|
||||
table::table() noexcept {}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table() noexcept {}
|
||||
table::table(const table& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
inline_{ other.inline_ }
|
||||
{
|
||||
for (auto&& [k, v] : other)
|
||||
map.emplace_hint(map.end(), k, impl::make_node(v));
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(table&& other) noexcept
|
||||
@ -7572,14 +7624,43 @@ TOML_NAMESPACE_START
|
||||
{}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator = (table&& rhs) noexcept
|
||||
table& table::operator= (const table& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
map = std::move(rhs.map);
|
||||
inline_ = rhs.inline_;
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(rhs);
|
||||
map.clear();
|
||||
for (auto&& [k, v] : rhs)
|
||||
map.emplace_hint(map.end(), k, impl::make_node(v));
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table& table::operator= (table&& rhs) noexcept
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
map = std::move(rhs.map);
|
||||
inline_ = rhs.inline_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TOML_EXTERNAL_LINKAGE
|
||||
table::table(impl::table_init_pair* pairs, size_t count) noexcept
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
map.insert_or_assign(
|
||||
std::move(pairs[i].key),
|
||||
std::move(pairs[i].value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#define TOML_MEMBER_ATTR(attr) TOML_EXTERNAL_LINKAGE TOML_ATTR(attr)
|
||||
|
||||
TOML_MEMBER_ATTR(const) node_type table::type() const noexcept { return node_type::table; }
|
||||
|
@ -95,12 +95,12 @@
|
||||
</Type>
|
||||
|
||||
<Type Name="toml::v2::table">
|
||||
<DisplayString>{values}</DisplayString>
|
||||
<DisplayString>{map}</DisplayString>
|
||||
<Expand>
|
||||
<!-- Modified from std::map visualizer in VS 2019 stl.natvis -->
|
||||
<TreeItems>
|
||||
<Size>values._Mypair._Myval2._Myval2._Mysize</Size>
|
||||
<HeadPointer>values._Mypair._Myval2._Myval2._Myhead->_Parent</HeadPointer>
|
||||
<Size>map._Mypair._Myval2._Myval2._Mysize</Size>
|
||||
<HeadPointer>map._Mypair._Myval2._Myval2._Myhead->_Parent</HeadPointer>
|
||||
<LeftPointer>_Left</LeftPointer>
|
||||
<RightPointer>_Right</RightPointer>
|
||||
<ValueNode Condition="_Isnil == 0" Name="[{_Myval.first,s8}]">*_Myval.second</ValueNode>
|
||||
@ -109,12 +109,12 @@
|
||||
</Type>
|
||||
|
||||
<Type Name="toml::v2::array">
|
||||
<DisplayString>{values}</DisplayString>
|
||||
<DisplayString>{elements}</DisplayString>
|
||||
<Expand>
|
||||
<!-- Modified from std::vector visualizer in VS 2019 stl.natvis -->
|
||||
<IndexListItems>
|
||||
<Size>values._Mypair._Myval2._Mylast - values._Mypair._Myval2._Myfirst</Size>
|
||||
<ValueNode>*values._Mypair._Myval2._Myfirst[$i]</ValueNode>
|
||||
<Size>elements._Mypair._Myval2._Mylast - elements._Mypair._Myval2._Myfirst</Size>
|
||||
<ValueNode>*elements._Mypair._Myval2._Myfirst[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
Loading…
Reference in New Issue
Block a user