fixed value_flags
not preserved during insertion (#108)
also: - fixed `toml::value::flags()` not being cleared when `std::move`-ing a value - fixed #195
This commit is contained in:
parent
7eb2ffcc09
commit
2414d904a8
10
CHANGELOG.md
10
CHANGELOG.md
@ -21,6 +21,16 @@ template:
|
||||
|
||||
-->
|
||||
|
||||
## Unreleased
|
||||
|
||||
#### Fixes
|
||||
|
||||
- fixed `value_flags` not being preserved correctly when inserting into tables and arrays (#108) (@LebJe)
|
||||
- fixed `toml::value::flags()` not being cleared when `std::move`-ing a value
|
||||
- fixed error in README (#195) (@andrewkcorcoran)
|
||||
|
||||
<br><br>
|
||||
|
||||
## v3.3.0
|
||||
|
||||
[Released](https://github.com/marzer/tomlplusplus/releases/tag/v3.3.0) 2023-01-29
|
||||
|
@ -177,12 +177,8 @@ FetchContent_MakeAvailable(tomlplusplus)
|
||||
|
||||
```plaintext
|
||||
git submodule add --depth 1 https://github.com/marzer/tomlplusplus.git tomlplusplus
|
||||
git config -f .gitmodules submodule.tomlplusplus.shallow true
|
||||
```
|
||||
|
||||
> ⚠️ The toml++ repository has some submodules of its own, but **they are only used for testing**!
|
||||
> You should **not** use the `--recursive` option for regular library consumption.
|
||||
|
||||
### Other environments and package managers
|
||||
|
||||
The C++ tooling ecosystem is a fractal nightmare of unbridled chaos so naturally I'm not up-to-speed with all of the
|
||||
|
@ -366,7 +366,7 @@ TOML_NAMESPACE_START // abi namespace
|
||||
T value;
|
||||
};
|
||||
template <typename T>
|
||||
inserter(T &&) -> inserter<T&&>;
|
||||
inserter(T&&) -> inserter<T&&>;
|
||||
template <typename T>
|
||||
inserter(T&) -> inserter<T&>;
|
||||
|
||||
|
@ -36,7 +36,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
// copy/move ctor
|
||||
if constexpr (std::is_same_v<remove_cvref<T>, value_type>)
|
||||
{
|
||||
out = new value_type{ static_cast<T&&>(val) };
|
||||
out = new value_type{ static_cast<T&&>(val), flags };
|
||||
}
|
||||
|
||||
// creating from raw value
|
||||
|
@ -473,11 +473,11 @@ TOML_ANON_NAMESPACE_START
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_string_view<Char>, std::string_view) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_string_view<Char>, std::string &&) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
utf8_reader(std::basic_string_view<Char>, std::string&&) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_istream<Char>&, std::string_view) -> utf8_reader<std::basic_istream<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_istream<Char>&, std::string &&) -> utf8_reader<std::basic_istream<Char>>;
|
||||
utf8_reader(std::basic_istream<Char>&, std::string&&) -> utf8_reader<std::basic_istream<Char>>;
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
#define utf8_buffered_reader_error_check(...) static_assert(true)
|
||||
|
@ -168,7 +168,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
const auto type = state_table[byte];
|
||||
|
||||
codepoint = static_cast<char32_t>(has_code_point() ? (uint_least32_t{ 255u } >> type) & byte
|
||||
: (byte & uint_least32_t{ 63u })
|
||||
: (byte& uint_least32_t{ 63u })
|
||||
| (static_cast<uint_least32_t>(codepoint) << 6));
|
||||
|
||||
state = state_table[state + uint_least32_t{ 256u } + type];
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "date_time.h"
|
||||
#include "node.h"
|
||||
#include "print_to_stream.h"
|
||||
#include "std_utility.h"
|
||||
#include "header_start.h"
|
||||
TOML_DISABLE_ARITHMETIC_WARNINGS;
|
||||
|
||||
@ -192,6 +193,16 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
return { static_cast<T>(val) };
|
||||
}
|
||||
|
||||
template <typename...>
|
||||
struct is_val_ctor_with_flags : std::false_type
|
||||
{};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_val_ctor_with_flags<T, U> : std::bool_constant< //
|
||||
(is_node<T> && is_value<T>) //
|
||||
&&(std::is_same_v<remove_cvref<U>, value_flags>)>
|
||||
{};
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
/// \endcond
|
||||
@ -253,7 +264,7 @@ TOML_NAMESPACE_START
|
||||
///
|
||||
/// \tparam Args Constructor argument types.
|
||||
/// \param args Arguments to forward to the internal value's constructor.
|
||||
template <typename... Args>
|
||||
TOML_HIDDEN_CONSTRAINT(!impl::is_val_ctor_with_flags<Args...>::value, typename... Args)
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit value(Args&&... args) noexcept(noexcept(value_type(
|
||||
impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...))))
|
||||
@ -293,7 +304,7 @@ TOML_NAMESPACE_START
|
||||
value(value&& other) noexcept //
|
||||
: node(std::move(other)),
|
||||
val_{ std::move(other.val_) },
|
||||
flags_{ other.flags_ }
|
||||
flags_{ std::exchange(other.flags_, value_flags{}) }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
@ -310,6 +321,7 @@ TOML_NAMESPACE_START
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
#endif
|
||||
other.flags_ = {};
|
||||
}
|
||||
|
||||
/// \brief Copy-assignment operator.
|
||||
@ -328,7 +340,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
flags_ = rhs.flags_;
|
||||
flags_ = std::exchange(rhs.flags_, value_flags{});
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -968,6 +980,8 @@ TOML_NAMESPACE_START
|
||||
|
||||
template <typename T>
|
||||
value(T) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
|
||||
template <typename T>
|
||||
value(T, value_flags) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
|
@ -453,6 +453,23 @@ TEST_CASE("arrays - insertion and erasure")
|
||||
CHECK(*arr.back().as_string() == "test4"sv);
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
// push_back with value_flags
|
||||
{
|
||||
arr.clear();
|
||||
|
||||
auto hex = toml::value{ 1 };
|
||||
hex.flags(value_flags::format_as_hexadecimal);
|
||||
CHECK(hex.flags() == value_flags::format_as_hexadecimal);
|
||||
|
||||
arr.push_back(hex);
|
||||
CHECK(hex.flags() == value_flags::format_as_hexadecimal);
|
||||
CHECK(arr.back().as_integer()->flags() == value_flags::format_as_hexadecimal);
|
||||
|
||||
arr.push_back(std::move(hex));
|
||||
CHECK(hex.flags() == value_flags{});
|
||||
CHECK(arr.back().as_integer()->flags() == value_flags::format_as_hexadecimal);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("arrays - flattening")
|
||||
@ -534,3 +551,75 @@ TEST_CASE("arrays - resizing and truncation")
|
||||
CHECK(arr.size() == 6u);
|
||||
CHECK(arr == array{ 1, 2, 42, 42, 42, 42 });
|
||||
}
|
||||
|
||||
TEST_CASE("arrays - for_each")
|
||||
{
|
||||
const auto arr = array{ 1, 2.0, 3, "four", false };
|
||||
|
||||
SECTION("type checking")
|
||||
{
|
||||
int count = 0;
|
||||
int ints = 0;
|
||||
int floats = 0;
|
||||
int numbers = 0;
|
||||
int strings = 0;
|
||||
int bools = 0;
|
||||
arr.for_each(
|
||||
[&](const auto& v) noexcept
|
||||
{
|
||||
count++;
|
||||
if constexpr (toml::is_integer<decltype(v)>)
|
||||
ints++;
|
||||
if constexpr (toml::is_floating_point<decltype(v)>)
|
||||
floats++;
|
||||
if constexpr (toml::is_number<decltype(v)>)
|
||||
numbers++;
|
||||
if constexpr (toml::is_string<decltype(v)>)
|
||||
strings++;
|
||||
if constexpr (toml::is_boolean<decltype(v)>)
|
||||
bools++;
|
||||
});
|
||||
CHECK(count == 5);
|
||||
CHECK(ints == 2);
|
||||
CHECK(floats == 1);
|
||||
CHECK(numbers == (ints + floats));
|
||||
CHECK(strings == 1);
|
||||
CHECK(bools == 1);
|
||||
}
|
||||
|
||||
SECTION("early-exit (elem, index)")
|
||||
{
|
||||
int count = 0;
|
||||
arr.for_each(
|
||||
[&](const auto& elem, size_t /*idx*/) noexcept -> bool
|
||||
{
|
||||
count++;
|
||||
return !toml::is_string<decltype(elem)>;
|
||||
});
|
||||
CHECK(count == 4);
|
||||
}
|
||||
|
||||
SECTION("early-exit (elem)")
|
||||
{
|
||||
int count = 0;
|
||||
arr.for_each(
|
||||
[&](const auto& elem) noexcept -> bool
|
||||
{
|
||||
count++;
|
||||
return !toml::is_string<decltype(elem)>;
|
||||
});
|
||||
CHECK(count == 4);
|
||||
}
|
||||
|
||||
SECTION("early-exit (index, elem)")
|
||||
{
|
||||
int count = 0;
|
||||
arr.for_each(
|
||||
[&](size_t /*idx*/, const auto& elem) noexcept -> bool
|
||||
{
|
||||
count++;
|
||||
return !toml::is_string<decltype(elem)>;
|
||||
});
|
||||
CHECK(count == 4);
|
||||
}
|
||||
}
|
||||
|
@ -403,6 +403,23 @@ TEST_CASE("tables - insertion and erasure")
|
||||
CHECK(tbl.size() == 0u);
|
||||
|
||||
#endif // TOML_ENABLE_WINDOWS_COMPAT
|
||||
|
||||
// insert with value_flags
|
||||
{
|
||||
tbl.clear();
|
||||
|
||||
auto hex = toml::value{ 1 };
|
||||
hex.flags(value_flags::format_as_hexadecimal);
|
||||
CHECK(hex.flags() == value_flags::format_as_hexadecimal);
|
||||
|
||||
tbl.insert("hex", hex);
|
||||
CHECK(hex.flags() == value_flags::format_as_hexadecimal);
|
||||
CHECK(tbl["hex"].as_integer()->flags() == value_flags::format_as_hexadecimal);
|
||||
|
||||
tbl.insert("hex2", std::move(hex));
|
||||
CHECK(hex.flags() == value_flags{});
|
||||
CHECK(tbl["hex2"].as_integer()->flags() == value_flags::format_as_hexadecimal);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("tables - toml_formatter")
|
||||
@ -599,3 +616,53 @@ key8 = [
|
||||
== expected_without_indentation);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("tables - for_each")
|
||||
{
|
||||
const auto tbl = table{ { "a", 1 }, { "b", 2.0 }, { "c", 3 }, { "d", "four" }, { "e", false } };
|
||||
|
||||
SECTION("type checking")
|
||||
{
|
||||
int count = 0;
|
||||
int ints = 0;
|
||||
int floats = 0;
|
||||
int numbers = 0;
|
||||
int strings = 0;
|
||||
int bools = 0;
|
||||
tbl.for_each(
|
||||
[&](const auto& v) noexcept
|
||||
{
|
||||
count++;
|
||||
if constexpr (toml::is_integer<decltype(v)>)
|
||||
ints++;
|
||||
if constexpr (toml::is_floating_point<decltype(v)>)
|
||||
floats++;
|
||||
if constexpr (toml::is_number<decltype(v)>)
|
||||
numbers++;
|
||||
if constexpr (toml::is_string<decltype(v)>)
|
||||
strings++;
|
||||
if constexpr (toml::is_boolean<decltype(v)>)
|
||||
bools++;
|
||||
});
|
||||
CHECK(count == 5);
|
||||
CHECK(ints == 2);
|
||||
CHECK(floats == 1);
|
||||
CHECK(numbers == (ints + floats));
|
||||
CHECK(strings == 1);
|
||||
CHECK(bools == 1);
|
||||
}
|
||||
|
||||
SECTION("early-exit (key, val)")
|
||||
{
|
||||
int count = 0;
|
||||
tbl.for_each([&](const key& /*k*/, const auto& /*v*/) noexcept -> bool { return ++count < 3; });
|
||||
CHECK(count == 3);
|
||||
}
|
||||
|
||||
SECTION("early-exit (val)")
|
||||
{
|
||||
int count = 0;
|
||||
tbl.for_each([&](const auto& /*v*/) noexcept -> bool { return ++count < 3; });
|
||||
CHECK(count == 3);
|
||||
}
|
||||
}
|
||||
|
29
toml.hpp
29
toml.hpp
@ -1466,7 +1466,7 @@ TOML_NAMESPACE_START // abi namespace
|
||||
T value;
|
||||
};
|
||||
template <typename T>
|
||||
inserter(T &&) -> inserter<T&&>;
|
||||
inserter(T&&) -> inserter<T&&>;
|
||||
template <typename T>
|
||||
inserter(T&) -> inserter<T&>;
|
||||
|
||||
@ -4721,6 +4721,16 @@ TOML_IMPL_NAMESPACE_START
|
||||
}
|
||||
return { static_cast<T>(val) };
|
||||
}
|
||||
|
||||
template <typename...>
|
||||
struct is_val_ctor_with_flags : std::false_type
|
||||
{};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_val_ctor_with_flags<T, U> : std::bool_constant< //
|
||||
(is_node<T> && is_value<T>) //
|
||||
&&(std::is_same_v<remove_cvref<U>, value_flags>)>
|
||||
{};
|
||||
}
|
||||
TOML_IMPL_NAMESPACE_END;
|
||||
|
||||
@ -4759,7 +4769,7 @@ TOML_NAMESPACE_START
|
||||
std::string_view,
|
||||
std::conditional_t<impl::is_one_of<value_type, double, int64_t, bool>, value_type, const value_type&>>);
|
||||
|
||||
template <typename... Args>
|
||||
TOML_HIDDEN_CONSTRAINT(!impl::is_val_ctor_with_flags<Args...>::value, typename... Args)
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit value(Args&&... args) noexcept(noexcept(value_type(
|
||||
impl::native_value_maker<value_type, std::decay_t<Args>...>::make(static_cast<Args&&>(args)...))))
|
||||
@ -4796,7 +4806,7 @@ TOML_NAMESPACE_START
|
||||
value(value&& other) noexcept //
|
||||
: node(std::move(other)),
|
||||
val_{ std::move(other.val_) },
|
||||
flags_{ other.flags_ }
|
||||
flags_{ std::exchange(other.flags_, value_flags{}) }
|
||||
{
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
@ -4812,6 +4822,7 @@ TOML_NAMESPACE_START
|
||||
#if TOML_LIFETIME_HOOKS
|
||||
TOML_VALUE_CREATED;
|
||||
#endif
|
||||
other.flags_ = {};
|
||||
}
|
||||
|
||||
value& operator=(const value& rhs) noexcept
|
||||
@ -4828,7 +4839,7 @@ TOML_NAMESPACE_START
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
flags_ = rhs.flags_;
|
||||
flags_ = std::exchange(rhs.flags_, value_flags{});
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -5316,6 +5327,8 @@ TOML_NAMESPACE_START
|
||||
|
||||
template <typename T>
|
||||
value(T) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
|
||||
template <typename T>
|
||||
value(T, value_flags) -> value<impl::native_type_of<impl::remove_cvref<T>>>;
|
||||
|
||||
template <typename T>
|
||||
TOML_NODISCARD
|
||||
@ -5649,7 +5662,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
// copy/move ctor
|
||||
if constexpr (std::is_same_v<remove_cvref<T>, value_type>)
|
||||
{
|
||||
out = new value_type{ static_cast<T&&>(val) };
|
||||
out = new value_type{ static_cast<T&&>(val), flags };
|
||||
}
|
||||
|
||||
// creating from raw value
|
||||
@ -8674,7 +8687,7 @@ TOML_IMPL_NAMESPACE_START
|
||||
const auto type = state_table[byte];
|
||||
|
||||
codepoint = static_cast<char32_t>(has_code_point() ? (uint_least32_t{ 255u } >> type) & byte
|
||||
: (byte & uint_least32_t{ 63u })
|
||||
: (byte& uint_least32_t{ 63u })
|
||||
| (static_cast<uint_least32_t>(codepoint) << 6));
|
||||
|
||||
state = state_table[state + uint_least32_t{ 256u } + type];
|
||||
@ -12595,11 +12608,11 @@ TOML_ANON_NAMESPACE_START
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_string_view<Char>, std::string_view) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_string_view<Char>, std::string &&) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
utf8_reader(std::basic_string_view<Char>, std::string&&) -> utf8_reader<std::basic_string_view<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_istream<Char>&, std::string_view) -> utf8_reader<std::basic_istream<Char>>;
|
||||
template <typename Char>
|
||||
utf8_reader(std::basic_istream<Char>&, std::string &&) -> utf8_reader<std::basic_istream<Char>>;
|
||||
utf8_reader(std::basic_istream<Char>&, std::string&&) -> utf8_reader<std::basic_istream<Char>>;
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
#define utf8_buffered_reader_error_check(...) static_assert(true)
|
||||
|
Loading…
Reference in New Issue
Block a user