removed internal operator""_sz (ADL is a cruel mistress)

also:
- applied clang-format to tests
- added some missing `TOML_API`
This commit is contained in:
Mark Gillard 2021-10-26 16:49:23 +03:00
parent 7da912c45e
commit dbc078202d
78 changed files with 2165 additions and 2303 deletions

View File

@ -156,7 +156,6 @@ StatementMacros:
- TOML_ALWAYS_INLINE - TOML_ALWAYS_INLINE
- TOML_API - TOML_API
- TOML_ATTR - TOML_ATTR
- TOML_CONSTEVAL
- TOML_EXTERNAL_LINKAGE - TOML_EXTERNAL_LINKAGE
- TOML_INTERNAL_LINKAGE - TOML_INTERNAL_LINKAGE
- TOML_MEMBER_ATTR - TOML_MEMBER_ATTR

View File

@ -6,7 +6,6 @@
#define TOML_ABSTRACT_BASE #define TOML_ABSTRACT_BASE
#define TOML_EMPTY_BASES #define TOML_EMPTY_BASES
#define TOML_MAY_THROW #define TOML_MAY_THROW
#define TOML_CONSTEVAL constexpr
#define TOML_CONSTRAINED_TEMPLATE(cond, ...) template <__VA_ARGS__> #define TOML_CONSTRAINED_TEMPLATE(cond, ...) template <__VA_ARGS__>
#define TOML_LIKELY(...) (__VA_ARGS__) #define TOML_LIKELY(...) (__VA_ARGS__)
#define TOML_UNLIKELY(...) (__VA_ARGS__) #define TOML_UNLIKELY(...) (__VA_ARGS__)

View File

@ -356,14 +356,13 @@ TOML_NAMESPACE_START
/// \tparam ElemTypes One of the TOML node or value types (or a type promotable to one). /// \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 val The node or value used to initialize element 0.
/// \param vals The nodes or values used to initialize elements 1...N. /// \param vals The nodes or values used to initialize elements 1...N.
TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0_sz TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
typename ElemType, typename ElemType,
typename... ElemTypes) typename... ElemTypes)
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
explicit array(ElemType&& val, ElemTypes&&... vals) explicit array(ElemType&& val, ElemTypes&&... vals)
{ {
elements.reserve(sizeof...(ElemTypes) + 1_sz); elements.reserve(sizeof...(ElemTypes) + 1u);
emplace_back_if_not_empty_view(static_cast<ElemType&&>(val)); emplace_back_if_not_empty_view(static_cast<ElemType&&>(val));
if constexpr (sizeof...(ElemTypes) > 0) if constexpr (sizeof...(ElemTypes) > 0)
{ {
@ -659,7 +658,7 @@ TOML_NAMESPACE_START
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin()); const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
preinsertion_resize(start_idx, count); preinsertion_resize(start_idx, count);
size_t i = start_idx; size_t i = start_idx;
for (size_t e = start_idx + count - 1_sz; i < e; i++) for (size_t e = start_idx + count - 1u; i < e; i++)
elements[i].reset(impl::make_node(val)); elements[i].reset(impl::make_node(val));
//# potentially move the initial value into the last element //# potentially move the initial value into the last element
@ -1087,7 +1086,7 @@ TOML_NAMESPACE_START
if (lhs.size() != rhs.size()) if (lhs.size() != rhs.size())
return false; return false;
if (rhs.size() == 0_sz) if (rhs.size() == 0u)
return true; return true;
size_t i{}; size_t i{};

View File

@ -94,14 +94,14 @@ TOML_NAMESPACE_START
void array::preinsertion_resize(size_t idx, size_t count) noexcept void array::preinsertion_resize(size_t idx, size_t count) noexcept
{ {
TOML_ASSERT(idx <= elements.size()); TOML_ASSERT(idx <= elements.size());
TOML_ASSERT(count >= 1_sz); TOML_ASSERT(count >= 1u);
const auto old_size = elements.size(); const auto old_size = elements.size();
const auto new_size = old_size + count; const auto new_size = old_size + count;
const auto inserting_at_end = idx == old_size; const auto inserting_at_end = idx == old_size;
elements.resize(new_size); elements.resize(new_size);
if (!inserting_at_end) if (!inserting_at_end)
{ {
for (size_t left = old_size, right = new_size - 1_sz; left-- > idx; right--) for (size_t left = old_size, right = new_size - 1u; left-- > idx; right--)
elements[right] = std::move(elements[left]); elements[right] = std::move(elements[left]);
} }
} }
@ -165,7 +165,7 @@ TOML_NAMESPACE_START
for (size_t i = 0, e = elements.size(); i < e; i++) for (size_t i = 0, e = elements.size(); i < e; i++)
{ {
auto arr = elements[i]->as_array(); auto arr = elements[i]->as_array();
leaves += arr ? arr->total_leaf_count() : 1_sz; leaves += arr ? arr->total_leaf_count() : size_t{ 1 };
} }
return leaves; return leaves;
} }
@ -195,14 +195,14 @@ TOML_NAMESPACE_START
bool requires_flattening = false; bool requires_flattening = false;
size_t size_after_flattening = elements.size(); size_t size_after_flattening = elements.size();
for (size_t i = elements.size(); i-- > 0_sz;) for (size_t i = elements.size(); i-- > 0u;)
{ {
auto arr = elements[i]->as_array(); auto arr = elements[i]->as_array();
if (!arr) if (!arr)
continue; continue;
size_after_flattening--; // discount the array itself size_after_flattening--; // discount the array itself
const auto leaf_count = arr->total_leaf_count(); const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 0_sz) if (leaf_count > 0u)
{ {
requires_flattening = true; requires_flattening = true;
size_after_flattening += leaf_count; size_after_flattening += leaf_count;
@ -228,8 +228,8 @@ TOML_NAMESPACE_START
std::unique_ptr<node> arr_storage = std::move(elements[i]); std::unique_ptr<node> arr_storage = std::move(elements[i]);
const auto leaf_count = arr->total_leaf_count(); const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 1_sz) if (leaf_count > 1u)
preinsertion_resize(i + 1_sz, leaf_count - 1_sz); preinsertion_resize(i + 1u, leaf_count - 1u);
flatten_child(std::move(*arr), i); // increments i flatten_child(std::move(*arr), i); // increments i
} }

View File

@ -46,7 +46,7 @@ TOML_NAMESPACE_START
std::vector<std::string> key_path_; std::vector<std::string> key_path_;
bool pending_table_separator_ = false; bool pending_table_separator_ = false;
static constexpr size_t line_wrap_cols = 120_sz; static constexpr size_t line_wrap_cols = 120;
TOML_NODISCARD TOML_NODISCARD
TOML_API TOML_API

View File

@ -45,7 +45,7 @@ TOML_NAMESPACE_START
if (requires_quotes) if (requires_quotes)
{ {
std::string s; std::string s;
s.reserve(str.length() + 2_sz); s.reserve(str.length() + 2u);
s += '"'; s += '"';
for (auto c : str) for (auto c : str)
{ {
@ -75,11 +75,11 @@ TOML_NAMESPACE_START
{ {
auto& n = *reinterpret_cast<const table*>(&node); auto& n = *reinterpret_cast<const table*>(&node);
if (n.empty()) if (n.empty())
return 2_sz; // "{}" return 2u; // "{}"
size_t weight = 3_sz; // "{ }" size_t weight = 3u; // "{ }"
for (auto&& [k, v] : n) for (auto&& [k, v] : n)
{ {
weight += k.length() + count_inline_columns(v) + 2_sz; // + ", " weight += k.length() + count_inline_columns(v) + 2u; // + ", "
if (weight >= line_wrap_cols) if (weight >= line_wrap_cols)
break; break;
} }
@ -90,11 +90,11 @@ TOML_NAMESPACE_START
{ {
auto& n = *reinterpret_cast<const array*>(&node); auto& n = *reinterpret_cast<const array*>(&node);
if (n.empty()) if (n.empty())
return 2_sz; // "[]" return 2u; // "[]"
size_t weight = 3_sz; // "[ ]" size_t weight = 3u; // "[ ]"
for (auto& elem : n) for (auto& elem : n)
{ {
weight += count_inline_columns(elem) + 2_sz; // + ", " weight += count_inline_columns(elem) + 2u; // + ", "
if (weight >= line_wrap_cols) if (weight >= line_wrap_cols)
break; break;
} }
@ -104,7 +104,7 @@ TOML_NAMESPACE_START
case node_type::string: case node_type::string:
{ {
auto& n = *reinterpret_cast<const value<std::string>*>(&node); auto& n = *reinterpret_cast<const value<std::string>*>(&node);
return n.get().length() + 2_sz; // + "" return n.get().length() + 2u; // + ""
} }
case node_type::integer: case node_type::integer:
@ -112,14 +112,14 @@ TOML_NAMESPACE_START
auto& n = *reinterpret_cast<const value<int64_t>*>(&node); auto& n = *reinterpret_cast<const value<int64_t>*>(&node);
auto v = n.get(); auto v = n.get();
if (!v) if (!v)
return 1_sz; return 1u;
size_t weight = {}; size_t weight = {};
if (v < 0) if (v < 0)
{ {
weight += 1; weight += 1u;
v *= -1; v *= -1;
} }
return weight + static_cast<size_t>(log10(static_cast<double>(v))) + 1_sz; return weight + static_cast<size_t>(log10(static_cast<double>(v))) + 1u;
} }
case node_type::floating_point: case node_type::floating_point:
@ -127,21 +127,21 @@ TOML_NAMESPACE_START
auto& n = *reinterpret_cast<const value<double>*>(&node); auto& n = *reinterpret_cast<const value<double>*>(&node);
auto v = n.get(); auto v = n.get();
if (v == 0.0) if (v == 0.0)
return 3_sz; // "0.0" return 3u; // "0.0"
size_t weight = 2_sz; // ".0" size_t weight = 2u; // ".0"
if (v < 0.0) if (v < 0.0)
{ {
weight += 1; weight += 1u;
v *= -1.0; v *= -1.0;
} }
return weight + static_cast<size_t>(log10(v)) + 1_sz; return weight + static_cast<size_t>(log10(v)) + 1u;
break; break;
} }
case node_type::boolean: return 5_sz; case node_type::boolean: return 5u;
case node_type::date: [[fallthrough]]; case node_type::date: [[fallthrough]];
case node_type::time: return 10_sz; case node_type::time: return 10u;
case node_type::date_time: return 30_sz; case node_type::date_time: return 30u;
case node_type::none: TOML_UNREACHABLE; case node_type::none: TOML_UNREACHABLE;
default: TOML_UNREACHABLE; default: TOML_UNREACHABLE;
} }
@ -267,7 +267,7 @@ TOML_NAMESPACE_START
for (size_t i = 0; i < arr.size(); i++) for (size_t i = 0; i < arr.size(); i++)
{ {
if (i > 0_sz) if (i > 0u)
{ {
impl::print_to_stream(base::stream(), ','); impl::print_to_stream(base::stream(), ',');
if (!multiline) if (!multiline)
@ -309,7 +309,7 @@ TOML_NAMESPACE_START
static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept
{ {
auto arr = nde.as_array(); auto arr = nde.as_array();
return arr && arr->is_array_of_tables() && !arr->template get_as<table>(0_sz)->is_inline(); return arr && arr->is_array_of_tables() && !arr->template get_as<table>(0u)->is_inline();
}; };
// values, arrays, and inline tables/table arrays // values, arrays, and inline tables/table arrays
@ -372,7 +372,7 @@ TOML_NAMESPACE_START
} }
} }
bool skip_self = false; bool skip_self = false;
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz)) if (child_value_count == 0u && (child_table_count > 0u || child_table_array_count > 0u))
skip_self = true; skip_self = true;
key_path_.push_back(make_key_segment(k)); key_path_.push_back(make_key_segment(k));

View File

@ -110,15 +110,6 @@ TOML_NAMESPACE_START
class parse_result; class parse_result;
#endif #endif
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
TOML_NODISCARD
TOML_ATTR(const)
TOML_ALWAYS_INLINE
TOML_CONSTEVAL
size_t operator"" _sz(unsigned long long n) noexcept
{
return static_cast<size_t>(n);
}
} }
TOML_NAMESPACE_END; TOML_NAMESPACE_END;

View File

@ -68,7 +68,7 @@ TOML_NAMESPACE_START
base::increase_indent(); base::increase_indent();
for (size_t i = 0; i < arr.size(); i++) for (size_t i = 0; i < arr.size(); i++)
{ {
if (i > 0_sz) if (i > 0u)
impl::print_to_stream(base::stream(), ','); impl::print_to_stream(base::stream(), ',');
base::print_newline(true); base::print_newline(true);
base::print_indent(); base::print_indent();

View File

@ -51,7 +51,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char> template <typename Char>
class utf8_byte_stream<std::basic_string_view<Char>> class utf8_byte_stream<std::basic_string_view<Char>>
{ {
static_assert(sizeof(Char) == 1_sz); static_assert(sizeof(Char) == 1);
private: private:
std::basic_string_view<Char> source_; std::basic_string_view<Char> source_;
@ -65,20 +65,20 @@ TOML_ANON_NAMESPACE_START
// trim trailing nulls // trim trailing nulls
const size_t initial_len = source_.length(); const size_t initial_len = source_.length();
size_t actual_len = initial_len; size_t actual_len = initial_len;
for (size_t i = actual_len; i-- > 0_sz;) for (size_t i = actual_len; i-- > 0u;)
{ {
if (source_[i] != Char{}) // not '\0' if (source_[i] != Char{}) // not '\0'
{ {
actual_len = i + 1_sz; actual_len = i + 1u;
break; break;
} }
} }
if (initial_len != actual_len) if (initial_len != actual_len)
source_ = source_.substr(0_sz, actual_len); source_ = source_.substr(0u, actual_len);
// skip bom // skip bom
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source_.data(), 3_sz) == 0) if (actual_len >= 3u && memcmp(utf8_byte_order_mark.data(), source_.data(), 3u) == 0)
position_ += 3_sz; position_ += 3u;
} }
TOML_NODISCARD TOML_NODISCARD
@ -114,7 +114,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char> template <typename Char>
class utf8_byte_stream<std::basic_istream<Char>> class utf8_byte_stream<std::basic_istream<Char>>
{ {
static_assert(sizeof(Char) == 1_sz); static_assert(sizeof(Char) == 1);
private: private:
std::basic_istream<Char>* source_; std::basic_istream<Char>* source_;
@ -130,7 +130,7 @@ TOML_ANON_NAMESPACE_START
const auto initial_pos = source_->tellg(); const auto initial_pos = source_->tellg();
Char bom[3]; Char bom[3];
source_->read(bom, 3); source_->read(bom, 3);
if (source_->bad() || (source_->gcount() == 3 && memcmp(utf8_byte_order_mark.data(), bom, 3_sz) == 0)) if (source_->bad() || (source_->gcount() == 3 && memcmp(utf8_byte_order_mark.data(), bom, 3u) == 0))
return; return;
source_->clear(); source_->clear();
@ -178,7 +178,7 @@ TOML_ANON_NAMESPACE_START
TOML_NODISCARD TOML_NODISCARD
std::string_view as_view() const noexcept std::string_view as_view() const noexcept
{ {
return bytes[3] ? std::string_view{ bytes, 4_sz } : std::string_view{ bytes }; return bytes[3] ? std::string_view{ bytes, 4u } : std::string_view{ bytes };
} }
TOML_NODISCARD TOML_NODISCARD
@ -269,7 +269,7 @@ TOML_ANON_NAMESPACE_START
{ {
TOML_ERROR_CHECK; TOML_ERROR_CHECK;
auto& prev = codepoints_[(cp_idx_ - 1_sz) % 2_sz]; auto& prev = codepoints_[(cp_idx_ - 1u) % 2u];
if (stream_.eof()) if (stream_.eof())
return nullptr; return nullptr;
@ -333,7 +333,7 @@ TOML_ANON_NAMESPACE_START
TOML_ERROR_CHECK; TOML_ERROR_CHECK;
auto& current = codepoints_[cp_idx_ % 2_sz]; auto& current = codepoints_[cp_idx_ % 2u];
current.bytes[current_byte_count_++] = static_cast<char>(next_byte); current.bytes[current_byte_count_++] = static_cast<char>(next_byte);
if (decoder_.has_code_point()) if (decoder_.has_code_point())
{ {
@ -966,7 +966,7 @@ TOML_IMPL_NAMESPACE_START
TOML_NEVER_INLINE TOML_NEVER_INLINE
void set_error_at(source_position pos, const T&... reason) const TOML_MAY_THROW void set_error_at(source_position pos, const T&... reason) const TOML_MAY_THROW
{ {
static_assert(sizeof...(T) > 0_sz); static_assert(sizeof...(T) > 0);
#if !TOML_EXCEPTIONS #if !TOML_EXCEPTIONS
if (err) if (err)
return; return;
@ -991,7 +991,7 @@ TOML_IMPL_NAMESPACE_START
set_error_at(current_position(1), reason...); set_error_at(current_position(1), reason...);
} }
void go_back(size_t count = 1_sz) noexcept void go_back(size_t count = 1) noexcept
{ {
return_if_error(); return_if_error();
assert_or_assume(count); assert_or_assume(count);
@ -1034,7 +1034,7 @@ TOML_IMPL_NAMESPACE_START
recording_buffer.append(cp->as_view()); recording_buffer.append(cp->as_view());
} }
void stop_recording(size_t pop_bytes = 0_sz) noexcept void stop_recording(size_t pop_bytes = 0) noexcept
{ {
return_if_error(); return_if_error();
@ -1043,7 +1043,7 @@ TOML_IMPL_NAMESPACE_START
{ {
if (pop_bytes >= recording_buffer.length()) if (pop_bytes >= recording_buffer.length())
recording_buffer.clear(); recording_buffer.clear();
else if (pop_bytes == 1_sz) else if (pop_bytes == 1u)
recording_buffer.pop_back(); recording_buffer.pop_back();
else else
recording_buffer.erase(recording_buffer.begin() recording_buffer.erase(recording_buffer.begin()
@ -1322,7 +1322,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line) if (multi_line)
{ {
size_t lookaheads = {}; size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz; size_t consecutive_delimiters = 1;
do do
{ {
advance_and_return_if_error({}); advance_and_return_if_error({});
@ -1332,30 +1332,30 @@ TOML_IMPL_NAMESPACE_START
else else
break; break;
} }
while (lookaheads < 4_sz); while (lookaheads < 4u);
switch (consecutive_delimiters) switch (consecutive_delimiters)
{ {
// """ " (one quote somewhere in a ML string) // """ " (one quote somewhere in a ML string)
case 1_sz: case 1:
str += '"'; str += '"';
skipping_whitespace = false; skipping_whitespace = false;
continue; continue;
// """ "" (two quotes somewhere in a ML string) // """ "" (two quotes somewhere in a ML string)
case 2_sz: case 2:
str.append("\"\""sv); str.append("\"\""sv);
skipping_whitespace = false; skipping_whitespace = false;
continue; continue;
// """ """ (the end of the string) // """ """ (the end of the string)
case 3_sz: return str; case 3: return str;
// """ """" (one at the end of the string) // """ """" (one at the end of the string)
case 4_sz: str += '"'; return str; case 4: str += '"'; return str;
// """ """"" (two quotes at the end of the string) // """ """"" (two quotes at the end of the string)
case 5_sz: case 5:
str.append("\"\""sv); str.append("\"\""sv);
advance_and_return_if_error({}); // skip the last '"' advance_and_return_if_error({}); // skip the last '"'
return str; return str;
@ -1451,7 +1451,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line) if (multi_line)
{ {
size_t lookaheads = {}; size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz; size_t consecutive_delimiters = 1;
do do
{ {
advance_and_return_if_error({}); advance_and_return_if_error({});
@ -1461,24 +1461,24 @@ TOML_IMPL_NAMESPACE_START
else else
break; break;
} }
while (lookaheads < 4_sz); while (lookaheads < 4u);
switch (consecutive_delimiters) switch (consecutive_delimiters)
{ {
// ''' ' (one quote somewhere in a ML string) // ''' ' (one quote somewhere in a ML string)
case 1_sz: str += '\''; continue; case 1: str += '\''; continue;
// ''' '' (two quotes somewhere in a ML string) // ''' '' (two quotes somewhere in a ML string)
case 2_sz: str.append("''"sv); continue; case 2: str.append("''"sv); continue;
// ''' ''' (the end of the string) // ''' ''' (the end of the string)
case 3_sz: return str; case 3: return str;
// ''' '''' (one at the end of the string) // ''' '''' (one at the end of the string)
case 4_sz: str += '\''; return str; case 4: str += '\''; return str;
// ''' ''''' (two quotes at the end of the string) // ''' ''''' (two quotes at the end of the string)
case 5_sz: case 5:
str.append("''"sv); str.append("''"sv);
advance_and_return_if_error({}); // skip the last ' advance_and_return_if_error({}); // skip the last '
return str; return str;
@ -1561,7 +1561,7 @@ TOML_IMPL_NAMESPACE_START
{ {
// step back two characters so that the current // step back two characters so that the current
// character is the string delimiter // character is the string delimiter
go_back(2_sz); go_back(2u);
return { first == U'\'' ? parse_literal_string(false) : parse_basic_string(false), false }; return { first == U'\'' ? parse_literal_string(false) : parse_basic_string(false), false };
} }
@ -1871,7 +1871,7 @@ TOML_IMPL_NAMESPACE_START
set_error_and_return_default("expected exponent digit or sign, saw '"sv, to_sv(*cp), "'"sv); set_error_and_return_default("expected exponent digit or sign, saw '"sv, to_sv(*cp), "'"sv);
// 0x.p-0 (mantissa is just '.') // 0x.p-0 (mantissa is just '.')
else if (fragments[0].length == 0_sz && fragments[1].length == 0_sz) else if (fragments[0].length == 0u && fragments[1].length == 0u)
set_error_and_return_default("expected hexadecimal digit, saw '"sv, to_sv(*cp), "'"sv); set_error_and_return_default("expected hexadecimal digit, saw '"sv, to_sv(*cp), "'"sv);
else else
@ -1906,7 +1906,7 @@ TOML_IMPL_NAMESPACE_START
} }
// sanity-check ending state // sanity-check ending state
if (current_fragment != fragments + 2 || current_fragment->length == 0_sz) if (current_fragment != fragments + 2 || current_fragment->length == 0u)
{ {
set_error_and_return_if_eof({}); set_error_and_return_if_eof({});
set_error_and_return_default("missing exponent"sv); set_error_and_return_default("missing exponent"sv);
@ -1937,7 +1937,7 @@ TOML_IMPL_NAMESPACE_START
// calculate value // calculate value
auto place = 1u; auto place = 1u;
for (size_t i = 0; i < f.length - 1_sz; i++) for (size_t i = 0; i < f.length - 1u; i++)
place *= base; place *= base;
uint32_t val{}; uint32_t val{};
while (place) while (place)
@ -2051,7 +2051,7 @@ TOML_IMPL_NAMESPACE_START
} }
// single digits can be converted trivially // single digits can be converted trivially
if (length == 1_sz) if (length == 1u)
{ {
if constexpr (base == 16) if constexpr (base == 16)
return static_cast<int64_t>(hex_to_dec(chars[0])); return static_cast<int64_t>(hex_to_dec(chars[0]));
@ -2101,7 +2101,7 @@ TOML_IMPL_NAMESPACE_START
// "YYYY" // "YYYY"
uint32_t digits[4]; uint32_t digits[4];
if (!consume_digit_sequence(digits, 4_sz)) if (!consume_digit_sequence(digits, 4u))
set_error_and_return_default("expected 4-digit year, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 4-digit year, saw '"sv, to_sv(cp), "'"sv);
const auto year = digits[3] + digits[2] * 10u + digits[1] * 100u + digits[0] * 1000u; const auto year = digits[3] + digits[2] * 10u + digits[1] * 100u + digits[0] * 1000u;
const auto is_leap_year = (year % 4u == 0u) && ((year % 100u != 0u) || (year % 400u == 0u)); const auto is_leap_year = (year % 4u == 0u) && ((year % 100u != 0u) || (year % 400u == 0u));
@ -2113,7 +2113,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "MM" // "MM"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit month, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit month, saw '"sv, to_sv(cp), "'"sv);
const auto month = digits[1] + digits[0] * 10u; const auto month = digits[1] + digits[0] * 10u;
if (month == 0u || month > 12u) if (month == 0u || month > 12u)
@ -2130,7 +2130,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "DD" // "DD"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit day, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit day, saw '"sv, to_sv(cp), "'"sv);
const auto day = digits[1] + digits[0] * 10u; const auto day = digits[1] + digits[0] * 10u;
if (day == 0u || day > max_days_in_month) if (day == 0u || day > max_days_in_month)
@ -2153,11 +2153,11 @@ TOML_IMPL_NAMESPACE_START
assert_or_assume(is_decimal_digit(*cp)); assert_or_assume(is_decimal_digit(*cp));
push_parse_scope("time"sv); push_parse_scope("time"sv);
static constexpr auto max_digits = 9_sz; static constexpr size_t max_digits = 9;
uint32_t digits[max_digits]; uint32_t digits[max_digits];
// "HH" // "HH"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv);
const auto hour = digits[1] + digits[0] * 10u; const auto hour = digits[1] + digits[0] * 10u;
if (hour > 23u) if (hour > 23u)
@ -2171,7 +2171,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "MM" // "MM"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv);
const auto minute = digits[1] + digits[0] * 10u; const auto minute = digits[1] + digits[0] * 10u;
if (minute > 59u) if (minute > 59u)
@ -2195,7 +2195,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "SS" // "SS"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit second, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit second, saw '"sv, to_sv(cp), "'"sv);
const auto second = digits[1] + digits[0] * 10u; const auto second = digits[1] + digits[0] * 10u;
if (second > 59u) if (second > 59u)
@ -2211,7 +2211,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "FFFFFFFFF" // "FFFFFFFFF"
auto digit_count = consume_variable_length_digit_sequence(digits, max_digits); size_t digit_count = consume_variable_length_digit_sequence(digits, max_digits);
if (!digit_count) if (!digit_count)
{ {
set_error_and_return_if_eof({}); set_error_and_return_if_eof({});
@ -2228,7 +2228,7 @@ TOML_IMPL_NAMESPACE_START
uint32_t value = 0u; uint32_t value = 0u;
uint32_t place = 1u; uint32_t place = 1u;
for (auto i = digit_count; i-- > 0_sz;) for (auto i = digit_count; i-- > 0u;)
{ {
value += digits[i] * place; value += digits[i] * place;
place *= 10u; place *= 10u;
@ -2280,7 +2280,7 @@ TOML_IMPL_NAMESPACE_START
// "HH" // "HH"
int digits[2]; int digits[2];
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv);
const auto hour = digits[1] + digits[0] * 10; const auto hour = digits[1] + digits[0] * 10;
if (hour > 23) if (hour > 23)
@ -2294,7 +2294,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "MM" // "MM"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv);
const auto minute = digits[1] + digits[0] * 10; const auto minute = digits[1] + digits[0] * 10;
if (minute > 59) if (minute > 59)
@ -2464,19 +2464,19 @@ TOML_IMPL_NAMESPACE_START
switch (static_cast<char32_t>(c | 32u)) switch (static_cast<char32_t>(c | 32u))
{ {
case U'b': case U'b':
if (char_count == 2_sz && has_any(begins_zero)) if (char_count == 2u && has_any(begins_zero))
add_trait(has_b); add_trait(has_b);
break; break;
case U'e': case U'e':
if (char_count > 1_sz if (char_count > 1u
&& has_none(has_b | has_o | has_p | has_t | has_x | has_z | has_colon) && has_none(has_b | has_o | has_p | has_t | has_x | has_z | has_colon)
&& (has_none(has_plus | has_minus) || has_any(begins_sign))) && (has_none(has_plus | has_minus) || has_any(begins_sign)))
add_trait(has_e); add_trait(has_e);
break; break;
case U'o': case U'o':
if (char_count == 2_sz && has_any(begins_zero)) if (char_count == 2u && has_any(begins_zero))
add_trait(has_o); add_trait(has_o);
break; break;
@ -2486,8 +2486,8 @@ TOML_IMPL_NAMESPACE_START
break; break;
case U'x': case U'x':
if ((char_count == 2_sz && has_any(begins_zero)) if ((char_count == 2u && has_any(begins_zero))
|| (char_count == 3_sz && has_any(begins_sign) && chars[1] == U'0')) || (char_count == 3u && has_any(begins_sign) && chars[1] == U'0'))
add_trait(has_x); add_trait(has_x);
break; break;
@ -2519,7 +2519,7 @@ TOML_IMPL_NAMESPACE_START
return_if_error({}); return_if_error({});
// force further scanning if this could have been a date-time with a space instead of a T // force further scanning if this could have been a date-time with a space instead of a T
if (char_count == 10_sz && traits == (bdigit_msk | has_minus) && chars[4] == U'-' && chars[7] == U'-' if (char_count == 10u && traits == (bdigit_msk | has_minus) && chars[4] == U'-' && chars[7] == U'-'
&& !is_eof() && *cp == U' ') && !is_eof() && *cp == U' ')
{ {
const auto pre_advance_count = advance_count; const auto pre_advance_count = advance_count;
@ -2532,7 +2532,7 @@ TOML_IMPL_NAMESPACE_START
go_back(advance_count - pre_advance_count); go_back(advance_count - pre_advance_count);
advance_count = pre_advance_count; advance_count = pre_advance_count;
traits = pre_scan_traits; traits = pre_scan_traits;
char_count = 10_sz; char_count = 10u;
}; };
advance_and_return_if_error({}); advance_and_return_if_error({});
@ -2550,19 +2550,19 @@ TOML_IMPL_NAMESPACE_START
scan(); scan();
return_if_error({}); return_if_error({});
if (char_count == 12_sz) if (char_count == 12u)
backpedal(); backpedal();
} }
} }
// set the reader back to where we started // set the reader back to where we started
go_back(advance_count); go_back(advance_count);
if (char_count < utf8_buffered_reader::max_history_length - 1_sz) if (char_count < utf8_buffered_reader::max_history_length - 1u)
chars[char_count] = U'\0'; chars[char_count] = U'\0';
// if after scanning ahead we still only have one value character, // if after scanning ahead we still only have one value character,
// the only valid value type is an integer. // the only valid value type is an integer.
if (char_count == 1_sz) if (char_count == 1u)
{ {
if (has_any(begins_zero | begins_digit)) if (has_any(begins_zero | begins_digit))
{ {
@ -2579,7 +2579,7 @@ TOML_IMPL_NAMESPACE_START
// now things that can be identified from two or more characters // now things that can be identified from two or more characters
return_if_error({}); return_if_error({});
assert_or_assume(char_count >= 2_sz); assert_or_assume(char_count >= 2u);
// do some 'fuzzy matching' where there's no ambiguity, since that allows the specific // do some 'fuzzy matching' where there's no ambiguity, since that allows the specific
// typed parse functions to take over and show better diagnostics if there's an issue // typed parse functions to take over and show better diagnostics if there's an issue
@ -2605,7 +2605,7 @@ TOML_IMPL_NAMESPACE_START
else if (has_any(begins_sign)) else if (has_any(begins_sign))
{ {
// single-digit signed integers // single-digit signed integers
if (char_count == 2_sz && has_any(has_digits)) if (char_count == 2u && has_any(has_digits))
{ {
val = new value{ static_cast<int64_t>(chars[1] - U'0') * (chars[0] == U'-' ? -1LL : 1LL) }; val = new value{ static_cast<int64_t>(chars[1] - U'0') * (chars[0] == U'-' ? -1LL : 1LL) };
advance(); // skip the sign advance(); // skip the sign
@ -2911,7 +2911,7 @@ TOML_IMPL_NAMESPACE_START
// get the key // get the key
start_recording(); start_recording();
auto key = parse_key(); auto key = parse_key();
stop_recording(1_sz); stop_recording(1u);
// skip past any whitespace that followed the key // skip past any whitespace that followed the key
consume_leading_whitespace(); consume_leading_whitespace();
@ -2977,7 +2977,7 @@ TOML_IMPL_NAMESPACE_START
// get the actual key // get the actual key
start_recording(); start_recording();
key = parse_key(); key = parse_key();
stop_recording(1_sz); stop_recording(1u);
return_if_error({}); return_if_error({});
// skip past any whitespace that followed the key // skip past any whitespace that followed the key
@ -3006,7 +3006,7 @@ TOML_IMPL_NAMESPACE_START
// check if each parent is a table/table array, or can be created implicitly as a table. // check if each parent is a table/table array, or can be created implicitly as a table.
auto parent = &root; auto parent = &root;
for (size_t i = 0; i < key.segments.size() - 1_sz; i++) for (size_t i = 0; i < key.segments.size() - 1u; i++)
{ {
auto child = parent->get(key.segments[i]); auto child = parent->get(key.segments[i]);
if (!child) if (!child)
@ -3134,13 +3134,13 @@ TOML_IMPL_NAMESPACE_START
auto kvp = parse_key_value_pair(); auto kvp = parse_key_value_pair();
return_if_error(); return_if_error();
TOML_ASSERT(kvp.key.segments.size() >= 1_sz); TOML_ASSERT(kvp.key.segments.size() >= 1u);
// if it's a dotted kvp we need to spawn the sub-tables if necessary, // if it's a dotted kvp we need to spawn the sub-tables if necessary,
// and set the target table to the second-to-last one in the chain // and set the target table to the second-to-last one in the chain
if (kvp.key.segments.size() > 1_sz) if (kvp.key.segments.size() > 1u)
{ {
for (size_t i = 0; i < kvp.key.segments.size() - 1_sz; i++) for (size_t i = 0; i < kvp.key.segments.size() - 1u; i++)
{ {
auto child = tab->get(kvp.key.segments[i]); auto child = tab->get(kvp.key.segments[i]);
if (!child) if (!child)
@ -3525,7 +3525,7 @@ TOML_ANON_NAMESPACE_START
// open file with a custom-sized stack buffer // open file with a custom-sized stack buffer
std::ifstream file; std::ifstream file;
char file_buffer[sizeof(void*) * 1024_sz]; char file_buffer[sizeof(void*) * 1024u];
file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer)); file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer));
file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate); file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
if (!file.is_open()) if (!file.is_open())

View File

@ -531,13 +531,6 @@
#define TOML_UNREACHABLE TOML_ASSERT(false) #define TOML_UNREACHABLE TOML_ASSERT(false)
#endif #endif
#if defined(__cpp_consteval) && __cpp_consteval >= 201811 && !defined(_MSC_VER)
// https://developercommunity.visualstudio.com/t/Erroneous-C7595-error-with-consteval-in/1404234
#define TOML_CONSTEVAL consteval
#else
#define TOML_CONSTEVAL constexpr
#endif
#ifdef __has_cpp_attribute #ifdef __has_cpp_attribute
#define TOML_HAS_ATTR(...) __has_cpp_attribute(__VA_ARGS__) #define TOML_HAS_ATTR(...) __has_cpp_attribute(__VA_ARGS__)
#else #else
@ -758,7 +751,9 @@
#define TOML_EXTERNAL_LINKAGE inline #define TOML_EXTERNAL_LINKAGE inline
#define TOML_INTERNAL_LINKAGE inline #define TOML_INTERNAL_LINKAGE inline
#else #else
#define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); using namespace toml; namespace #define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); \
using namespace toml; \
namespace
#define TOML_ANON_NAMESPACE_END static_assert(true) #define TOML_ANON_NAMESPACE_END static_assert(true)
#define TOML_ANON_NAMESPACE #define TOML_ANON_NAMESPACE
#define TOML_EXTERNAL_LINKAGE #define TOML_EXTERNAL_LINKAGE

View File

@ -314,26 +314,26 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
void print_to_stream(std::ostream & stream, const toml::date& val) void print_to_stream(std::ostream & stream, const toml::date& val)
{ {
print_integer_leftpad_zeros(stream, val.year, 4_sz); print_integer_leftpad_zeros(stream, val.year, 4u);
stream.put('-'); stream.put('-');
print_integer_leftpad_zeros(stream, val.month, 2_sz); print_integer_leftpad_zeros(stream, val.month, 2u);
stream.put('-'); stream.put('-');
print_integer_leftpad_zeros(stream, val.day, 2_sz); print_integer_leftpad_zeros(stream, val.day, 2u);
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
void print_to_stream(std::ostream & stream, const toml::time& val) void print_to_stream(std::ostream & stream, const toml::time& val)
{ {
print_integer_leftpad_zeros(stream, val.hour, 2_sz); print_integer_leftpad_zeros(stream, val.hour, 2u);
stream.put(':'); stream.put(':');
print_integer_leftpad_zeros(stream, val.minute, 2_sz); print_integer_leftpad_zeros(stream, val.minute, 2u);
stream.put(':'); stream.put(':');
print_integer_leftpad_zeros(stream, val.second, 2_sz); print_integer_leftpad_zeros(stream, val.second, 2u);
if (val.nanosecond && val.nanosecond <= 999999999u) if (val.nanosecond && val.nanosecond <= 999999999u)
{ {
stream.put('.'); stream.put('.');
auto ns = val.nanosecond; auto ns = val.nanosecond;
size_t digits = 9_sz; size_t digits = 9u;
while (ns % 10u == 0u) while (ns % 10u == 0u)
{ {
ns /= 10u; ns /= 10u;
@ -363,13 +363,13 @@ TOML_IMPL_NAMESPACE_START
const auto hours = mins / 60; const auto hours = mins / 60;
if (hours) if (hours)
{ {
print_integer_leftpad_zeros(stream, static_cast<unsigned int>(hours), 2_sz); print_integer_leftpad_zeros(stream, static_cast<unsigned int>(hours), 2u);
mins -= hours * 60; mins -= hours * 60;
} }
else else
print_to_stream(stream, "00"sv); print_to_stream(stream, "00"sv);
stream.put(':'); stream.put(':');
print_integer_leftpad_zeros(stream, static_cast<unsigned int>(mins), 2_sz); print_integer_leftpad_zeros(stream, static_cast<unsigned int>(mins), 2u);
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE

View File

@ -377,12 +377,15 @@ TOML_NAMESPACE_START
} }
TOML_NODISCARD TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype) const noexcept final; bool is_homogeneous(node_type ntype) const noexcept final;
TOML_NODISCARD TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final; bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final;
TOML_NODISCARD TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final; bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final;
template <typename ElemType = void> template <typename ElemType = void>

View File

@ -78,7 +78,6 @@ TOML_POP_WARNINGS;
#undef TOML_COMPILER_EXCEPTIONS #undef TOML_COMPILER_EXCEPTIONS
#undef TOML_CONCAT #undef TOML_CONCAT
#undef TOML_CONCAT_1 #undef TOML_CONCAT_1
#undef TOML_CONSTEVAL
#undef TOML_CONSTRAINED_TEMPLATE #undef TOML_CONSTRAINED_TEMPLATE
#undef TOML_CPP #undef TOML_CPP
#undef TOML_DISABLE_ARITHMETIC_WARNINGS #undef TOML_DISABLE_ARITHMETIC_WARNINGS

View File

@ -1,38 +0,0 @@
// This file is a part of toml++ and is subject to the the terms of the MIT license.
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
#include "settings.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#elif defined (__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#elif defined(_MSC_VER)
#pragma warning(push, 0)
#pragma warning(disable : 4365)
#pragma warning(disable : 4868)
#pragma warning(disable : 5105)
#endif
#if __has_include(<Catch2/single_include/catch2/catch.hpp>)
#include <Catch2/single_include/catch2/catch.hpp>
#else
#error Catch2 is missing! You probably need to fetch submodules ("git submodule update --init --depth 1 external/Catch2")
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//----- //-----
// this file was generated by generate_conformance_tests.py - do not modify it directly // this file was generated by generate_conformance_tests.py - do not modify it directly
// clang-format off
#include "tests.h" #include "tests.h"
using namespace toml::impl; using namespace toml::impl;

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//----- //-----
// this file was generated by generate_conformance_tests.py - do not modify it directly // this file was generated by generate_conformance_tests.py - do not modify it directly
// clang-format off
#include "tests.h" #include "tests.h"
using namespace toml::impl; using namespace toml::impl;

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//----- //-----
// this file was generated by generate_conformance_tests.py - do not modify it directly // this file was generated by generate_conformance_tests.py - do not modify it directly
// clang-format off
#include "tests.h" #include "tests.h"
using namespace toml::impl; using namespace toml::impl;

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//----- //-----
// this file was generated by generate_conformance_tests.py - do not modify it directly // this file was generated by generate_conformance_tests.py - do not modify it directly
// clang-format off
#include "tests.h" #include "tests.h"
using namespace toml::impl; using namespace toml::impl;
@ -1531,4 +1532,3 @@ Location SF.)"sv },
#endif // UNICODE_LITERALS_OK #endif // UNICODE_LITERALS_OK
} }

View File

@ -5,17 +5,17 @@
#include "settings.h" #include "settings.h"
#if !TOML_HEADER_ONLY #if !TOML_HEADER_ONLY
#define TOML_IMPLEMENTATION #define TOML_IMPLEMENTATION
#endif #endif
#if USE_TARTANLLAMA_OPTIONAL #if USE_TARTANLLAMA_OPTIONAL
#include "tloptional.h" #include "lib_tloptional.h"
#endif #endif
#if USE_SINGLE_HEADER #if USE_SINGLE_HEADER
#include "../toml.hpp" #include "../toml.hpp"
#else #else
#include "../include/toml++/toml.h" #include "../include/toml++/toml.h"
#endif #endif
namespace toml namespace toml
@ -23,286 +23,285 @@ namespace toml
using std::declval; using std::declval;
using std::is_same_v; using std::is_same_v;
#define CHECK_NODE_TYPE_MAPPING(T, expected) \ #define CHECK_NODE_TYPE_MAPPING(T, expected) \
static_assert(impl::node_type_of<T> == expected); \ static_assert(impl::node_type_of<T> == expected); \
static_assert(impl::node_type_of<T&> == expected); \ static_assert(impl::node_type_of<T&> == expected); \
static_assert(impl::node_type_of<T&&> == expected); \ static_assert(impl::node_type_of<T&&> == expected); \
static_assert(impl::node_type_of<const T> == expected); \ static_assert(impl::node_type_of<const T> == expected); \
static_assert(impl::node_type_of<const T&> == expected); \ static_assert(impl::node_type_of<const T&> == expected); \
static_assert(impl::node_type_of<const T&&> == expected); \ static_assert(impl::node_type_of<const T&&> == expected); \
static_assert(impl::node_type_of<volatile T> == expected); \ static_assert(impl::node_type_of<volatile T> == expected); \
static_assert(impl::node_type_of<volatile T&> == expected); \ static_assert(impl::node_type_of<volatile T&> == expected); \
static_assert(impl::node_type_of<volatile T&&> == expected); \ static_assert(impl::node_type_of<volatile T&&> == expected); \
static_assert(impl::node_type_of<const volatile T> == expected); \ static_assert(impl::node_type_of<const volatile T> == expected); \
static_assert(impl::node_type_of<const volatile T&> == expected); \ static_assert(impl::node_type_of<const volatile T&> == expected); \
static_assert(impl::node_type_of<const volatile T&&> == expected) static_assert(impl::node_type_of<const volatile T&&> == expected)
CHECK_NODE_TYPE_MAPPING(int64_t, node_type::integer); CHECK_NODE_TYPE_MAPPING(int64_t, node_type::integer);
CHECK_NODE_TYPE_MAPPING(double, node_type::floating_point); CHECK_NODE_TYPE_MAPPING(double, node_type::floating_point);
CHECK_NODE_TYPE_MAPPING(std::string, node_type::string); CHECK_NODE_TYPE_MAPPING(std::string, node_type::string);
CHECK_NODE_TYPE_MAPPING(bool, node_type::boolean); CHECK_NODE_TYPE_MAPPING(bool, node_type::boolean);
CHECK_NODE_TYPE_MAPPING(toml::date, node_type::date); CHECK_NODE_TYPE_MAPPING(toml::date, node_type::date);
CHECK_NODE_TYPE_MAPPING(toml::time, node_type::time); CHECK_NODE_TYPE_MAPPING(toml::time, node_type::time);
CHECK_NODE_TYPE_MAPPING(toml::date_time, node_type::date_time); CHECK_NODE_TYPE_MAPPING(toml::date_time, node_type::date_time);
CHECK_NODE_TYPE_MAPPING(toml::array, node_type::array); CHECK_NODE_TYPE_MAPPING(toml::array, node_type::array);
CHECK_NODE_TYPE_MAPPING(toml::table, node_type::table); CHECK_NODE_TYPE_MAPPING(toml::table, node_type::table);
#define CHECK_CAN_REPRESENT_NATIVE(T, expected) \
static_assert((impl::value_traits<T>::is_native || impl::value_traits<T>::can_represent_native) == expected)
#define CHECK_CAN_REPRESENT_NATIVE(T, expected) \ CHECK_CAN_REPRESENT_NATIVE(time, true);
static_assert((impl::value_traits<T>::is_native || impl::value_traits<T>::can_represent_native) == expected) CHECK_CAN_REPRESENT_NATIVE(date, true);
CHECK_CAN_REPRESENT_NATIVE(date_time, true);
CHECK_CAN_REPRESENT_NATIVE(time, true); CHECK_CAN_REPRESENT_NATIVE(bool, true);
CHECK_CAN_REPRESENT_NATIVE(date, true); CHECK_CAN_REPRESENT_NATIVE(int8_t, false);
CHECK_CAN_REPRESENT_NATIVE(date_time, true); CHECK_CAN_REPRESENT_NATIVE(int16_t, false);
CHECK_CAN_REPRESENT_NATIVE(bool, true); CHECK_CAN_REPRESENT_NATIVE(int32_t, false);
CHECK_CAN_REPRESENT_NATIVE(int8_t, false); CHECK_CAN_REPRESENT_NATIVE(int64_t, true);
CHECK_CAN_REPRESENT_NATIVE(int16_t, false); CHECK_CAN_REPRESENT_NATIVE(uint8_t, false);
CHECK_CAN_REPRESENT_NATIVE(int32_t, false); CHECK_CAN_REPRESENT_NATIVE(uint16_t, false);
CHECK_CAN_REPRESENT_NATIVE(int64_t, true); CHECK_CAN_REPRESENT_NATIVE(uint32_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint8_t, false); CHECK_CAN_REPRESENT_NATIVE(uint64_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint16_t, false); CHECK_CAN_REPRESENT_NATIVE(float, false);
CHECK_CAN_REPRESENT_NATIVE(uint32_t, false); CHECK_CAN_REPRESENT_NATIVE(double, true);
CHECK_CAN_REPRESENT_NATIVE(uint64_t, false); #ifdef TOML_INT128
CHECK_CAN_REPRESENT_NATIVE(float, false); CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true);
CHECK_CAN_REPRESENT_NATIVE(double, true); CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false);
#ifdef TOML_INT128 #endif
CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true); #ifdef TOML_FP16
CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false);
#endif
#ifdef TOML_FP16
CHECK_CAN_REPRESENT_NATIVE(TOML_FP16, false); CHECK_CAN_REPRESENT_NATIVE(TOML_FP16, false);
#endif #endif
#ifdef TOML_FLOAT16 #ifdef TOML_FLOAT16
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false); CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false);
#endif #endif
#ifdef TOML_FLOAT128 #ifdef TOML_FLOAT128
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true); CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true);
#endif #endif
CHECK_CAN_REPRESENT_NATIVE(char*, false); CHECK_CAN_REPRESENT_NATIVE(char*, false);
CHECK_CAN_REPRESENT_NATIVE(char*const, false); CHECK_CAN_REPRESENT_NATIVE(char* const, false);
CHECK_CAN_REPRESENT_NATIVE(char[2], false); CHECK_CAN_REPRESENT_NATIVE(char[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char[2], false); CHECK_CAN_REPRESENT_NATIVE(const char[2], false);
CHECK_CAN_REPRESENT_NATIVE(char(&)[2], false); CHECK_CAN_REPRESENT_NATIVE(char (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char(&)[2], false); CHECK_CAN_REPRESENT_NATIVE(const char (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false); CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char(&&)[2], false); CHECK_CAN_REPRESENT_NATIVE(const char(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char*, true); CHECK_CAN_REPRESENT_NATIVE(const char*, true);
CHECK_CAN_REPRESENT_NATIVE(const char*const, true); CHECK_CAN_REPRESENT_NATIVE(const char* const, true);
CHECK_CAN_REPRESENT_NATIVE(std::string, true); CHECK_CAN_REPRESENT_NATIVE(std::string, true);
CHECK_CAN_REPRESENT_NATIVE(std::string_view, true); CHECK_CAN_REPRESENT_NATIVE(std::string_view, true);
#if TOML_HAS_CHAR8 #if TOML_HAS_CHAR8
CHECK_CAN_REPRESENT_NATIVE(char8_t*, false); CHECK_CAN_REPRESENT_NATIVE(char8_t*, false);
CHECK_CAN_REPRESENT_NATIVE(char8_t*const, false); CHECK_CAN_REPRESENT_NATIVE(char8_t* const, false);
CHECK_CAN_REPRESENT_NATIVE(char8_t[2], false); CHECK_CAN_REPRESENT_NATIVE(char8_t[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char8_t[2], false); CHECK_CAN_REPRESENT_NATIVE(const char8_t[2], false);
CHECK_CAN_REPRESENT_NATIVE(char8_t(&)[2], false); CHECK_CAN_REPRESENT_NATIVE(char8_t (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char8_t(&)[2], false); CHECK_CAN_REPRESENT_NATIVE(const char8_t (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false); CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char8_t(&&)[2], false); CHECK_CAN_REPRESENT_NATIVE(const char8_t(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char8_t*, true); CHECK_CAN_REPRESENT_NATIVE(const char8_t*, true);
CHECK_CAN_REPRESENT_NATIVE(const char8_t*const, true); CHECK_CAN_REPRESENT_NATIVE(const char8_t* const, true);
CHECK_CAN_REPRESENT_NATIVE(std::u8string, true); CHECK_CAN_REPRESENT_NATIVE(std::u8string, true);
CHECK_CAN_REPRESENT_NATIVE(std::u8string_view, true); CHECK_CAN_REPRESENT_NATIVE(std::u8string_view, true);
#endif #endif
CHECK_CAN_REPRESENT_NATIVE(wchar_t*, false); CHECK_CAN_REPRESENT_NATIVE(wchar_t*, false);
CHECK_CAN_REPRESENT_NATIVE(wchar_t*const, false); CHECK_CAN_REPRESENT_NATIVE(wchar_t* const, false);
CHECK_CAN_REPRESENT_NATIVE(wchar_t[2], false); CHECK_CAN_REPRESENT_NATIVE(wchar_t[2], false);
CHECK_CAN_REPRESENT_NATIVE(const wchar_t[2], false); CHECK_CAN_REPRESENT_NATIVE(const wchar_t[2], false);
CHECK_CAN_REPRESENT_NATIVE(wchar_t(&)[2], false); CHECK_CAN_REPRESENT_NATIVE(wchar_t (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const wchar_t(&)[2], false); CHECK_CAN_REPRESENT_NATIVE(const wchar_t (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(wchar_t(&&)[2], false); CHECK_CAN_REPRESENT_NATIVE(wchar_t(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const wchar_t(&&)[2], false); CHECK_CAN_REPRESENT_NATIVE(const wchar_t(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const wchar_t*, false); CHECK_CAN_REPRESENT_NATIVE(const wchar_t*, false);
CHECK_CAN_REPRESENT_NATIVE(const wchar_t*const, false); CHECK_CAN_REPRESENT_NATIVE(const wchar_t* const, false);
CHECK_CAN_REPRESENT_NATIVE(std::wstring, !!TOML_WINDOWS_COMPAT); CHECK_CAN_REPRESENT_NATIVE(std::wstring, !!TOML_WINDOWS_COMPAT);
CHECK_CAN_REPRESENT_NATIVE(std::wstring_view, false); CHECK_CAN_REPRESENT_NATIVE(std::wstring_view, false);
#define CHECK_VALUE_EXACT(T, expected) \ #define CHECK_VALUE_EXACT(T, expected) \
static_assert(is_same_v<decltype(declval<node>().value_exact<T>()), optional<expected>>); \ static_assert(is_same_v<decltype(declval<node>().value_exact<T>()), optional<expected>>); \
static_assert(is_same_v<decltype(declval<node_view<node>>().value_exact<T>()), optional<expected>>); \ static_assert(is_same_v<decltype(declval<node_view<node>>().value_exact<T>()), optional<expected>>); \
static_assert(is_same_v<decltype(declval<node_view<const node>>().value_exact<T>()), optional<expected>>) static_assert(is_same_v<decltype(declval<node_view<const node>>().value_exact<T>()), optional<expected>>)
#define CHECK_VALUE_OR(T, expected) \ #define CHECK_VALUE_OR(T, expected) \
static_assert(is_same_v<decltype(declval<node>().value_or(declval<T>())), expected>); \ static_assert(is_same_v<decltype(declval<node>().value_or(declval<T>())), expected>); \
static_assert(is_same_v<decltype(declval<node_view<node>>().value_or(declval<T>())), expected>); \ static_assert(is_same_v<decltype(declval<node_view<node>>().value_or(declval<T>())), expected>); \
static_assert(is_same_v<decltype(declval<node_view<const node>>().value_or(declval<T>())), expected>) static_assert(is_same_v<decltype(declval<node_view<const node>>().value_or(declval<T>())), expected>)
CHECK_VALUE_EXACT( time, time); CHECK_VALUE_EXACT(time, time);
CHECK_VALUE_EXACT( date, date); CHECK_VALUE_EXACT(date, date);
CHECK_VALUE_EXACT( date_time, date_time); CHECK_VALUE_EXACT(date_time, date_time);
CHECK_VALUE_EXACT( bool, bool); CHECK_VALUE_EXACT(bool, bool);
CHECK_VALUE_EXACT( double, double); CHECK_VALUE_EXACT(double, double);
CHECK_VALUE_EXACT( int64_t, int64_t); CHECK_VALUE_EXACT(int64_t, int64_t);
CHECK_VALUE_EXACT( const char*, const char*); CHECK_VALUE_EXACT(const char*, const char*);
CHECK_VALUE_EXACT( std::string_view, std::string_view); CHECK_VALUE_EXACT(std::string_view, std::string_view);
CHECK_VALUE_EXACT( std::string, std::string); CHECK_VALUE_EXACT(std::string, std::string);
#if TOML_HAS_CHAR8 #if TOML_HAS_CHAR8
CHECK_VALUE_EXACT( const char8_t*, const char8_t*); CHECK_VALUE_EXACT(const char8_t*, const char8_t*);
CHECK_VALUE_EXACT( std::u8string_view, std::u8string_view); CHECK_VALUE_EXACT(std::u8string_view, std::u8string_view);
CHECK_VALUE_EXACT( std::u8string, std::u8string); CHECK_VALUE_EXACT(std::u8string, std::u8string);
#endif #endif
CHECK_VALUE_OR( time, time); CHECK_VALUE_OR(time, time);
CHECK_VALUE_OR( time&, time); CHECK_VALUE_OR(time&, time);
CHECK_VALUE_OR( time&&, time); CHECK_VALUE_OR(time&&, time);
CHECK_VALUE_OR( time const, time); CHECK_VALUE_OR(time const, time);
CHECK_VALUE_OR( date, date); CHECK_VALUE_OR(date, date);
CHECK_VALUE_OR( date&, date); CHECK_VALUE_OR(date&, date);
CHECK_VALUE_OR( date&&, date); CHECK_VALUE_OR(date&&, date);
CHECK_VALUE_OR( date const, date); CHECK_VALUE_OR(date const, date);
CHECK_VALUE_OR( date_time, date_time); CHECK_VALUE_OR(date_time, date_time);
CHECK_VALUE_OR( date_time&, date_time); CHECK_VALUE_OR(date_time&, date_time);
CHECK_VALUE_OR( date_time&&, date_time); CHECK_VALUE_OR(date_time&&, date_time);
CHECK_VALUE_OR( date_time const, date_time); CHECK_VALUE_OR(date_time const, date_time);
CHECK_VALUE_OR( bool, bool); CHECK_VALUE_OR(bool, bool);
CHECK_VALUE_OR( bool&, bool); CHECK_VALUE_OR(bool&, bool);
CHECK_VALUE_OR( bool&&, bool); CHECK_VALUE_OR(bool&&, bool);
CHECK_VALUE_OR( bool const, bool); CHECK_VALUE_OR(bool const, bool);
CHECK_VALUE_OR( int32_t, int32_t); CHECK_VALUE_OR(int32_t, int32_t);
CHECK_VALUE_OR( int32_t&, int32_t); CHECK_VALUE_OR(int32_t&, int32_t);
CHECK_VALUE_OR( int32_t&&, int32_t); CHECK_VALUE_OR(int32_t&&, int32_t);
CHECK_VALUE_OR( int32_t const, int32_t); CHECK_VALUE_OR(int32_t const, int32_t);
CHECK_VALUE_OR( int64_t, int64_t); CHECK_VALUE_OR(int64_t, int64_t);
CHECK_VALUE_OR( int64_t&, int64_t); CHECK_VALUE_OR(int64_t&, int64_t);
CHECK_VALUE_OR( int64_t&&, int64_t); CHECK_VALUE_OR(int64_t&&, int64_t);
CHECK_VALUE_OR( int64_t const, int64_t); CHECK_VALUE_OR(int64_t const, int64_t);
#ifdef TOML_INT128 #ifdef TOML_INT128
CHECK_VALUE_OR( TOML_INT128, TOML_INT128); CHECK_VALUE_OR(TOML_INT128, TOML_INT128);
CHECK_VALUE_OR( TOML_INT128&, TOML_INT128); CHECK_VALUE_OR(TOML_INT128&, TOML_INT128);
CHECK_VALUE_OR( TOML_INT128&&, TOML_INT128); CHECK_VALUE_OR(TOML_INT128&&, TOML_INT128);
CHECK_VALUE_OR( TOML_INT128 const, TOML_INT128); CHECK_VALUE_OR(TOML_INT128 const, TOML_INT128);
CHECK_VALUE_OR( TOML_UINT128, TOML_UINT128); CHECK_VALUE_OR(TOML_UINT128, TOML_UINT128);
CHECK_VALUE_OR( TOML_UINT128&, TOML_UINT128); CHECK_VALUE_OR(TOML_UINT128&, TOML_UINT128);
CHECK_VALUE_OR( TOML_UINT128&&, TOML_UINT128); CHECK_VALUE_OR(TOML_UINT128&&, TOML_UINT128);
CHECK_VALUE_OR( TOML_UINT128 const, TOML_UINT128); CHECK_VALUE_OR(TOML_UINT128 const, TOML_UINT128);
#endif #endif
CHECK_VALUE_OR( float, float); CHECK_VALUE_OR(float, float);
CHECK_VALUE_OR( float&, float); CHECK_VALUE_OR(float&, float);
CHECK_VALUE_OR( float&&, float); CHECK_VALUE_OR(float&&, float);
CHECK_VALUE_OR( float const, float); CHECK_VALUE_OR(float const, float);
CHECK_VALUE_OR( double, double); CHECK_VALUE_OR(double, double);
CHECK_VALUE_OR( double&, double); CHECK_VALUE_OR(double&, double);
CHECK_VALUE_OR( double&&, double); CHECK_VALUE_OR(double&&, double);
CHECK_VALUE_OR( double const, double); CHECK_VALUE_OR(double const, double);
#ifdef TOML_FLOAT128 #ifdef TOML_FLOAT128
CHECK_VALUE_OR( TOML_FLOAT128, TOML_FLOAT128); CHECK_VALUE_OR(TOML_FLOAT128, TOML_FLOAT128);
CHECK_VALUE_OR( TOML_FLOAT128&, TOML_FLOAT128); CHECK_VALUE_OR(TOML_FLOAT128&, TOML_FLOAT128);
CHECK_VALUE_OR( TOML_FLOAT128&&, TOML_FLOAT128); CHECK_VALUE_OR(TOML_FLOAT128&&, TOML_FLOAT128);
CHECK_VALUE_OR( TOML_FLOAT128 const, TOML_FLOAT128); CHECK_VALUE_OR(TOML_FLOAT128 const, TOML_FLOAT128);
#endif #endif
CHECK_VALUE_OR( char*, const char*); CHECK_VALUE_OR(char*, const char*);
CHECK_VALUE_OR( char*&, const char*); CHECK_VALUE_OR(char*&, const char*);
CHECK_VALUE_OR( char*&&, const char*); CHECK_VALUE_OR(char*&&, const char*);
CHECK_VALUE_OR( char*const, const char*); CHECK_VALUE_OR(char* const, const char*);
CHECK_VALUE_OR( char[2], const char*); CHECK_VALUE_OR(char[2], const char*);
CHECK_VALUE_OR( char(&)[2], const char*); CHECK_VALUE_OR(char (&)[2], const char*);
CHECK_VALUE_OR( char(&&)[2], const char*); CHECK_VALUE_OR(char(&&)[2], const char*);
CHECK_VALUE_OR( const char*, const char*); CHECK_VALUE_OR(const char*, const char*);
CHECK_VALUE_OR( const char*&, const char*); CHECK_VALUE_OR(const char*&, const char*);
CHECK_VALUE_OR( const char*&&, const char*); CHECK_VALUE_OR(const char*&&, const char*);
CHECK_VALUE_OR( const char*const, const char*); CHECK_VALUE_OR(const char* const, const char*);
CHECK_VALUE_OR( const char[2], const char*); CHECK_VALUE_OR(const char[2], const char*);
CHECK_VALUE_OR( const char(&)[2], const char*); CHECK_VALUE_OR(const char (&)[2], const char*);
CHECK_VALUE_OR( const char(&&)[2], const char*); CHECK_VALUE_OR(const char(&&)[2], const char*);
CHECK_VALUE_OR( std::string_view, std::string_view); CHECK_VALUE_OR(std::string_view, std::string_view);
CHECK_VALUE_OR( std::string_view&, std::string_view); CHECK_VALUE_OR(std::string_view&, std::string_view);
CHECK_VALUE_OR( std::string_view&&, std::string_view); CHECK_VALUE_OR(std::string_view&&, std::string_view);
CHECK_VALUE_OR( const std::string_view, std::string_view); CHECK_VALUE_OR(const std::string_view, std::string_view);
CHECK_VALUE_OR( const std::string_view&, std::string_view); CHECK_VALUE_OR(const std::string_view&, std::string_view);
CHECK_VALUE_OR( const std::string_view&&, std::string_view); CHECK_VALUE_OR(const std::string_view&&, std::string_view);
CHECK_VALUE_OR( std::string, std::string); CHECK_VALUE_OR(std::string, std::string);
CHECK_VALUE_OR( std::string&, std::string); CHECK_VALUE_OR(std::string&, std::string);
CHECK_VALUE_OR( std::string&&, std::string); CHECK_VALUE_OR(std::string&&, std::string);
CHECK_VALUE_OR( const std::string, std::string); CHECK_VALUE_OR(const std::string, std::string);
CHECK_VALUE_OR( const std::string&, std::string); CHECK_VALUE_OR(const std::string&, std::string);
CHECK_VALUE_OR( const std::string&&, std::string); CHECK_VALUE_OR(const std::string&&, std::string);
#if TOML_HAS_CHAR8 #if TOML_HAS_CHAR8
CHECK_VALUE_OR( char8_t*, const char8_t*); CHECK_VALUE_OR(char8_t*, const char8_t*);
CHECK_VALUE_OR( char8_t*&, const char8_t*); CHECK_VALUE_OR(char8_t*&, const char8_t*);
CHECK_VALUE_OR( char8_t*&&, const char8_t*); CHECK_VALUE_OR(char8_t*&&, const char8_t*);
CHECK_VALUE_OR( char8_t*const, const char8_t*); CHECK_VALUE_OR(char8_t* const, const char8_t*);
CHECK_VALUE_OR( char8_t[2], const char8_t*); CHECK_VALUE_OR(char8_t[2], const char8_t*);
CHECK_VALUE_OR( char8_t(&)[2], const char8_t*); CHECK_VALUE_OR(char8_t (&)[2], const char8_t*);
CHECK_VALUE_OR( char8_t(&&)[2], const char8_t*); CHECK_VALUE_OR(char8_t(&&)[2], const char8_t*);
CHECK_VALUE_OR( const char8_t*, const char8_t*); CHECK_VALUE_OR(const char8_t*, const char8_t*);
CHECK_VALUE_OR( const char8_t*&, const char8_t*); CHECK_VALUE_OR(const char8_t*&, const char8_t*);
CHECK_VALUE_OR( const char8_t*&&, const char8_t*); CHECK_VALUE_OR(const char8_t*&&, const char8_t*);
CHECK_VALUE_OR( const char8_t*const, const char8_t*); CHECK_VALUE_OR(const char8_t* const, const char8_t*);
CHECK_VALUE_OR( const char8_t[2], const char8_t*); CHECK_VALUE_OR(const char8_t[2], const char8_t*);
CHECK_VALUE_OR( const char8_t(&)[2], const char8_t*); CHECK_VALUE_OR(const char8_t (&)[2], const char8_t*);
CHECK_VALUE_OR( const char8_t(&&)[2], const char8_t*); CHECK_VALUE_OR(const char8_t(&&)[2], const char8_t*);
CHECK_VALUE_OR( std::u8string_view, std::u8string_view); CHECK_VALUE_OR(std::u8string_view, std::u8string_view);
CHECK_VALUE_OR( std::u8string_view&, std::u8string_view); CHECK_VALUE_OR(std::u8string_view&, std::u8string_view);
CHECK_VALUE_OR( std::u8string_view&&, std::u8string_view); CHECK_VALUE_OR(std::u8string_view&&, std::u8string_view);
CHECK_VALUE_OR( const std::u8string_view, std::u8string_view); CHECK_VALUE_OR(const std::u8string_view, std::u8string_view);
CHECK_VALUE_OR( const std::u8string_view&, std::u8string_view); CHECK_VALUE_OR(const std::u8string_view&, std::u8string_view);
CHECK_VALUE_OR( const std::u8string_view&&, std::u8string_view); CHECK_VALUE_OR(const std::u8string_view&&, std::u8string_view);
CHECK_VALUE_OR( std::u8string, std::u8string); CHECK_VALUE_OR(std::u8string, std::u8string);
CHECK_VALUE_OR( std::u8string&, std::u8string); CHECK_VALUE_OR(std::u8string&, std::u8string);
CHECK_VALUE_OR( std::u8string&&, std::u8string); CHECK_VALUE_OR(std::u8string&&, std::u8string);
CHECK_VALUE_OR( const std::u8string, std::u8string); CHECK_VALUE_OR(const std::u8string, std::u8string);
CHECK_VALUE_OR( const std::u8string&, std::u8string); CHECK_VALUE_OR(const std::u8string&, std::u8string);
CHECK_VALUE_OR( const std::u8string&&, std::u8string); CHECK_VALUE_OR(const std::u8string&&, std::u8string);
#endif #endif
#if TOML_WINDOWS_COMPAT #if TOML_WINDOWS_COMPAT
CHECK_VALUE_OR( wchar_t*, std::wstring); CHECK_VALUE_OR(wchar_t*, std::wstring);
CHECK_VALUE_OR( wchar_t*&, std::wstring); CHECK_VALUE_OR(wchar_t*&, std::wstring);
CHECK_VALUE_OR( wchar_t*&&, std::wstring); CHECK_VALUE_OR(wchar_t*&&, std::wstring);
CHECK_VALUE_OR( wchar_t*const, std::wstring); CHECK_VALUE_OR(wchar_t* const, std::wstring);
CHECK_VALUE_OR( wchar_t[2], std::wstring); CHECK_VALUE_OR(wchar_t[2], std::wstring);
CHECK_VALUE_OR( wchar_t(&)[2], std::wstring); CHECK_VALUE_OR(wchar_t (&)[2], std::wstring);
CHECK_VALUE_OR( wchar_t(&&)[2], std::wstring); CHECK_VALUE_OR(wchar_t(&&)[2], std::wstring);
CHECK_VALUE_OR( const wchar_t*, std::wstring); CHECK_VALUE_OR(const wchar_t*, std::wstring);
CHECK_VALUE_OR( const wchar_t*&, std::wstring); CHECK_VALUE_OR(const wchar_t*&, std::wstring);
CHECK_VALUE_OR( const wchar_t*&&, std::wstring); CHECK_VALUE_OR(const wchar_t*&&, std::wstring);
CHECK_VALUE_OR( const wchar_t*const, std::wstring); CHECK_VALUE_OR(const wchar_t* const, std::wstring);
CHECK_VALUE_OR( const wchar_t[2], std::wstring); CHECK_VALUE_OR(const wchar_t[2], std::wstring);
CHECK_VALUE_OR( const wchar_t(&)[2], std::wstring); CHECK_VALUE_OR(const wchar_t (&)[2], std::wstring);
CHECK_VALUE_OR( const wchar_t(&&)[2], std::wstring); CHECK_VALUE_OR(const wchar_t(&&)[2], std::wstring);
CHECK_VALUE_OR( std::wstring_view, std::wstring); CHECK_VALUE_OR(std::wstring_view, std::wstring);
CHECK_VALUE_OR( std::wstring_view&, std::wstring); CHECK_VALUE_OR(std::wstring_view&, std::wstring);
CHECK_VALUE_OR( std::wstring_view&&, std::wstring); CHECK_VALUE_OR(std::wstring_view&&, std::wstring);
CHECK_VALUE_OR( const std::wstring_view, std::wstring); CHECK_VALUE_OR(const std::wstring_view, std::wstring);
CHECK_VALUE_OR( const std::wstring_view&, std::wstring); CHECK_VALUE_OR(const std::wstring_view&, std::wstring);
CHECK_VALUE_OR( const std::wstring_view&&, std::wstring); CHECK_VALUE_OR(const std::wstring_view&&, std::wstring);
CHECK_VALUE_OR( std::wstring, std::wstring); CHECK_VALUE_OR(std::wstring, std::wstring);
CHECK_VALUE_OR( std::wstring&, std::wstring); CHECK_VALUE_OR(std::wstring&, std::wstring);
CHECK_VALUE_OR( std::wstring&&, std::wstring); CHECK_VALUE_OR(std::wstring&&, std::wstring);
CHECK_VALUE_OR( const std::wstring, std::wstring); CHECK_VALUE_OR(const std::wstring, std::wstring);
CHECK_VALUE_OR( const std::wstring&, std::wstring); CHECK_VALUE_OR(const std::wstring&, std::wstring);
CHECK_VALUE_OR( const std::wstring&&, std::wstring); CHECK_VALUE_OR(const std::wstring&&, std::wstring);
#endif #endif
#define CHECK_INSERTED_AS(T, expected) \ #define CHECK_INSERTED_AS(T, expected) \
static_assert(std::is_same_v<expected, toml::inserted_type_of<T>>); \ static_assert(std::is_same_v<expected, toml::inserted_type_of<T>>); \
static_assert(std::is_same_v<expected, toml::inserted_type_of<const T>>); \ static_assert(std::is_same_v<expected, toml::inserted_type_of<const T>>); \
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&>>); \ static_assert(std::is_same_v<expected, toml::inserted_type_of<T&>>); \
static_assert(std::is_same_v<expected, toml::inserted_type_of<const T&>>); \ static_assert(std::is_same_v<expected, toml::inserted_type_of<const T&>>); \
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&&>>) static_assert(std::is_same_v<expected, toml::inserted_type_of<T&&>>)
CHECK_INSERTED_AS(table, table); CHECK_INSERTED_AS(table, table);
CHECK_INSERTED_AS(array, array); CHECK_INSERTED_AS(array, array);
CHECK_INSERTED_AS(node, node); CHECK_INSERTED_AS(node, node);
CHECK_INSERTED_AS(time, value<time>); CHECK_INSERTED_AS(time, value<time>);
CHECK_INSERTED_AS(date, value<date>); CHECK_INSERTED_AS(date, value<date>);
CHECK_INSERTED_AS(date_time, value<date_time>); CHECK_INSERTED_AS(date_time, value<date_time>);
CHECK_INSERTED_AS(bool, value<bool>); CHECK_INSERTED_AS(bool, value<bool>);
CHECK_INSERTED_AS(int8_t, value<int64_t>); CHECK_INSERTED_AS(int8_t, value<int64_t>);
CHECK_INSERTED_AS(int16_t, value<int64_t>); CHECK_INSERTED_AS(int16_t, value<int64_t>);
CHECK_INSERTED_AS(int32_t, value<int64_t>); CHECK_INSERTED_AS(int32_t, value<int64_t>);
CHECK_INSERTED_AS(int64_t, value<int64_t>); CHECK_INSERTED_AS(int64_t, value<int64_t>);
CHECK_INSERTED_AS(uint8_t, value<int64_t>); CHECK_INSERTED_AS(uint8_t, value<int64_t>);
CHECK_INSERTED_AS(uint16_t, value<int64_t>); CHECK_INSERTED_AS(uint16_t, value<int64_t>);
CHECK_INSERTED_AS(uint32_t, value<int64_t>); CHECK_INSERTED_AS(uint32_t, value<int64_t>);
CHECK_INSERTED_AS(float, value<double>); CHECK_INSERTED_AS(float, value<double>);
CHECK_INSERTED_AS(double, value<double>); CHECK_INSERTED_AS(double, value<double>);
#ifdef TOML_FP16 #ifdef TOML_FP16
CHECK_INSERTED_AS(TOML_FP16, value<double>); CHECK_INSERTED_AS(TOML_FP16, value<double>);
#endif #endif
#ifdef TOML_FLOAT16 #ifdef TOML_FLOAT16
CHECK_INSERTED_AS(TOML_FLOAT16, value<double>); CHECK_INSERTED_AS(TOML_FLOAT16, value<double>);
#endif #endif
static_assert(is_same_v<decltype(declval<node&>().ref<double>()), double&>); static_assert(is_same_v<decltype(declval<node&>().ref<double>()), double&>);
static_assert(is_same_v<decltype(declval<node&&>().ref<double>()), double&&>); static_assert(is_same_v<decltype(declval<node&&>().ref<double>()), double&&>);

View File

@ -10,10 +10,10 @@ namespace leakproof
void value_destroyed() noexcept; void value_destroyed() noexcept;
} }
#define TOML_LIFETIME_HOOKS 1 #define TOML_LIFETIME_HOOKS 1
#define TOML_TABLE_CREATED ::leakproof::table_created() #define TOML_TABLE_CREATED ::leakproof::table_created()
#define TOML_TABLE_DESTROYED ::leakproof::table_destroyed() #define TOML_TABLE_DESTROYED ::leakproof::table_destroyed()
#define TOML_ARRAY_CREATED ::leakproof::array_created() #define TOML_ARRAY_CREATED ::leakproof::array_created()
#define TOML_ARRAY_DESTROYED ::leakproof::array_destroyed() #define TOML_ARRAY_DESTROYED ::leakproof::array_destroyed()
#define TOML_VALUE_CREATED ::leakproof::value_created() #define TOML_VALUE_CREATED ::leakproof::value_created()
#define TOML_VALUE_DESTROYED ::leakproof::value_destroyed() #define TOML_VALUE_DESTROYED ::leakproof::value_destroyed()

37
tests/lib_catch2.h Normal file
View File

@ -0,0 +1,37 @@
// This file is a part of toml++ and is subject to the the terms of the MIT license.
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
#include "settings.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra"
#pragma GCC diagnostic ignored "-Wpadded"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#elif defined(_MSC_VER)
#pragma warning(push, 0)
#pragma warning(disable : 4365)
#pragma warning(disable : 4868)
#pragma warning(disable : 5105)
#endif
#if __has_include(<Catch2/single_include/catch2/catch.hpp>)
#include <Catch2/single_include/catch2/catch.hpp>
#else
#error Catch2 is missing! You probably need to fetch submodules ("git submodule update --init --depth 1 external/Catch2")
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif

View File

@ -2,13 +2,12 @@
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> // Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything" #pragma clang diagnostic ignored "-Weverything"
#elif defined (__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall" #pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra" #pragma GCC diagnostic ignored "-Wextra"
@ -17,14 +16,13 @@
#endif #endif
#if __has_include(<tloptional/include/tl/optional.hpp>) #if __has_include(<tloptional/include/tl/optional.hpp>)
#include <tloptional/include/tl/optional.hpp> #include <tloptional/include/tl/optional.hpp>
#else #else
#error TartanLlama/optional is missing! You probably need to fetch submodules ("git submodule update --init --depth 1 external/tloptional") #error TartanLlama/optional is missing! You probably need to fetch submodules ("git submodule update --init --depth 1 external/tloptional")
#endif #endif
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic pop #pragma clang diagnostic pop
#elif defined (__GNUC__) #elif defined(__GNUC__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif

View File

@ -4,41 +4,71 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define CATCH_CONFIG_RUNNER #define CATCH_CONFIG_RUNNER
#include "catch2.h" #include "lib_catch2.h"
#include <clocale> #include <clocale>
#if LEAK_TESTS #if LEAK_TESTS
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <atomic> #include <atomic>
#include "leakproof.h" #include "leakproof.h"
using namespace std::string_view_literals; using namespace std::string_view_literals;
namespace leakproof namespace leakproof
{ {
static std::atomic_llong total_created_ = 0LL; static std::atomic_llong total_created_ = 0LL;
static std::atomic_llong tables_ = 0LL; static std::atomic_llong tables_ = 0LL;
static std::atomic_llong arrays_ = 0LL; static std::atomic_llong arrays_ = 0LL;
static std::atomic_llong values_ = 0LL; static std::atomic_llong values_ = 0LL;
void table_created() noexcept { tables_++; total_created_++; }
void array_created() noexcept { arrays_++; total_created_++; } void table_created() noexcept
void value_created() noexcept { values_++; total_created_++; } {
void table_destroyed() noexcept { tables_--; } tables_++;
void array_destroyed() noexcept { arrays_--; } total_created_++;
void value_destroyed() noexcept { values_--; } }
void array_created() noexcept
{
arrays_++;
total_created_++;
}
void value_created() noexcept
{
values_++;
total_created_++;
}
void table_destroyed() noexcept
{
tables_--;
}
void array_destroyed() noexcept
{
arrays_--;
}
void value_destroyed() noexcept
{
values_--;
}
} }
#endif
#endif // LEAK_TESTS
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
#ifdef _WIN32 #ifdef _WIN32
SetConsoleOutputCP(65001); SetConsoleOutputCP(65001);
#endif #endif
std::setlocale(LC_ALL, ""); std::setlocale(LC_ALL, "");
std::locale::global(std::locale("")); std::locale::global(std::locale(""));
if (auto result = Catch::Session().run(argc, argv)) if (auto result = Catch::Session().run(argc, argv))
return result; return result;
#if LEAK_TESTS #if LEAK_TESTS
constexpr auto handle_leak_result = [](std::string_view name, long long count) noexcept constexpr auto handle_leak_result = [](std::string_view name, long long count) noexcept
{ {
std::cout << "\n"sv << name << ": "sv << std::right << std::setw(6) << count; std::cout << "\n"sv << name << ": "sv << std::right << std::setw(6) << count;
@ -50,13 +80,13 @@ int main(int argc, char* argv[])
}; };
std::cout << "\n---------- leak test results ----------"sv; std::cout << "\n---------- leak test results ----------"sv;
bool ok = true; bool ok = true;
ok = handle_leak_result("tables"sv, leakproof::tables_.load()) && ok; ok = handle_leak_result("tables"sv, leakproof::tables_.load()) && ok;
ok = handle_leak_result("arrays"sv, leakproof::arrays_.load()) && ok; ok = handle_leak_result("arrays"sv, leakproof::arrays_.load()) && ok;
ok = handle_leak_result("values"sv, leakproof::values_.load()) && ok; ok = handle_leak_result("values"sv, leakproof::values_.load()) && ok;
std::cout << "\n(total objects created: "sv << leakproof::total_created_.load() << ")"sv; std::cout << "\n(total objects created: "sv << leakproof::total_created_.load() << ")"sv;
std::cout << "\n---------------------------------------"sv; std::cout << "\n---------------------------------------"sv;
return ok ? 0 : -1; return ok ? 0 : -1;
#else #else
return 0; return 0;
#endif #endif
} }

View File

@ -64,8 +64,7 @@ TEST_CASE("arrays - moving")
CHECK(!arr2.source().path); CHECK(!arr2.source().path);
CHECK(arr2.size() == 0u); CHECK(arr2.size() == 0u);
}, },
filename filename);
);
} }
TEST_CASE("arrays - copying") TEST_CASE("arrays - copying")
@ -116,8 +115,7 @@ TEST_CASE("arrays - copying")
CHECK(arr3 == *arr1); CHECK(arr3 == *arr1);
CHECK(arr3 == arr2); CHECK(arr3 == arr2);
}, },
filename filename);
);
} }
TEST_CASE("arrays - construction") TEST_CASE("arrays - construction")
@ -133,7 +131,7 @@ TEST_CASE("arrays - construction")
CHECK(!arr.source().path); CHECK(!arr.source().path);
CHECK(!arr.is_homogeneous()); CHECK(!arr.is_homogeneous());
} }
{ {
array arr{ 42 }; array arr{ 42 };
CHECK(arr.size() == 1u); CHECK(arr.size() == 1u);
@ -163,7 +161,7 @@ TEST_CASE("arrays - construction")
CHECK(!arr.is_homogeneous()); CHECK(!arr.is_homogeneous());
} }
#if TOML_WINDOWS_COMPAT #if TOML_WINDOWS_COMPAT
{ {
array arr{ "mixed", "string"sv, L"test", L"kek"sv }; array arr{ "mixed", "string"sv, L"test", L"kek"sv };
CHECK(arr.size() == 4u); CHECK(arr.size() == 4u);
@ -174,7 +172,7 @@ TEST_CASE("arrays - construction")
CHECK(*arr.get_as<std::string>(2) == "test"sv); CHECK(*arr.get_as<std::string>(2) == "test"sv);
CHECK(*arr.get_as<std::string>(3) == "kek"sv); CHECK(*arr.get_as<std::string>(3) == "kek"sv);
} }
#endif // TOML_WINDOWS_COMPAT #endif // TOML_WINDOWS_COMPAT
} }
TEST_CASE("arrays - equality") TEST_CASE("arrays - equality")
@ -373,12 +371,12 @@ TEST_CASE("arrays - insertion and erasure")
CHECK(*arr.get_as<double>(5u) == 3.0); CHECK(*arr.get_as<double>(5u) == 3.0);
} }
#if TOML_WINDOWS_COMPAT #if TOML_WINDOWS_COMPAT
arr.clear(); arr.clear();
it = arr.insert(arr.cbegin(), L"test"); it = arr.insert(arr.cbegin(), L"test");
REQUIRE(*arr.get_as<std::string>(0u) == "test"sv); REQUIRE(*arr.get_as<std::string>(0u) == "test"sv);
it = arr.emplace<std::string>(arr.cbegin(), L"test2"sv); it = arr.emplace<std::string>(arr.cbegin(), L"test2"sv);
REQUIRE(*arr.get_as<std::string>(0u) == "test2"sv); REQUIRE(*arr.get_as<std::string>(0u) == "test2"sv);
@ -388,30 +386,37 @@ TEST_CASE("arrays - insertion and erasure")
arr.emplace_back<std::string>(L"test4"); arr.emplace_back<std::string>(L"test4");
REQUIRE(*arr.back().as_string() == "test4"sv); REQUIRE(*arr.back().as_string() == "test4"sv);
#endif // TOML_WINDOWS_COMPAT #endif // TOML_WINDOWS_COMPAT
} }
TEST_CASE("arrays - flattening") TEST_CASE("arrays - flattening")
{ {
{ {
array arr{ array arr{
1, 2, 3, 1,
2,
3,
array{ 4, 5 }, array{ 4, 5 },
6, 6,
array{}, array{},
array{ 7, array{ 8, array{ 9 }, 10, array{}, }, 11 }, array{ 7,
array{
8,
array{ 9 },
10,
array{},
},
11 },
}; };
arr.flatten(); arr.flatten();
REQUIRE(arr == array{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }); REQUIRE(arr == array{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 });
} }
{ {
array arr{ array arr{ array{},
array{}, array{ inserter{ array{} } },
array{inserter{array{}}}, array{ array{}, array{ array{}, array{} }, array{} },
array{array{},array{array{},array{}},array{}}, array{ array{ array{ array{ array{ array{ 1 } } } } } } };
array{array{array{array{array{array{ 1 }}}}}}
};
arr.flatten(); arr.flatten();
REQUIRE(arr == array{ 1 }); REQUIRE(arr == array{ 1 });
} }
@ -442,7 +447,7 @@ TEST_CASE("arrays - resizing and truncation")
REQUIRE(arr.size() == 2u); REQUIRE(arr.size() == 2u);
REQUIRE(arr == array{ 1, 2 }); REQUIRE(arr == array{ 1, 2 });
//resize up to six elements // resize up to six elements
arr.resize(6u, 42); arr.resize(6u, 42);
REQUIRE(arr.size() == 6u); REQUIRE(arr.size() == 6u);
REQUIRE(arr == array{ 1, 2, 42, 42, 42, 42 }); REQUIRE(arr == array{ 1, 2, 42, 42, 42, 42 });

View File

@ -25,7 +25,7 @@ TEST_CASE("parse_result - good parse")
REQUIRE(!static_cast<table&>(result).empty()); REQUIRE(!static_cast<table&>(result).empty());
REQUIRE(!static_cast<table&&>(result).empty()); REQUIRE(!static_cast<table&&>(result).empty());
REQUIRE(!static_cast<const table&>(result).empty()); REQUIRE(!static_cast<const table&>(result).empty());
auto& tbl = static_cast<table&>(result); auto& tbl = static_cast<table&>(result);
CHECK(tbl["key"sv]); CHECK(tbl["key"sv]);
CHECK(result["key"sv]); CHECK(result["key"sv]);
@ -38,7 +38,7 @@ TEST_CASE("parse_result - good parse")
CHECK(result.cbegin() != tbl.cend()); CHECK(result.cbegin() != tbl.cend());
auto& cresult = static_cast<const parse_result&>(result); auto& cresult = static_cast<const parse_result&>(result);
auto& ctbl = static_cast<const table&>(cresult); auto& ctbl = static_cast<const table&>(cresult);
CHECK(cresult.begin() == ctbl.begin()); CHECK(cresult.begin() == ctbl.begin());
CHECK(cresult.end() == ctbl.end()); CHECK(cresult.end() == ctbl.end());
CHECK(cresult.begin() != ctbl.end()); CHECK(cresult.begin() != ctbl.end());
@ -52,19 +52,22 @@ TEST_CASE("parse_result - good parse")
size_t tbl_iterations{}; size_t tbl_iterations{};
for (auto&& [k, v] : tbl) for (auto&& [k, v] : tbl)
{ {
(void)k; (void)v; (void)k;
(void)v;
tbl_iterations++; tbl_iterations++;
} }
size_t result_iterations{}; size_t result_iterations{};
for (auto& [k, v] : result) for (auto& [k, v] : result)
{ {
(void)k; (void)v; (void)k;
(void)v;
result_iterations++; result_iterations++;
} }
size_t cresult_iterations{}; size_t cresult_iterations{};
for (auto [k, v] : cresult) for (auto [k, v] : cresult)
{ {
(void)k; (void)v; (void)k;
(void)v;
cresult_iterations++; cresult_iterations++;
} }
CHECK(tbl_iterations == tbl.size()); CHECK(tbl_iterations == tbl.size());
@ -72,7 +75,6 @@ TEST_CASE("parse_result - good parse")
CHECK(tbl_iterations == cresult_iterations); CHECK(tbl_iterations == cresult_iterations);
} }
TEST_CASE("parse_result - bad parse") TEST_CASE("parse_result - bad parse")
{ {
auto result = "key = trUe"_toml; auto result = "key = trUe"_toml;
@ -98,15 +100,16 @@ TEST_CASE("parse_result - bad parse")
for (auto [k, v] : result) for (auto [k, v] : result)
{ {
(void)k; (void)v; (void)k;
(void)v;
FAIL("This code should not run"); FAIL("This code should not run");
} }
for (auto [k, v] : cresult) for (auto [k, v] : cresult)
{ {
(void)k; (void)v; (void)k;
(void)v;
FAIL("This code should not run"); FAIL("This code should not run");
} }
} }
#endif //!TOML_EXCEPTIONS #endif //!TOML_EXCEPTIONS

View File

@ -64,8 +64,7 @@ TEST_CASE("tables - moving")
CHECK(tbl2.size() == 0u); CHECK(tbl2.size() == 0u);
CHECK(!tbl2["test"].as<table>()); CHECK(!tbl2["test"].as<table>());
}, },
filename filename);
);
} }
TEST_CASE("tables - copying") TEST_CASE("tables - copying")
@ -114,8 +113,7 @@ TEST_CASE("tables - copying")
CHECK(tbl3 == tbl2); CHECK(tbl3 == tbl2);
CHECK(tbl3 == tbl); CHECK(tbl3 == tbl);
}, },
filename filename);
);
} }
TEST_CASE("tables - construction") TEST_CASE("tables - construction")
@ -132,9 +130,7 @@ TEST_CASE("tables - construction")
} }
{ {
table tbl{{ table tbl{ { { "foo"sv, 42 } } };
{ "foo"sv, 42 }
}};
CHECK(tbl.size() == 1u); CHECK(tbl.size() == 1u);
CHECK(!tbl.empty()); CHECK(!tbl.empty());
CHECK(tbl.begin() != tbl.end()); CHECK(tbl.begin() != tbl.end());
@ -144,12 +140,7 @@ TEST_CASE("tables - construction")
} }
{ {
table tbl{{ table tbl{ { { "foo"sv, 42 }, { "bar"sv, 10.0 }, { "kek"sv, false }, { "qux"sv, array{ 1 } } } };
{ "foo"sv, 42 },
{ "bar"sv, 10.0 },
{ "kek"sv, false },
{ "qux"sv, array{ 1 } }
}};
CHECK(tbl.size() == 4u); CHECK(tbl.size() == 4u);
CHECK(!tbl.empty()); CHECK(!tbl.empty());
REQUIRE(tbl.get_as<int64_t>("foo"sv)); REQUIRE(tbl.get_as<int64_t>("foo"sv));
@ -162,14 +153,12 @@ TEST_CASE("tables - construction")
CHECK(*tbl.get_as<array>("qux"sv) == array{ 1 }); CHECK(*tbl.get_as<array>("qux"sv) == array{ 1 });
} }
#if TOML_WINDOWS_COMPAT #if TOML_WINDOWS_COMPAT
{ {
table tbl{ { table tbl{ { { L"foo", L"test1" },
{ L"foo", L"test1" }, { L"bar"sv, L"test2"sv },
{ L"bar"sv, L"test2"sv }, { L"kek"s, L"test3"sv },
{ L"kek"s, L"test3"sv }, { L"qux"sv.data(), L"test4"sv.data() } } };
{ L"qux"sv.data(), L"test4"sv.data() }
} };
CHECK(tbl.size() == 4u); CHECK(tbl.size() == 4u);
CHECK(!tbl.empty()); CHECK(!tbl.empty());
REQUIRE(tbl.get_as<std::string>("foo"sv)); REQUIRE(tbl.get_as<std::string>("foo"sv));
@ -181,46 +170,26 @@ TEST_CASE("tables - construction")
REQUIRE(tbl.get_as<std::string>("qux"sv)); REQUIRE(tbl.get_as<std::string>("qux"sv));
CHECK(*tbl.get_as<std::string>("qux"sv) == "test4"sv); CHECK(*tbl.get_as<std::string>("qux"sv) == "test4"sv);
} }
#endif // TOML_WINDOWS_COMPAT #endif // TOML_WINDOWS_COMPAT
} }
TEST_CASE("tables - equality") TEST_CASE("tables - equality")
{ {
static constexpr const char* one = "one"; static constexpr const char* one = "one";
table tbl1{{ table tbl1{ { { one, 1 }, { "two", 2 }, { "three", 3 } } };
{ one, 1 },
{ "two", 2 },
{ "three", 3 }
}};
CHECK(tbl1 == tbl1); CHECK(tbl1 == tbl1);
table tbl2{{ table tbl2{ { { "one"sv, 1 }, { "two"sv, 2 }, { "three"sv, 3 } } };
{ "one"sv, 1 },
{ "two"sv, 2 },
{ "three"sv, 3 }
}};
CHECK(tbl1 == tbl2); CHECK(tbl1 == tbl2);
table tbl3{{ table tbl3{ { { "one"sv, 1 }, { "two"sv, 2 } } };
{ "one"sv, 1 },
{ "two"sv, 2 }
}};
CHECK(tbl1 != tbl3); CHECK(tbl1 != tbl3);
table tbl4{{ table tbl4{ { { "one"sv, 1 }, { "two"sv, 2 }, { "three"sv, 3 }, { "four"sv, 4 } } };
{ "one"sv, 1 },
{ "two"sv, 2 },
{ "three"sv, 3 },
{ "four"sv, 4 }
}};
CHECK(tbl1 != tbl4); CHECK(tbl1 != tbl4);
table tbl5{{ table tbl5{ { { "one"sv, 1 }, { "two"sv, 2 }, { "three"sv, 3.0 } } };
{ "one"sv, 1 },
{ "two"sv, 2 },
{ "three"sv, 3.0 }
}};
CHECK(tbl1 != tbl5); CHECK(tbl1 != tbl5);
table tbl6{}; table tbl6{};
@ -260,7 +229,7 @@ TEST_CASE("tables - insertion and erasure")
CHECK(!tbl.empty()); CHECK(!tbl.empty());
REQUIRE(tbl.get_as<int64_t>("a"sv)); REQUIRE(tbl.get_as<int64_t>("a"sv));
CHECK(*tbl.get_as<int64_t>("a"sv) == 42); CHECK(*tbl.get_as<int64_t>("a"sv) == 42);
REQUIRE(tbl == table{{ { "a"sv, 42 } }}); REQUIRE(tbl == table{ { { "a"sv, 42 } } });
res = tbl.insert("a", 69); res = tbl.insert("a", 69);
CHECK(res.first == tbl.begin()); CHECK(res.first == tbl.begin());
@ -268,16 +237,16 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 1u); CHECK(tbl.size() == 1u);
REQUIRE(tbl.get_as<int64_t>("a")); REQUIRE(tbl.get_as<int64_t>("a"));
CHECK(*tbl.get_as<int64_t>("a") == 42); CHECK(*tbl.get_as<int64_t>("a") == 42);
REQUIRE(tbl == table{{ { "a"sv, 42 } }}); REQUIRE(tbl == table{ { { "a"sv, 42 } } });
static constexpr const char* a = "a"; static constexpr const char* a = "a";
res = tbl.insert_or_assign(a, 69); res = tbl.insert_or_assign(a, 69);
CHECK(res.first == tbl.begin()); CHECK(res.first == tbl.begin());
CHECK(res.second == false); // should assign CHECK(res.second == false); // should assign
CHECK(tbl.size() == 1u); CHECK(tbl.size() == 1u);
REQUIRE(tbl.get_as<int64_t>("a")); REQUIRE(tbl.get_as<int64_t>("a"));
CHECK(*tbl.get_as<int64_t>("a") == 69); CHECK(*tbl.get_as<int64_t>("a") == 69);
REQUIRE(tbl == table{{ { "a"sv, 69 } }}); REQUIRE(tbl == table{ { { "a"sv, 69 } } });
res = tbl.insert_or_assign("b", "kek"); res = tbl.insert_or_assign("b", "kek");
CHECK(res.first == advance(tbl.begin(), 1)); CHECK(res.first == advance(tbl.begin(), 1));
@ -285,7 +254,7 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 2u); CHECK(tbl.size() == 2u);
REQUIRE(tbl.get_as<std::string>("b")); REQUIRE(tbl.get_as<std::string>("b"));
CHECK(*tbl.get_as<std::string>("b") == "kek"sv); CHECK(*tbl.get_as<std::string>("b") == "kek"sv);
REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek" } }}); REQUIRE(tbl == table{ { { "a"sv, 69 }, { "b"sv, "kek" } } });
res = tbl.emplace<array>("c", 1, 2, 3); res = tbl.emplace<array>("c", 1, 2, 3);
CHECK(res.first == advance(tbl.begin(), 2)); CHECK(res.first == advance(tbl.begin(), 2));
@ -293,7 +262,7 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 3u); CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<array>("c")); REQUIRE(tbl.get_as<array>("c"));
CHECK(*tbl.get_as<array>("c") == array{ 1, 2, 3 }); CHECK(*tbl.get_as<array>("c") == array{ 1, 2, 3 });
REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek"sv }, { "c"sv, array{ 1, 2, 3 } } }}); REQUIRE(tbl == table{ { { "a"sv, 69 }, { "b"sv, "kek"sv }, { "c"sv, array{ 1, 2, 3 } } } });
res = tbl.emplace<int64_t>("c", 1); res = tbl.emplace<int64_t>("c", 1);
CHECK(res.first == advance(tbl.begin(), 2)); CHECK(res.first == advance(tbl.begin(), 2));
@ -301,10 +270,10 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 3u); CHECK(tbl.size() == 3u);
REQUIRE(!tbl.get_as<int64_t>("c")); REQUIRE(!tbl.get_as<int64_t>("c"));
REQUIRE(tbl.get_as<array>("c")); REQUIRE(tbl.get_as<array>("c"));
REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek"s }, { "c"sv, array{ 1, 2, 3 } } }}); REQUIRE(tbl == table{ { { "a"sv, 69 }, { "b"sv, "kek"s }, { "c"sv, array{ 1, 2, 3 } } } });
auto it = tbl.erase(tbl.cbegin()); auto it = tbl.erase(tbl.cbegin());
REQUIRE(tbl == table{{ { "b"sv, "kek" }, { "c"sv, array{ 1, 2, 3 } } }}); REQUIRE(tbl == table{ { { "b"sv, "kek" }, { "c"sv, array{ 1, 2, 3 } } } });
CHECK(it == tbl.begin()); CHECK(it == tbl.begin());
CHECK(tbl.size() == 2u); CHECK(tbl.size() == 2u);
@ -314,10 +283,10 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 3u); CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<int64_t>("a")); REQUIRE(tbl.get_as<int64_t>("a"));
CHECK(*tbl.get_as<int64_t>("a") == 69); CHECK(*tbl.get_as<int64_t>("a") == 69);
REQUIRE(tbl == table{{ { "a"sv, 69 }, { "b"sv, "kek" }, { "c"sv, array{ 1, 2, 3 } } }}); REQUIRE(tbl == table{ { { "a"sv, 69 }, { "b"sv, "kek" }, { "c"sv, array{ 1, 2, 3 } } } });
it = tbl.erase(advance(tbl.cbegin(), 1), advance(tbl.cbegin(), 3)); it = tbl.erase(advance(tbl.cbegin(), 1), advance(tbl.cbegin(), 3));
REQUIRE(tbl == table{{ { "a"sv, 69 } }}); REQUIRE(tbl == table{ { { "a"sv, 69 } } });
CHECK(it == tbl.end()); CHECK(it == tbl.end());
CHECK(tbl.size() == 1u); CHECK(tbl.size() == 1u);
@ -328,11 +297,7 @@ TEST_CASE("tables - insertion and erasure")
// void insert(Iter first, Iter last) // void insert(Iter first, Iter last)
{ {
std::vector<std::pair<std::string, std::string>> vals{ std::vector<std::pair<std::string, std::string>> vals{ { "foo", "foo" }, { "bar", "bar" }, { "kek", "kek" } };
{ "foo", "foo" },
{ "bar", "bar" },
{ "kek", "kek" }
};
tbl.insert(vals.begin(), vals.end()); tbl.insert(vals.begin(), vals.end());
CHECK(tbl.size() == 3u); CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<std::string>("foo")); REQUIRE(tbl.get_as<std::string>("foo"));
@ -355,11 +320,7 @@ TEST_CASE("tables - insertion and erasure")
// void insert(Iter first, Iter last) (with move iterators) // void insert(Iter first, Iter last) (with move iterators)
{ {
std::vector<std::pair<std::string, std::string>> vals{ std::vector<std::pair<std::string, std::string>> vals{ { "foo", "foo" }, { "bar", "bar" }, { "kek", "kek" } };
{ "foo", "foo" },
{ "bar", "bar" },
{ "kek", "kek" }
};
tbl.insert(std::make_move_iterator(vals.begin()), std::make_move_iterator(vals.end())); tbl.insert(std::make_move_iterator(vals.begin()), std::make_move_iterator(vals.end()));
CHECK(tbl.size() == 3u); CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<std::string>("foo")); REQUIRE(tbl.get_as<std::string>("foo"));
@ -380,8 +341,7 @@ TEST_CASE("tables - insertion and erasure")
tbl.clear(); tbl.clear();
} }
#if TOML_WINDOWS_COMPAT
#if TOML_WINDOWS_COMPAT
tbl.insert(L"a", L"test1"); tbl.insert(L"a", L"test1");
REQUIRE(*tbl.get_as<std::string>(L"a"sv) == "test1"sv); REQUIRE(*tbl.get_as<std::string>(L"a"sv) == "test1"sv);
@ -395,7 +355,7 @@ TEST_CASE("tables - insertion and erasure")
tbl.erase(L"a"s); tbl.erase(L"a"s);
CHECK(tbl.size() == 0u); CHECK(tbl.size() == 0u);
#endif // TOML_WINDOWS_COMPAT #endif // TOML_WINDOWS_COMPAT
} }
TEST_CASE("tables - printing") TEST_CASE("tables - printing")
@ -458,4 +418,3 @@ c = 3)"sv;
CHECK(to_string(some_toml) == some_toml); CHECK(to_string(some_toml) == some_toml);
} }
} }

View File

@ -18,73 +18,74 @@ static constexpr T one = static_cast<T>(1);
TEST_CASE("values - construction") TEST_CASE("values - construction")
{ {
#define CHECK_VALUE_INIT2(initializer, target_type, equiv) \ #define CHECK_VALUE_INIT2(initializer, target_type, equiv) \
do { \ do \
auto v = value{ initializer }; \ { \
static_assert(std::is_same_v<decltype(v), value<target_type>>); \ auto v = value{ initializer }; \
CHECK(v == equiv); \ static_assert(std::is_same_v<decltype(v), value<target_type>>); \
CHECK(equiv == v); \ CHECK(v == equiv); \
CHECK(*v == equiv); \ CHECK(equiv == v); \
CHECK(v.get() == equiv); \ CHECK(*v == equiv); \
CHECK(v.is_homogeneous()); \ CHECK(v.get() == equiv); \
CHECK(v.is_homogeneous<target_type>()); \ CHECK(v.is_homogeneous()); \
CHECK(v.is_homogeneous(impl::node_type_of<target_type>)); \ CHECK(v.is_homogeneous<target_type>()); \
} while (false) CHECK(v.is_homogeneous(impl::node_type_of<target_type>)); \
} \
while (false)
#define CHECK_VALUE_INIT(initializer, target_type) \ #define CHECK_VALUE_INIT(initializer, target_type) CHECK_VALUE_INIT2(initializer, target_type, initializer)
CHECK_VALUE_INIT2(initializer, target_type, initializer)
CHECK_VALUE_INIT(one<signed char>, int64_t); CHECK_VALUE_INIT(one<signed char>, int64_t);
CHECK_VALUE_INIT(one<signed short>, int64_t); CHECK_VALUE_INIT(one<signed short>, int64_t);
CHECK_VALUE_INIT(one<signed int>, int64_t); CHECK_VALUE_INIT(one<signed int>, int64_t);
CHECK_VALUE_INIT(one<signed long>, int64_t); CHECK_VALUE_INIT(one<signed long>, int64_t);
CHECK_VALUE_INIT(one<signed long long>, int64_t); CHECK_VALUE_INIT(one<signed long long>, int64_t);
CHECK_VALUE_INIT2(one<unsigned char>, int64_t, 1u); CHECK_VALUE_INIT2(one<unsigned char>, int64_t, 1u);
CHECK_VALUE_INIT2(one<unsigned short>, int64_t, 1u); CHECK_VALUE_INIT2(one<unsigned short>, int64_t, 1u);
CHECK_VALUE_INIT2(one<unsigned int>, int64_t, 1u); CHECK_VALUE_INIT2(one<unsigned int>, int64_t, 1u);
CHECK_VALUE_INIT2(one<unsigned long>, int64_t, 1u); CHECK_VALUE_INIT2(one<unsigned long>, int64_t, 1u);
CHECK_VALUE_INIT2(one<unsigned long long>, int64_t, 1u); CHECK_VALUE_INIT2(one<unsigned long long>, int64_t, 1u);
CHECK_VALUE_INIT(true, bool); CHECK_VALUE_INIT(true, bool);
CHECK_VALUE_INIT(false, bool); CHECK_VALUE_INIT(false, bool);
CHECK_VALUE_INIT("kek", std::string); CHECK_VALUE_INIT("kek", std::string);
CHECK_VALUE_INIT("kek"s, std::string); CHECK_VALUE_INIT("kek"s, std::string);
CHECK_VALUE_INIT("kek"sv, std::string); CHECK_VALUE_INIT("kek"sv, std::string);
CHECK_VALUE_INIT2("kek"sv.data(), std::string, "kek"sv); CHECK_VALUE_INIT2("kek"sv.data(), std::string, "kek"sv);
#if TOML_HAS_CHAR8 #if TOML_HAS_CHAR8
CHECK_VALUE_INIT2(u8"kek", std::string, "kek"sv); CHECK_VALUE_INIT2(u8"kek", std::string, "kek"sv);
CHECK_VALUE_INIT2(u8"kek"s, std::string, "kek"sv); CHECK_VALUE_INIT2(u8"kek"s, std::string, "kek"sv);
CHECK_VALUE_INIT2(u8"kek"sv, std::string, "kek"sv); CHECK_VALUE_INIT2(u8"kek"sv, std::string, "kek"sv);
CHECK_VALUE_INIT2(u8"kek"sv.data(), std::string, "kek"sv); CHECK_VALUE_INIT2(u8"kek"sv.data(), std::string, "kek"sv);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
CHECK_VALUE_INIT(one<BOOL>, int64_t); CHECK_VALUE_INIT(one<BOOL>, int64_t);
CHECK_VALUE_INIT(one<SHORT>, int64_t); CHECK_VALUE_INIT(one<SHORT>, int64_t);
CHECK_VALUE_INIT(one<INT>, int64_t); CHECK_VALUE_INIT(one<INT>, int64_t);
CHECK_VALUE_INIT(one<LONG>, int64_t); CHECK_VALUE_INIT(one<LONG>, int64_t);
CHECK_VALUE_INIT(one<INT_PTR>, int64_t); CHECK_VALUE_INIT(one<INT_PTR>, int64_t);
CHECK_VALUE_INIT(one<LONG_PTR>, int64_t); CHECK_VALUE_INIT(one<LONG_PTR>, int64_t);
CHECK_VALUE_INIT2(one<USHORT>, int64_t, 1u); CHECK_VALUE_INIT2(one<USHORT>, int64_t, 1u);
CHECK_VALUE_INIT2(one<UINT>, int64_t, 1u); CHECK_VALUE_INIT2(one<UINT>, int64_t, 1u);
CHECK_VALUE_INIT2(one<ULONG>, int64_t, 1u); CHECK_VALUE_INIT2(one<ULONG>, int64_t, 1u);
CHECK_VALUE_INIT2(one<UINT_PTR>, int64_t, 1u); CHECK_VALUE_INIT2(one<UINT_PTR>, int64_t, 1u);
CHECK_VALUE_INIT2(one<ULONG_PTR>, int64_t, 1u); CHECK_VALUE_INIT2(one<ULONG_PTR>, int64_t, 1u);
CHECK_VALUE_INIT2(one<WORD>, int64_t, 1u); CHECK_VALUE_INIT2(one<WORD>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD>, int64_t, 1u); CHECK_VALUE_INIT2(one<DWORD>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD32>, int64_t, 1u); CHECK_VALUE_INIT2(one<DWORD32>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD64>, int64_t, 1u); CHECK_VALUE_INIT2(one<DWORD64>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORDLONG>, int64_t, 1u); CHECK_VALUE_INIT2(one<DWORDLONG>, int64_t, 1u);
#if TOML_WINDOWS_COMPAT #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);
#endif // TOML_WINDOWS_COMPAT
#endif 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
#endif
} }
TEST_CASE("values - printing") TEST_CASE("values - printing")
@ -132,10 +133,8 @@ TEST_CASE("values - printing")
TEST_CASE("nodes - value() int/float/bool conversions") TEST_CASE("nodes - value() int/float/bool conversions")
{ {
#define CHECK_VALUE_PASS(type, v) \ #define CHECK_VALUE_PASS(type, v) CHECK(n.value<type>() == static_cast<type>(v))
CHECK(n.value<type>() == static_cast<type>(v)) #define CHECK_VALUE_FAIL(type) CHECK(!n.value<type>())
#define CHECK_VALUE_FAIL(type) \
CHECK(!n.value<type>())
// bools // bools
{ {
@ -328,7 +327,6 @@ TEST_CASE("nodes - value() int/float/bool conversions")
CHECK_VALUE_FAIL(toml::time); CHECK_VALUE_FAIL(toml::time);
CHECK_VALUE_FAIL(toml::date_time); CHECK_VALUE_FAIL(toml::date_time);
*val = 1.0; *val = 1.0;
CHECK_VALUE_FAIL(bool); CHECK_VALUE_FAIL(bool);
CHECK_VALUE_PASS(int8_t, 1); CHECK_VALUE_PASS(int8_t, 1);

View File

@ -7,179 +7,175 @@
TEST_CASE("parsing - arrays") TEST_CASE("parsing - arrays")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( integers = [ 1, 2, 3 ]
integers = [ 1, 2, 3 ] integers2 = [
integers2 = [ 1, 2, 3
1, 2, 3 ]
] integers3 = [
integers3 = [ 1,
1, 2, # this is ok
2, # this is ok ]
] colors = [ "red", "yellow", "green" ]
colors = [ "red", "yellow", "green" ] nested_array_of_int = [ [ 1, 2 ], [3, 4, 5] ]
nested_array_of_int = [ [ 1, 2 ], [3, 4, 5] ] nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ] string_array = [ "all", 'strings', """are the same""", '''type''' ]
string_array = [ "all", 'strings', """are the same""", '''type''' ] )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ REQUIRE(tbl["integers"].as<array>());
REQUIRE(tbl["integers"].as<array>()); CHECK(tbl["integers"].is_homogeneous());
CHECK(tbl["integers"].is_homogeneous()); CHECK(tbl["integers"].is_homogeneous(node_type::integer));
CHECK(tbl["integers"].is_homogeneous(node_type::integer)); CHECK(!tbl["integers"].is_homogeneous(node_type::floating_point));
CHECK(!tbl["integers"].is_homogeneous(node_type::floating_point)); CHECK(tbl["integers"].is_homogeneous<int64_t>());
CHECK(tbl["integers"].is_homogeneous<int64_t>()); CHECK(!tbl["integers"].is_homogeneous<double>());
CHECK(!tbl["integers"].is_homogeneous<double>()); CHECK(tbl["integers"].as<array>()->is_homogeneous());
CHECK(tbl["integers"].as<array>()->is_homogeneous()); CHECK(tbl["integers"].as<array>()->is_homogeneous(node_type::integer));
CHECK(tbl["integers"].as<array>()->is_homogeneous(node_type::integer)); CHECK(!tbl["integers"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(!tbl["integers"].as<array>()->is_homogeneous(node_type::floating_point)); CHECK(tbl["integers"].as<array>()->is_homogeneous<int64_t>());
CHECK(tbl["integers"].as<array>()->is_homogeneous<int64_t>()); CHECK(!tbl["integers"].as<array>()->is_homogeneous<double>());
CHECK(!tbl["integers"].as<array>()->is_homogeneous<double>()); CHECK(tbl["integers"].as<array>()->size() == 3);
CHECK(tbl["integers"].as<array>()->size() == 3); CHECK(tbl["integers"][0] == 1);
CHECK(tbl["integers"][0] == 1); CHECK(tbl["integers"][1] == 2);
CHECK(tbl["integers"][1] == 2); CHECK(tbl["integers"][2] == 3);
CHECK(tbl["integers"][2] == 3);
REQUIRE(tbl["integers2"].as<array>()); REQUIRE(tbl["integers2"].as<array>());
CHECK(tbl["integers2"].is_homogeneous()); CHECK(tbl["integers2"].is_homogeneous());
CHECK(tbl["integers2"].is_homogeneous(node_type::integer)); CHECK(tbl["integers2"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers2"].is_homogeneous(node_type::floating_point)); CHECK(!tbl["integers2"].is_homogeneous(node_type::floating_point));
CHECK(tbl["integers2"].is_homogeneous<int64_t>()); CHECK(tbl["integers2"].is_homogeneous<int64_t>());
CHECK(!tbl["integers2"].is_homogeneous<double>()); CHECK(!tbl["integers2"].is_homogeneous<double>());
CHECK(tbl["integers2"].as<array>()->is_homogeneous()); CHECK(tbl["integers2"].as<array>()->is_homogeneous());
CHECK(tbl["integers2"].as<array>()->is_homogeneous(node_type::integer)); CHECK(tbl["integers2"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers2"].as<array>()->is_homogeneous(node_type::floating_point)); CHECK(!tbl["integers2"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["integers2"].as<array>()->is_homogeneous<int64_t>()); CHECK(tbl["integers2"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers2"].as<array>()->is_homogeneous<double>()); CHECK(!tbl["integers2"].as<array>()->is_homogeneous<double>());
CHECK(tbl["integers2"].as<array>()->size() == 3); CHECK(tbl["integers2"].as<array>()->size() == 3);
CHECK(tbl["integers2"][0] == 1); CHECK(tbl["integers2"][0] == 1);
CHECK(tbl["integers2"][1] == 2); CHECK(tbl["integers2"][1] == 2);
CHECK(tbl["integers2"][2] == 3); CHECK(tbl["integers2"][2] == 3);
REQUIRE(tbl["integers3"].as<array>()); REQUIRE(tbl["integers3"].as<array>());
CHECK(tbl["integers3"].is_homogeneous()); CHECK(tbl["integers3"].is_homogeneous());
CHECK(tbl["integers3"].is_homogeneous(node_type::integer)); CHECK(tbl["integers3"].is_homogeneous(node_type::integer));
CHECK(!tbl["integers3"].is_homogeneous(node_type::floating_point)); CHECK(!tbl["integers3"].is_homogeneous(node_type::floating_point));
CHECK(tbl["integers3"].is_homogeneous<int64_t>()); CHECK(tbl["integers3"].is_homogeneous<int64_t>());
CHECK(!tbl["integers3"].is_homogeneous<double>()); CHECK(!tbl["integers3"].is_homogeneous<double>());
CHECK(tbl["integers3"].as<array>()->is_homogeneous()); CHECK(tbl["integers3"].as<array>()->is_homogeneous());
CHECK(tbl["integers3"].as<array>()->is_homogeneous(node_type::integer)); CHECK(tbl["integers3"].as<array>()->is_homogeneous(node_type::integer));
CHECK(!tbl["integers3"].as<array>()->is_homogeneous(node_type::floating_point)); CHECK(!tbl["integers3"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["integers3"].as<array>()->is_homogeneous<int64_t>()); CHECK(tbl["integers3"].as<array>()->is_homogeneous<int64_t>());
CHECK(!tbl["integers3"].as<array>()->is_homogeneous<double>()); CHECK(!tbl["integers3"].as<array>()->is_homogeneous<double>());
CHECK(tbl["integers3"].as<array>()->size() == 2); CHECK(tbl["integers3"].as<array>()->size() == 2);
CHECK(tbl["integers3"][0] == 1); CHECK(tbl["integers3"][0] == 1);
CHECK(tbl["integers3"][1] == 2); CHECK(tbl["integers3"][1] == 2);
REQUIRE(tbl["colors"].as<array>()); REQUIRE(tbl["colors"].as<array>());
CHECK(tbl["colors"].is_homogeneous()); CHECK(tbl["colors"].is_homogeneous());
CHECK(tbl["colors"].is_homogeneous(node_type::string)); CHECK(tbl["colors"].is_homogeneous(node_type::string));
CHECK(!tbl["colors"].is_homogeneous(node_type::floating_point)); CHECK(!tbl["colors"].is_homogeneous(node_type::floating_point));
CHECK(tbl["colors"].is_homogeneous<std::string>()); CHECK(tbl["colors"].is_homogeneous<std::string>());
CHECK(!tbl["colors"].is_homogeneous<double>()); CHECK(!tbl["colors"].is_homogeneous<double>());
CHECK(tbl["colors"].as<array>()->is_homogeneous()); CHECK(tbl["colors"].as<array>()->is_homogeneous());
CHECK(tbl["colors"].as<array>()->is_homogeneous(node_type::string)); CHECK(tbl["colors"].as<array>()->is_homogeneous(node_type::string));
CHECK(!tbl["colors"].as<array>()->is_homogeneous(node_type::floating_point)); CHECK(!tbl["colors"].as<array>()->is_homogeneous(node_type::floating_point));
CHECK(tbl["colors"].as<array>()->is_homogeneous<std::string>()); CHECK(tbl["colors"].as<array>()->is_homogeneous<std::string>());
CHECK(!tbl["colors"].as<array>()->is_homogeneous<double>()); CHECK(!tbl["colors"].as<array>()->is_homogeneous<double>());
CHECK(tbl["colors"].as<array>()->size() == 3); CHECK(tbl["colors"].as<array>()->size() == 3);
CHECK(tbl["colors"][0] == "red"sv); CHECK(tbl["colors"][0] == "red"sv);
CHECK(tbl["colors"][1] == "yellow"sv); CHECK(tbl["colors"][1] == "yellow"sv);
CHECK(tbl["colors"][2] == "green"sv); CHECK(tbl["colors"][2] == "green"sv);
REQUIRE(tbl["nested_array_of_int"].as<array>()); REQUIRE(tbl["nested_array_of_int"].as<array>());
CHECK(tbl["nested_array_of_int"].as<array>()->is_homogeneous()); CHECK(tbl["nested_array_of_int"].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"].as<array>()->size() == 2); CHECK(tbl["nested_array_of_int"].as<array>()->size() == 2);
REQUIRE(tbl["nested_array_of_int"][0].as<array>()); REQUIRE(tbl["nested_array_of_int"][0].as<array>());
CHECK(tbl["nested_array_of_int"][0].as<array>()->is_homogeneous()); CHECK(tbl["nested_array_of_int"][0].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"][0].as<array>()->size() == 2); CHECK(tbl["nested_array_of_int"][0].as<array>()->size() == 2);
CHECK(tbl["nested_array_of_int"][0][0] == 1); CHECK(tbl["nested_array_of_int"][0][0] == 1);
CHECK(tbl["nested_array_of_int"][0][1] == 2); CHECK(tbl["nested_array_of_int"][0][1] == 2);
REQUIRE(tbl["nested_array_of_int"][1].as<array>()); REQUIRE(tbl["nested_array_of_int"][1].as<array>());
CHECK(tbl["nested_array_of_int"][1].as<array>()->is_homogeneous()); CHECK(tbl["nested_array_of_int"][1].as<array>()->is_homogeneous());
CHECK(tbl["nested_array_of_int"][1].as<array>()->size() == 3); CHECK(tbl["nested_array_of_int"][1].as<array>()->size() == 3);
CHECK(tbl["nested_array_of_int"][1][0] == 3); CHECK(tbl["nested_array_of_int"][1][0] == 3);
CHECK(tbl["nested_array_of_int"][1][1] == 4); CHECK(tbl["nested_array_of_int"][1][1] == 4);
CHECK(tbl["nested_array_of_int"][1][2] == 5); CHECK(tbl["nested_array_of_int"][1][2] == 5);
REQUIRE(tbl["nested_mixed_array"].as<array>()); REQUIRE(tbl["nested_mixed_array"].as<array>());
CHECK(tbl["nested_mixed_array"].as<array>()->is_homogeneous()); CHECK(tbl["nested_mixed_array"].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"].as<array>()->size() == 2); CHECK(tbl["nested_mixed_array"].as<array>()->size() == 2);
REQUIRE(tbl["nested_mixed_array"][0].as<array>()); REQUIRE(tbl["nested_mixed_array"][0].as<array>());
CHECK(tbl["nested_mixed_array"][0].as<array>()->is_homogeneous()); CHECK(tbl["nested_mixed_array"][0].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"][0].as<array>()->size() == 2); CHECK(tbl["nested_mixed_array"][0].as<array>()->size() == 2);
CHECK(tbl["nested_mixed_array"][0][0] == 1); CHECK(tbl["nested_mixed_array"][0][0] == 1);
CHECK(tbl["nested_mixed_array"][0][1] == 2); CHECK(tbl["nested_mixed_array"][0][1] == 2);
REQUIRE(tbl["nested_mixed_array"][1].as<array>()); REQUIRE(tbl["nested_mixed_array"][1].as<array>());
CHECK(tbl["nested_mixed_array"][1].as<array>()->is_homogeneous()); CHECK(tbl["nested_mixed_array"][1].as<array>()->is_homogeneous());
CHECK(tbl["nested_mixed_array"][1].as<array>()->size() == 3); CHECK(tbl["nested_mixed_array"][1].as<array>()->size() == 3);
CHECK(tbl["nested_mixed_array"][1][0] == "a"sv); CHECK(tbl["nested_mixed_array"][1][0] == "a"sv);
CHECK(tbl["nested_mixed_array"][1][1] == "b"sv); CHECK(tbl["nested_mixed_array"][1][1] == "b"sv);
CHECK(tbl["nested_mixed_array"][1][2] == "c"sv); CHECK(tbl["nested_mixed_array"][1][2] == "c"sv);
REQUIRE(tbl["string_array"].as<array>()); REQUIRE(tbl["string_array"].as<array>());
CHECK(tbl["string_array"].as<array>()->is_homogeneous()); CHECK(tbl["string_array"].as<array>()->is_homogeneous());
CHECK(tbl["string_array"].as<array>()->size() == 4); CHECK(tbl["string_array"].as<array>()->size() == 4);
CHECK(tbl["string_array"][0] == "all"sv); CHECK(tbl["string_array"][0] == "all"sv);
CHECK(tbl["string_array"][1] == "strings"sv); CHECK(tbl["string_array"][1] == "strings"sv);
CHECK(tbl["string_array"][2] == "are the same"sv); CHECK(tbl["string_array"][2] == "are the same"sv);
CHECK(tbl["string_array"][3] == "type"sv); CHECK(tbl["string_array"][3] == "type"sv);
REQUIRE(tbl["integers"].as<array>()); REQUIRE(tbl["integers"].as<array>());
CHECK(tbl["integers"].as<array>()->is_homogeneous()); CHECK(tbl["integers"].as<array>()->is_homogeneous());
CHECK(tbl["integers"].as<array>()->size() == 3); CHECK(tbl["integers"].as<array>()->size() == 3);
CHECK(tbl["integers"][0] == 1); CHECK(tbl["integers"][0] == 1);
CHECK(tbl["integers"][1] == 2); CHECK(tbl["integers"][1] == 2);
CHECK(tbl["integers"][2] == 3); CHECK(tbl["integers"][2] == 3);
} });
);
// toml/issues/665 (heterogeneous arrays) // toml/issues/665 (heterogeneous arrays)
#if TOML_LANG_AT_LEAST(1, 0, 0) #if TOML_LANG_AT_LEAST(1, 0, 0)
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( # Mixed-type arrays are allowed
# Mixed-type arrays are allowed numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ] contributors = [
contributors = [ "Foo Bar <foo@example.com>",
"Foo Bar <foo@example.com>", { name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
{ name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" } ]
] )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ REQUIRE(tbl["numbers"].as<array>());
REQUIRE(tbl["numbers"].as<array>()); CHECK(!tbl["numbers"].as<array>()->is_homogeneous());
CHECK(!tbl["numbers"].as<array>()->is_homogeneous()); CHECK(tbl["numbers"].as<array>()->size() == 6);
CHECK(tbl["numbers"].as<array>()->size() == 6); CHECK(tbl["numbers"][0].as<double>());
CHECK(tbl["numbers"][0].as<double>()); CHECK(tbl["numbers"][1].as<double>());
CHECK(tbl["numbers"][1].as<double>()); CHECK(tbl["numbers"][2].as<double>());
CHECK(tbl["numbers"][2].as<double>()); CHECK(tbl["numbers"][3].as<int64_t>());
CHECK(tbl["numbers"][3].as<int64_t>()); CHECK(tbl["numbers"][4].as<int64_t>());
CHECK(tbl["numbers"][4].as<int64_t>()); CHECK(tbl["numbers"][5].as<int64_t>());
CHECK(tbl["numbers"][5].as<int64_t>()); CHECK(tbl["numbers"][0] == 0.1);
CHECK(tbl["numbers"][0] == 0.1); CHECK(tbl["numbers"][1] == 0.2);
CHECK(tbl["numbers"][1] == 0.2); CHECK(tbl["numbers"][2] == 0.5);
CHECK(tbl["numbers"][2] == 0.5); CHECK(tbl["numbers"][3] == 1);
CHECK(tbl["numbers"][3] == 1); CHECK(tbl["numbers"][4] == 2);
CHECK(tbl["numbers"][4] == 2); CHECK(tbl["numbers"][5] == 5);
CHECK(tbl["numbers"][5] == 5);
REQUIRE(tbl["contributors"].as<array>()); REQUIRE(tbl["contributors"].as<array>());
CHECK(!tbl["contributors"].as<array>()->is_homogeneous()); CHECK(!tbl["contributors"].as<array>()->is_homogeneous());
CHECK(tbl["contributors"].as<array>()->size() == 2); CHECK(tbl["contributors"].as<array>()->size() == 2);
CHECK(tbl["contributors"][0].as<std::string>()); CHECK(tbl["contributors"][0].as<std::string>());
CHECK(tbl["contributors"][1].as<table>()); CHECK(tbl["contributors"][1].as<table>());
CHECK(tbl["contributors"][0] == "Foo Bar <foo@example.com>"sv); CHECK(tbl["contributors"][0] == "Foo Bar <foo@example.com>"sv);
CHECK(tbl["contributors"][1]["name"] == "Baz Qux"sv); CHECK(tbl["contributors"][1]["name"] == "Baz Qux"sv);
CHECK(tbl["contributors"][1]["email"] == "bazqux@example.com"sv); CHECK(tbl["contributors"][1]["email"] == "bazqux@example.com"sv);
CHECK(tbl["contributors"][1]["url"] == "https://example.com/bazqux"sv); CHECK(tbl["contributors"][1]["url"] == "https://example.com/bazqux"sv);
} });
);
#else #else
parsing_should_fail(FILE_LINE_ARGS, "numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]"sv); parsing_should_fail(FILE_LINE_ARGS, "numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]"sv);
#endif #endif
} }

View File

@ -7,18 +7,16 @@
TEST_CASE("parsing - booleans") TEST_CASE("parsing - booleans")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( bool1 = true
bool1 = true bool2 = false
bool2 = false )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl["bool1"] == true);
CHECK(tbl["bool1"] == true); CHECK(tbl["bool2"] == false);
CHECK(tbl["bool2"] == false); });
}
);
// "Always lowercase." // "Always lowercase."
parsing_should_fail(FILE_LINE_ARGS, "bool = True"sv); parsing_should_fail(FILE_LINE_ARGS, "bool = True"sv);
@ -29,6 +27,6 @@ TEST_CASE("parsing - booleans")
parsing_should_fail(FILE_LINE_ARGS, "bool = fALSE"sv); parsing_should_fail(FILE_LINE_ARGS, "bool = fALSE"sv);
// value tests // value tests
parse_expected_value(FILE_LINE_ARGS, " true", true); parse_expected_value(FILE_LINE_ARGS, " true", true);
parse_expected_value(FILE_LINE_ARGS, "false", false); parse_expected_value(FILE_LINE_ARGS, "false", false);
} }

View File

@ -7,30 +7,24 @@
TEST_CASE("parsing - comments") TEST_CASE("parsing - comments")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(# This is a full-line comment # This is a full-line comment
key = "value" # This is a comment at the end of a line key = "value" # This is a comment at the end of a line
another = "# This is not a comment" another = "# This is not a comment"
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl.size() == 2); CHECK(tbl.size() == 2);
CHECK(tbl["key"] == "value"sv); CHECK(tbl["key"] == "value"sv);
CHECK(tbl["another"] == "# This is not a comment"sv); CHECK(tbl["another"] == "# This is not a comment"sv);
} });
);
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(# this = "looks like a KVP but is commented out)"sv,
R"(# this = "looks like a KVP but is commented out)"sv, [](table&& tbl) { CHECK(tbl.size() == 0); });
[](table&& tbl)
{ #if TOML_LANG_AT_LEAST(1, 0, 0)
CHECK(tbl.size() == 0);
}
);
#if TOML_LANG_AT_LEAST(1, 0, 0)
{ {
// toml/issues/567 (disallow non-TAB control characters in comments) // toml/issues/567 (disallow non-TAB control characters in comments)
// 00 - 08 // 00 - 08
@ -43,14 +37,14 @@ TEST_CASE("parsing - comments")
parsing_should_fail(FILE_LINE_ARGS, "# \u0006"sv); parsing_should_fail(FILE_LINE_ARGS, "# \u0006"sv);
parsing_should_fail(FILE_LINE_ARGS, "# \u0007"sv); parsing_should_fail(FILE_LINE_ARGS, "# \u0007"sv);
parsing_should_fail(FILE_LINE_ARGS, "# \u0008"sv); parsing_should_fail(FILE_LINE_ARGS, "# \u0008"sv);
// skip tab and line breaks (real and otherwise) // skip tab and line breaks (real and otherwise)
// \u0009 is \t // \u0009 is \t
// \u000A is \n // \u000A is \n
// \u000B is \v (vertical tab) // \u000B is \v (vertical tab)
// \u000C is \f (form feed) // \u000C is \f (form feed)
// \u000D is \r // \u000D is \r
// 0E - 1F // 0E - 1F
parsing_should_fail(FILE_LINE_ARGS, "# \u000E"sv); parsing_should_fail(FILE_LINE_ARGS, "# \u000E"sv);
parsing_should_fail(FILE_LINE_ARGS, "# \u000F"sv); parsing_should_fail(FILE_LINE_ARGS, "# \u000F"sv);
@ -73,45 +67,44 @@ TEST_CASE("parsing - comments")
// 7F // 7F
parsing_should_fail(FILE_LINE_ARGS, "# \u007F"sv); parsing_should_fail(FILE_LINE_ARGS, "# \u007F"sv);
} }
#else #else
{ {
parsing_should_succeed(FILE_LINE_ARGS, S( parsing_should_succeed(FILE_LINE_ARGS,
"## 00 - 08" S("## 00 - 08"
"# \u0000 " "# \u0000 "
"# \u0001 " "# \u0001 "
"# \u0002 " "# \u0002 "
"# \u0003 " "# \u0003 "
"# \u0004 " "# \u0004 "
"# \u0005 " "# \u0005 "
"# \u0006 " "# \u0006 "
"# \u0007 " "# \u0007 "
"# \u0008 " "# \u0008 "
"## 0A - 1F" "## 0A - 1F"
"# \u000A " "# \u000A "
"# \u000B " "# \u000B "
"# \u000C " "# \u000C "
"# \u000D " "# \u000D "
"# \u000E " "# \u000E "
"# \u000F " "# \u000F "
"# \u0010 " "# \u0010 "
"# \u0011 " "# \u0011 "
"# \u0012 " "# \u0012 "
"# \u0013 " "# \u0013 "
"# \u0014 " "# \u0014 "
"# \u0015 " "# \u0015 "
"# \u0016 " "# \u0016 "
"# \u0017 " "# \u0017 "
"# \u0018 " "# \u0018 "
"# \u0019 " "# \u0019 "
"# \u001A " "# \u001A "
"# \u001B " "# \u001B "
"# \u001C " "# \u001C "
"# \u001D " "# \u001D "
"# \u001E " "# \u001E "
"# \u001F " "# \u001F "
"## 7F " "## 7F "
"# \u007F "sv "# \u007F "sv));
));
} }
#endif #endif
} }

View File

@ -7,36 +7,34 @@
TEST_CASE("parsing - floats") TEST_CASE("parsing - floats")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( # fractional
# fractional flt1 = +1.0
flt1 = +1.0 flt2 = 3.1415
flt2 = 3.1415 flt3 = -0.01
flt3 = -0.01
# exponent # exponent
flt4 = 5e+22 flt4 = 5e+22
flt5 = 1e06 flt5 = 1e06
flt6 = -2E-2 flt6 = -2E-2
# both # both
flt7 = 6.626e-34 flt7 = 6.626e-34
flt8 = 224_617.445_991_228 flt8 = 224_617.445_991_228
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["flt1"] == 1.0); CHECK(tbl["flt1"] == 1.0);
CHECK(tbl["flt2"] == 3.1415); CHECK(tbl["flt2"] == 3.1415);
CHECK(tbl["flt3"] == -0.01); CHECK(tbl["flt3"] == -0.01);
CHECK(tbl["flt4"].as<double>()->get() == 5e+22_a); CHECK(tbl["flt4"].as<double>()->get() == 5e+22_a);
CHECK(tbl["flt5"].as<double>()->get() == 1e6_a); CHECK(tbl["flt5"].as<double>()->get() == 1e6_a);
CHECK(tbl["flt6"] == -2E-2); CHECK(tbl["flt6"] == -2E-2);
CHECK(tbl["flt7"].as<double>()->get() == 6.626e-34_a); CHECK(tbl["flt7"].as<double>()->get() == 6.626e-34_a);
CHECK(tbl["flt8"].as<double>()->get() == 224617.445991228_a); CHECK(tbl["flt8"].as<double>()->get() == 224617.445991228_a);
} });
);
// "Each underscore must be surrounded by at least one digit on each side." // "Each underscore must be surrounded by at least one digit on each side."
parsing_should_fail(FILE_LINE_ARGS, "flt8 = 224_617.445_991_228_"sv); parsing_should_fail(FILE_LINE_ARGS, "flt8 = 224_617.445_991_228_"sv);
@ -44,15 +42,13 @@ TEST_CASE("parsing - floats")
parsing_should_fail(FILE_LINE_ARGS, "flt8 = 224__617.445_991_228"sv); parsing_should_fail(FILE_LINE_ARGS, "flt8 = 224__617.445_991_228"sv);
// "Float values -0.0 and +0.0 are valid and should map according to IEEE 754." // "Float values -0.0 and +0.0 are valid and should map according to IEEE 754."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(zeroes = [-0.0, +0.0])"sv,
R"(zeroes = [-0.0, +0.0])"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl["zeroes"][0] == -0.0);
CHECK(tbl["zeroes"][0] == -0.0); CHECK(tbl["zeroes"][1] == +0.0);
CHECK(tbl["zeroes"][1] == +0.0); });
}
);
// "A float consists of an integer part followed by a fractional part and/or an exponent part" // "A float consists of an integer part followed by a fractional part and/or an exponent part"
// (i.e. omitting the leading digits before the '.' is not legal in TOML) // (i.e. omitting the leading digits before the '.' is not legal in TOML)
@ -84,128 +80,126 @@ TEST_CASE("parsing - floats")
parsing_should_fail(FILE_LINE_ARGS, "flt = -1.e-1"sv); parsing_should_fail(FILE_LINE_ARGS, "flt = -1.e-1"sv);
// value tests // value tests
parse_expected_value( FILE_LINE_ARGS, "1e1"sv, 1e1); parse_expected_value(FILE_LINE_ARGS, "1e1"sv, 1e1);
parse_expected_value( FILE_LINE_ARGS, "1e+1"sv, 1e+1); parse_expected_value(FILE_LINE_ARGS, "1e+1"sv, 1e+1);
parse_expected_value( FILE_LINE_ARGS, "1e-1"sv, 1e-1); parse_expected_value(FILE_LINE_ARGS, "1e-1"sv, 1e-1);
parse_expected_value( FILE_LINE_ARGS, "1.0"sv, 1.0); parse_expected_value(FILE_LINE_ARGS, "1.0"sv, 1.0);
parse_expected_value( FILE_LINE_ARGS, "1.0e1"sv, 1.0e1); parse_expected_value(FILE_LINE_ARGS, "1.0e1"sv, 1.0e1);
parse_expected_value( FILE_LINE_ARGS, "1.0e+1"sv, 1.0e+1); parse_expected_value(FILE_LINE_ARGS, "1.0e+1"sv, 1.0e+1);
parse_expected_value( FILE_LINE_ARGS, "1.0e-1"sv, 1.0e-1); parse_expected_value(FILE_LINE_ARGS, "1.0e-1"sv, 1.0e-1);
parse_expected_value( FILE_LINE_ARGS, "+1e1"sv, +1e1); parse_expected_value(FILE_LINE_ARGS, "+1e1"sv, +1e1);
parse_expected_value( FILE_LINE_ARGS, "+1.0"sv, +1.0); parse_expected_value(FILE_LINE_ARGS, "+1.0"sv, +1.0);
parse_expected_value( FILE_LINE_ARGS, "+1.0e1"sv, +1.0e1); parse_expected_value(FILE_LINE_ARGS, "+1.0e1"sv, +1.0e1);
parse_expected_value( FILE_LINE_ARGS, "+1.0e+1"sv, +1.0e+1); parse_expected_value(FILE_LINE_ARGS, "+1.0e+1"sv, +1.0e+1);
parse_expected_value( FILE_LINE_ARGS, "+1.0e-1"sv, +1.0e-1); parse_expected_value(FILE_LINE_ARGS, "+1.0e-1"sv, +1.0e-1);
parse_expected_value( FILE_LINE_ARGS, "-1.0e+1"sv, -1.0e+1); parse_expected_value(FILE_LINE_ARGS, "-1.0e+1"sv, -1.0e+1);
parse_expected_value( FILE_LINE_ARGS, "-1e1"sv, -1e1); parse_expected_value(FILE_LINE_ARGS, "-1e1"sv, -1e1);
parse_expected_value( FILE_LINE_ARGS, "-1.0"sv, -1.0); parse_expected_value(FILE_LINE_ARGS, "-1.0"sv, -1.0);
parse_expected_value( FILE_LINE_ARGS, "-1.0e1"sv, -1.0e1); parse_expected_value(FILE_LINE_ARGS, "-1.0e1"sv, -1.0e1);
parse_expected_value( FILE_LINE_ARGS, "-1.0e-1"sv, -1.0e-1); parse_expected_value(FILE_LINE_ARGS, "-1.0e-1"sv, -1.0e-1);
parse_expected_value( FILE_LINE_ARGS, "0.1"sv, 0.1); parse_expected_value(FILE_LINE_ARGS, "0.1"sv, 0.1);
parse_expected_value( FILE_LINE_ARGS, "0.001"sv, 0.001); parse_expected_value(FILE_LINE_ARGS, "0.001"sv, 0.001);
parse_expected_value( FILE_LINE_ARGS, "0.100"sv, 0.100); parse_expected_value(FILE_LINE_ARGS, "0.100"sv, 0.100);
parse_expected_value( FILE_LINE_ARGS, "+3.14"sv, +3.14); parse_expected_value(FILE_LINE_ARGS, "+3.14"sv, +3.14);
parse_expected_value( FILE_LINE_ARGS, "-3.14"sv, -3.14); parse_expected_value(FILE_LINE_ARGS, "-3.14"sv, -3.14);
parse_expected_value( FILE_LINE_ARGS, "3.1415_9265_3589"sv, 3.141592653589); parse_expected_value(FILE_LINE_ARGS, "3.1415_9265_3589"sv, 3.141592653589);
parse_expected_value( FILE_LINE_ARGS, "+3.1415_9265_3589"sv, +3.141592653589); parse_expected_value(FILE_LINE_ARGS, "+3.1415_9265_3589"sv, +3.141592653589);
parse_expected_value( FILE_LINE_ARGS, "-3.1415_9265_3589"sv, -3.141592653589); parse_expected_value(FILE_LINE_ARGS, "-3.1415_9265_3589"sv, -3.141592653589);
parse_expected_value( FILE_LINE_ARGS, "123_456.789"sv, 123456.789); parse_expected_value(FILE_LINE_ARGS, "123_456.789"sv, 123456.789);
parse_expected_value( FILE_LINE_ARGS, "+123_456.789"sv, +123456.789); parse_expected_value(FILE_LINE_ARGS, "+123_456.789"sv, +123456.789);
parse_expected_value( FILE_LINE_ARGS, "-123_456.789"sv, -123456.789); parse_expected_value(FILE_LINE_ARGS, "-123_456.789"sv, -123456.789);
parse_expected_value( FILE_LINE_ARGS, "+0.0"sv, +0.0); parse_expected_value(FILE_LINE_ARGS, "+0.0"sv, +0.0);
parse_expected_value( FILE_LINE_ARGS, "-0.0"sv, -0.0); parse_expected_value(FILE_LINE_ARGS, "-0.0"sv, -0.0);
parse_expected_value( FILE_LINE_ARGS, "1e10"sv, 1e10); parse_expected_value(FILE_LINE_ARGS, "1e10"sv, 1e10);
parse_expected_value( FILE_LINE_ARGS, "1e+10"sv, 1e+10); parse_expected_value(FILE_LINE_ARGS, "1e+10"sv, 1e+10);
parse_expected_value( FILE_LINE_ARGS, "1e-10"sv, 1e-10); parse_expected_value(FILE_LINE_ARGS, "1e-10"sv, 1e-10);
parse_expected_value( FILE_LINE_ARGS, "+1e10"sv, +1e10); parse_expected_value(FILE_LINE_ARGS, "+1e10"sv, +1e10);
parse_expected_value( FILE_LINE_ARGS, "+1e+10"sv, +1e+10); parse_expected_value(FILE_LINE_ARGS, "+1e+10"sv, +1e+10);
parse_expected_value( FILE_LINE_ARGS, "+1e-10"sv, +1e-10); parse_expected_value(FILE_LINE_ARGS, "+1e-10"sv, +1e-10);
parse_expected_value( FILE_LINE_ARGS, "-1e10"sv, -1e10); parse_expected_value(FILE_LINE_ARGS, "-1e10"sv, -1e10);
parse_expected_value( FILE_LINE_ARGS, "-1e+10"sv, -1e+10); parse_expected_value(FILE_LINE_ARGS, "-1e+10"sv, -1e+10);
parse_expected_value( FILE_LINE_ARGS, "-1e-10"sv, -1e-10); parse_expected_value(FILE_LINE_ARGS, "-1e-10"sv, -1e-10);
parse_expected_value( FILE_LINE_ARGS, "123e-10"sv, 123e-10); parse_expected_value(FILE_LINE_ARGS, "123e-10"sv, 123e-10);
parse_expected_value( FILE_LINE_ARGS, "1E10"sv, 1E10); parse_expected_value(FILE_LINE_ARGS, "1E10"sv, 1E10);
parse_expected_value( FILE_LINE_ARGS, "1E+10"sv, 1E+10); parse_expected_value(FILE_LINE_ARGS, "1E+10"sv, 1E+10);
parse_expected_value( FILE_LINE_ARGS, "1E-10"sv, 1E-10); parse_expected_value(FILE_LINE_ARGS, "1E-10"sv, 1E-10);
parse_expected_value( FILE_LINE_ARGS, "123E-10"sv, 123E-10); parse_expected_value(FILE_LINE_ARGS, "123E-10"sv, 123E-10);
parse_expected_value( FILE_LINE_ARGS, "1_2_3E-10"sv, 123E-10); parse_expected_value(FILE_LINE_ARGS, "1_2_3E-10"sv, 123E-10);
parse_expected_value( FILE_LINE_ARGS, "1_2_3E-1_0"sv, 123E-10); parse_expected_value(FILE_LINE_ARGS, "1_2_3E-1_0"sv, 123E-10);
parse_expected_value( FILE_LINE_ARGS, "+0e0"sv, +0e0); parse_expected_value(FILE_LINE_ARGS, "+0e0"sv, +0e0);
parse_expected_value( FILE_LINE_ARGS, "-0e0"sv, -0e0); parse_expected_value(FILE_LINE_ARGS, "-0e0"sv, -0e0);
parse_expected_value( FILE_LINE_ARGS, "1_2_3E-01"sv, 123E-01); parse_expected_value(FILE_LINE_ARGS, "1_2_3E-01"sv, 123E-01);
parse_expected_value( FILE_LINE_ARGS, "1_2_3E-0_1"sv, 123E-01); parse_expected_value(FILE_LINE_ARGS, "1_2_3E-0_1"sv, 123E-01);
parse_expected_value( FILE_LINE_ARGS, "6.02e23"sv, 6.02e23); parse_expected_value(FILE_LINE_ARGS, "6.02e23"sv, 6.02e23);
parse_expected_value( FILE_LINE_ARGS, "6.02e+23"sv, 6.02e+23); parse_expected_value(FILE_LINE_ARGS, "6.02e+23"sv, 6.02e+23);
parse_expected_value( FILE_LINE_ARGS, "1.112_650_06e-17"sv, 1.11265006e-17); parse_expected_value(FILE_LINE_ARGS, "1.112_650_06e-17"sv, 1.11265006e-17);
// toml/issues/562 (hexfloats) // toml/issues/562 (hexfloats)
#if TOML_LANG_UNRELEASED #if TOML_LANG_UNRELEASED
parse_expected_value(FILE_LINE_ARGS, " 0x1.2p3"sv, 0x1.2p3); parse_expected_value(FILE_LINE_ARGS, " 0x1.2p3"sv, 0x1.2p3);
parse_expected_value(FILE_LINE_ARGS, " 0x10p1"sv, 0x10p1); parse_expected_value(FILE_LINE_ARGS, " 0x10p1"sv, 0x10p1);
parse_expected_value(FILE_LINE_ARGS, " 0x10p-1"sv, 0x10p-1); parse_expected_value(FILE_LINE_ARGS, " 0x10p-1"sv, 0x10p-1);
parse_expected_value(FILE_LINE_ARGS, " 0x10p+1"sv, 0x10p+1); parse_expected_value(FILE_LINE_ARGS, " 0x10p+1"sv, 0x10p+1);
parse_expected_value(FILE_LINE_ARGS, " -0x10p1"sv, -0x10p1); parse_expected_value(FILE_LINE_ARGS, " -0x10p1"sv, -0x10p1);
parse_expected_value(FILE_LINE_ARGS, " -0x10p-1"sv, -0x10p-1); parse_expected_value(FILE_LINE_ARGS, " -0x10p-1"sv, -0x10p-1);
parse_expected_value(FILE_LINE_ARGS, " +0x10p1"sv, +0x10p1); parse_expected_value(FILE_LINE_ARGS, " +0x10p1"sv, +0x10p1);
parse_expected_value(FILE_LINE_ARGS, " +0x10p+1"sv, +0x10p+1); parse_expected_value(FILE_LINE_ARGS, " +0x10p+1"sv, +0x10p+1);
parse_expected_value(FILE_LINE_ARGS, " -0x10p+1"sv, -0x10p+1); parse_expected_value(FILE_LINE_ARGS, " -0x10p+1"sv, -0x10p+1);
parse_expected_value(FILE_LINE_ARGS, " +0x10p-1"sv, +0x10p-1); parse_expected_value(FILE_LINE_ARGS, " +0x10p-1"sv, +0x10p-1);
parse_expected_value(FILE_LINE_ARGS, " 0x10.1p1"sv, 0x10.1p1); parse_expected_value(FILE_LINE_ARGS, " 0x10.1p1"sv, 0x10.1p1);
parse_expected_value(FILE_LINE_ARGS, " 0x10.1p-1"sv, 0x10.1p-1); parse_expected_value(FILE_LINE_ARGS, " 0x10.1p-1"sv, 0x10.1p-1);
parse_expected_value(FILE_LINE_ARGS, " 0x10.1p+1"sv, 0x10.1p+1); parse_expected_value(FILE_LINE_ARGS, " 0x10.1p+1"sv, 0x10.1p+1);
parse_expected_value(FILE_LINE_ARGS, " -0x10.1p1"sv, -0x10.1p1); parse_expected_value(FILE_LINE_ARGS, " -0x10.1p1"sv, -0x10.1p1);
parse_expected_value(FILE_LINE_ARGS, " -0x10.1p-1"sv, -0x10.1p-1); parse_expected_value(FILE_LINE_ARGS, " -0x10.1p-1"sv, -0x10.1p-1);
parse_expected_value(FILE_LINE_ARGS, " +0x10.1p1"sv, +0x10.1p1); parse_expected_value(FILE_LINE_ARGS, " +0x10.1p1"sv, +0x10.1p1);
parse_expected_value(FILE_LINE_ARGS, " +0x10.1p+1"sv, +0x10.1p+1); parse_expected_value(FILE_LINE_ARGS, " +0x10.1p+1"sv, +0x10.1p+1);
parse_expected_value(FILE_LINE_ARGS, " -0x10.1p+1"sv, -0x10.1p+1); parse_expected_value(FILE_LINE_ARGS, " -0x10.1p+1"sv, -0x10.1p+1);
parse_expected_value(FILE_LINE_ARGS, " +0x10.1p-1"sv, +0x10.1p-1); parse_expected_value(FILE_LINE_ARGS, " +0x10.1p-1"sv, +0x10.1p-1);
#else #else
parsing_should_fail(FILE_LINE_ARGS, " val = 0x10p1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = 0x10p1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = 0x10p-1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = 0x10p-1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = 0x10p+1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = 0x10p+1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = -0x10p1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = -0x10p1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = -0x10p-1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = -0x10p-1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = +0x10p1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = +0x10p1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = +0x10p+1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = +0x10p+1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = -0x10p+1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = -0x10p+1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = +0x10p-1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = +0x10p-1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = 0x10.1p1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = 0x10.1p1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = 0x10.1p-1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = 0x10.1p-1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = 0x10.1p+1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = 0x10.1p+1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = -0x10.1p1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = -0x10.1p1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = -0x10.1p-1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = -0x10.1p-1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = +0x10.1p1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = +0x10.1p1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = +0x10.1p+1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = +0x10.1p+1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = -0x10.1p+1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = -0x10.1p+1"sv);
parsing_should_fail(FILE_LINE_ARGS, " val = +0x10.1p-1"sv); parsing_should_fail(FILE_LINE_ARGS, " val = +0x10.1p-1"sv);
#endif #endif
} }
TEST_CASE("parsing - inf and nan") TEST_CASE("parsing - inf and nan")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( # infinity
# infinity sf1 = inf # positive infinity
sf1 = inf # positive infinity sf2 = +inf # positive infinity
sf2 = +inf # positive infinity sf3 = -inf # negative infinity
sf3 = -inf # negative infinity
# not a number # not a number
sf4 = nan # actual sNaN/qNaN encoding is implementation specific sf4 = nan # actual sNaN/qNaN encoding is implementation specific
sf5 = +nan # same as `nan` sf5 = +nan # same as `nan`
sf6 = -nan # valid, actual encoding is implementation specific sf6 = -nan # valid, actual encoding is implementation specific
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(impl::fpclassify(**tbl["sf1"].as<double>()) == impl::fp_class::pos_inf); CHECK(impl::fpclassify(**tbl["sf1"].as<double>()) == impl::fp_class::pos_inf);
CHECK(impl::fpclassify(**tbl["sf2"].as<double>()) == impl::fp_class::pos_inf); CHECK(impl::fpclassify(**tbl["sf2"].as<double>()) == impl::fp_class::pos_inf);
CHECK(impl::fpclassify(**tbl["sf3"].as<double>()) == impl::fp_class::neg_inf); CHECK(impl::fpclassify(**tbl["sf3"].as<double>()) == impl::fp_class::neg_inf);
CHECK(impl::fpclassify(**tbl["sf4"].as<double>()) == impl::fp_class::nan); CHECK(impl::fpclassify(**tbl["sf4"].as<double>()) == impl::fp_class::nan);
CHECK(impl::fpclassify(**tbl["sf5"].as<double>()) == impl::fp_class::nan); CHECK(impl::fpclassify(**tbl["sf5"].as<double>()) == impl::fp_class::nan);
CHECK(impl::fpclassify(**tbl["sf6"].as<double>()) == impl::fp_class::nan); CHECK(impl::fpclassify(**tbl["sf6"].as<double>()) == impl::fp_class::nan);
} });
);
parsing_should_fail(FILE_LINE_ARGS, " val = NaN "sv); parsing_should_fail(FILE_LINE_ARGS, " val = NaN "sv);
parsing_should_fail(FILE_LINE_ARGS, " val = Nan "sv); parsing_should_fail(FILE_LINE_ARGS, " val = Nan "sv);

View File

@ -7,28 +7,26 @@
TEST_CASE("parsing - integers (decimal)") TEST_CASE("parsing - integers (decimal)")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, BOM_PREFIX R"(
BOM_PREFIX R"( int1 = +99
int1 = +99 int2 = 42
int2 = 42 int3 = 0
int3 = 0 int4 = -17
int4 = -17 int5 = 1_000
int5 = 1_000 int6 = 5_349_221
int6 = 5_349_221 int7 = 1_2_3_4_5 # VALID but discouraged
int7 = 1_2_3_4_5 # VALID but discouraged )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl["int1"] == 99);
CHECK(tbl["int1"] == 99); CHECK(tbl["int2"] == 42);
CHECK(tbl["int2"] == 42); CHECK(tbl["int3"] == 0);
CHECK(tbl["int3"] == 0); CHECK(tbl["int4"] == -17);
CHECK(tbl["int4"] == -17); CHECK(tbl["int5"] == 1000);
CHECK(tbl["int5"] == 1000); CHECK(tbl["int6"] == 5349221);
CHECK(tbl["int6"] == 5349221); CHECK(tbl["int7"] == 12345);
CHECK(tbl["int7"] == 12345); });
}
);
// "Each underscore must be surrounded by at least one digit on each side." // "Each underscore must be surrounded by at least one digit on each side."
parsing_should_fail(FILE_LINE_ARGS, "int5 = 1__000"sv); parsing_should_fail(FILE_LINE_ARGS, "int5 = 1__000"sv);
@ -45,19 +43,17 @@ TEST_CASE("parsing - integers (decimal)")
parsing_should_fail(FILE_LINE_ARGS, "int7 = 01_2_3_4_5"sv); parsing_should_fail(FILE_LINE_ARGS, "int7 = 01_2_3_4_5"sv);
// "Integer values -0 and +0 are valid and identical to an unprefixed zero." // "Integer values -0 and +0 are valid and identical to an unprefixed zero."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, "zeroes = [-0, +0]"sv,
"zeroes = [-0, +0]"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl["zeroes"][0] == 0);
CHECK(tbl["zeroes"][0] == 0); CHECK(tbl["zeroes"][1] == 0);
CHECK(tbl["zeroes"][1] == 0); });
}
);
// "64 bit (signed long) range expected (9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)." // "64 bit (signed long) range expected (9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)."
parse_expected_value(FILE_LINE_ARGS, "9223372036854775807"sv, INT64_MAX); parse_expected_value(FILE_LINE_ARGS, "9223372036854775807"sv, INT64_MAX);
parse_expected_value(FILE_LINE_ARGS, "-9223372036854775808"sv, INT64_MIN); parse_expected_value(FILE_LINE_ARGS, "-9223372036854775808"sv, INT64_MIN);
parsing_should_fail(FILE_LINE_ARGS, "val = 9223372036854775808"sv); // INT64_MAX + 1 parsing_should_fail(FILE_LINE_ARGS, "val = 9223372036854775808"sv); // INT64_MAX + 1
parsing_should_fail(FILE_LINE_ARGS, "val = -9223372036854775809"sv); // INT64_MIN - 1 parsing_should_fail(FILE_LINE_ARGS, "val = -9223372036854775809"sv); // INT64_MIN - 1
@ -72,46 +68,44 @@ TEST_CASE("parsing - integers (decimal)")
parsing_should_fail(FILE_LINE_ARGS, "val = +1-"sv); parsing_should_fail(FILE_LINE_ARGS, "val = +1-"sv);
// value tests // value tests
parse_expected_value(FILE_LINE_ARGS, "0"sv, 0); parse_expected_value(FILE_LINE_ARGS, "0"sv, 0);
parse_expected_value(FILE_LINE_ARGS, "1"sv, 1); parse_expected_value(FILE_LINE_ARGS, "1"sv, 1);
parse_expected_value(FILE_LINE_ARGS, "+1"sv, 1); parse_expected_value(FILE_LINE_ARGS, "+1"sv, 1);
parse_expected_value(FILE_LINE_ARGS, "-1"sv, -1); parse_expected_value(FILE_LINE_ARGS, "-1"sv, -1);
parse_expected_value(FILE_LINE_ARGS, "1234"sv, 1234); parse_expected_value(FILE_LINE_ARGS, "1234"sv, 1234);
parse_expected_value(FILE_LINE_ARGS, "+1234"sv, 1234); parse_expected_value(FILE_LINE_ARGS, "+1234"sv, 1234);
parse_expected_value(FILE_LINE_ARGS, "-1234"sv, -1234); parse_expected_value(FILE_LINE_ARGS, "-1234"sv, -1234);
parse_expected_value(FILE_LINE_ARGS, "1_2_3_4"sv, 1234); parse_expected_value(FILE_LINE_ARGS, "1_2_3_4"sv, 1234);
parse_expected_value(FILE_LINE_ARGS, "+1_2_3_4"sv, 1234); parse_expected_value(FILE_LINE_ARGS, "+1_2_3_4"sv, 1234);
parse_expected_value(FILE_LINE_ARGS, "-1_2_3_4"sv, -1234); parse_expected_value(FILE_LINE_ARGS, "-1_2_3_4"sv, -1234);
parse_expected_value(FILE_LINE_ARGS, "123_456_789"sv, 123456789); parse_expected_value(FILE_LINE_ARGS, "123_456_789"sv, 123456789);
} }
TEST_CASE("parsing - integers (hex, bin, oct)") TEST_CASE("parsing - integers (hex, bin, oct)")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( # hexadecimal with prefix `0x`
# hexadecimal with prefix `0x` hex1 = 0xDEADBEEF
hex1 = 0xDEADBEEF hex2 = 0xdeadbeef
hex2 = 0xdeadbeef hex3 = 0xdead_beef
hex3 = 0xdead_beef
# octal with prefix `0o` # octal with prefix `0o`
oct1 = 0o01234567 oct1 = 0o01234567
oct2 = 0o755 # useful for Unix file permissions oct2 = 0o755 # useful for Unix file permissions
# binary with prefix `0b` # binary with prefix `0b`
bin1 = 0b11010110 bin1 = 0b11010110
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["hex1"] == 0xDEADBEEF); CHECK(tbl["hex1"] == 0xDEADBEEF);
CHECK(tbl["hex2"] == 0xDEADBEEF); CHECK(tbl["hex2"] == 0xDEADBEEF);
CHECK(tbl["hex3"] == 0xDEADBEEF); CHECK(tbl["hex3"] == 0xDEADBEEF);
CHECK(tbl["oct1"] == 01234567); CHECK(tbl["oct1"] == 01234567);
CHECK(tbl["oct2"] == 0755); CHECK(tbl["oct2"] == 0755);
CHECK(tbl["bin1"] == 0b11010110); CHECK(tbl["bin1"] == 0b11010110);
} });
);
// "leading + is not allowed" // "leading + is not allowed"
parsing_should_fail(FILE_LINE_ARGS, "hex1 = +0xDEADBEEF"sv); parsing_should_fail(FILE_LINE_ARGS, "hex1 = +0xDEADBEEF"sv);
@ -123,26 +117,24 @@ TEST_CASE("parsing - integers (hex, bin, oct)")
parsing_should_fail(FILE_LINE_ARGS, "bin1 = +0b11010110"sv); parsing_should_fail(FILE_LINE_ARGS, "bin1 = +0b11010110"sv);
// "leading zeros are allowed (after the prefix)" // "leading zeros are allowed (after the prefix)"
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( hex1 = 0x000DEADBEEF
hex1 = 0x000DEADBEEF hex2 = 0x00000deadbeef
hex2 = 0x00000deadbeef hex3 = 0x0dead_beef
hex3 = 0x0dead_beef oct1 = 0o0001234567
oct1 = 0o0001234567 oct2 = 0o000755
oct2 = 0o000755 bin1 = 0b0000011010110
bin1 = 0b0000011010110 )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl["hex1"] == 0xDEADBEEF);
CHECK(tbl["hex1"] == 0xDEADBEEF); CHECK(tbl["hex2"] == 0xDEADBEEF);
CHECK(tbl["hex2"] == 0xDEADBEEF); CHECK(tbl["hex3"] == 0xDEADBEEF);
CHECK(tbl["hex3"] == 0xDEADBEEF); CHECK(tbl["oct1"] == 01234567);
CHECK(tbl["oct1"] == 01234567); CHECK(tbl["oct2"] == 0755);
CHECK(tbl["oct2"] == 0755); CHECK(tbl["bin1"] == 0b11010110);
CHECK(tbl["bin1"] == 0b11010110); });
}
);
// "***Non-negative*** integer values may also be expressed in hexadecimal, octal, or binary" // "***Non-negative*** integer values may also be expressed in hexadecimal, octal, or binary"
parsing_should_fail(FILE_LINE_ARGS, "val = -0x1"sv); parsing_should_fail(FILE_LINE_ARGS, "val = -0x1"sv);
@ -151,29 +143,30 @@ TEST_CASE("parsing - integers (hex, bin, oct)")
// "64 bit (signed long) range expected (9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)." // "64 bit (signed long) range expected (9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)."
// (ignoring INT64_MIN because toml doesn't allow these forms to represent negative values) // (ignoring INT64_MIN because toml doesn't allow these forms to represent negative values)
parse_expected_value(FILE_LINE_ARGS, "0x7FFFFFFFFFFFFFFF"sv, INT64_MAX); parse_expected_value(FILE_LINE_ARGS, "0x7FFFFFFFFFFFFFFF"sv, INT64_MAX);
parse_expected_value(FILE_LINE_ARGS, "0o777777777777777777777"sv, INT64_MAX); parse_expected_value(FILE_LINE_ARGS, "0o777777777777777777777"sv, INT64_MAX);
parse_expected_value(FILE_LINE_ARGS, "0b111111111111111111111111111111111111111111111111111111111111111"sv, INT64_MAX); parse_expected_value(FILE_LINE_ARGS,
"0b111111111111111111111111111111111111111111111111111111111111111"sv,
INT64_MAX);
parsing_should_fail(FILE_LINE_ARGS, "val = 0x8000000000000000"sv); // INT64_MAX + 1 parsing_should_fail(FILE_LINE_ARGS, "val = 0x8000000000000000"sv); // INT64_MAX + 1
parsing_should_fail(FILE_LINE_ARGS, "val = 0o1000000000000000000000"sv); parsing_should_fail(FILE_LINE_ARGS, "val = 0o1000000000000000000000"sv);
parsing_should_fail(FILE_LINE_ARGS, "val = 0b1000000000000000000000000000000000000000000000000000000000000000"sv); parsing_should_fail(FILE_LINE_ARGS, "val = 0b1000000000000000000000000000000000000000000000000000000000000000"sv);
// value tests // value tests
parse_expected_value(FILE_LINE_ARGS, "0xDEADBEEF"sv, 0xDEADBEEF); parse_expected_value(FILE_LINE_ARGS, "0xDEADBEEF"sv, 0xDEADBEEF);
parse_expected_value(FILE_LINE_ARGS, "0xdeadbeef"sv, 0xDEADBEEF); parse_expected_value(FILE_LINE_ARGS, "0xdeadbeef"sv, 0xDEADBEEF);
parse_expected_value(FILE_LINE_ARGS, "0xDEADbeef"sv, 0xDEADBEEF); parse_expected_value(FILE_LINE_ARGS, "0xDEADbeef"sv, 0xDEADBEEF);
parse_expected_value(FILE_LINE_ARGS, "0xDEAD_BEEF"sv, 0xDEADBEEF); parse_expected_value(FILE_LINE_ARGS, "0xDEAD_BEEF"sv, 0xDEADBEEF);
parse_expected_value(FILE_LINE_ARGS, "0xdead_beef"sv, 0xDEADBEEF); parse_expected_value(FILE_LINE_ARGS, "0xdead_beef"sv, 0xDEADBEEF);
parse_expected_value(FILE_LINE_ARGS, "0xdead_BEEF"sv, 0xDEADBEEF); parse_expected_value(FILE_LINE_ARGS, "0xdead_BEEF"sv, 0xDEADBEEF);
parse_expected_value(FILE_LINE_ARGS, "0xFF"sv, 0xFF); parse_expected_value(FILE_LINE_ARGS, "0xFF"sv, 0xFF);
parse_expected_value(FILE_LINE_ARGS, "0x00FF"sv, 0xFF); parse_expected_value(FILE_LINE_ARGS, "0x00FF"sv, 0xFF);
parse_expected_value(FILE_LINE_ARGS, "0x0000FF"sv, 0xFF); parse_expected_value(FILE_LINE_ARGS, "0x0000FF"sv, 0xFF);
parse_expected_value(FILE_LINE_ARGS, "0o777"sv, 0777); parse_expected_value(FILE_LINE_ARGS, "0o777"sv, 0777);
parse_expected_value(FILE_LINE_ARGS, "0o7_7_7"sv, 0777); parse_expected_value(FILE_LINE_ARGS, "0o7_7_7"sv, 0777);
parse_expected_value(FILE_LINE_ARGS, "0o007"sv, 0007); parse_expected_value(FILE_LINE_ARGS, "0o007"sv, 0007);
parse_expected_value(FILE_LINE_ARGS, "0b10000"sv, 0b10000); parse_expected_value(FILE_LINE_ARGS, "0b10000"sv, 0b10000);
parse_expected_value(FILE_LINE_ARGS, "0b010000"sv, 0b10000); parse_expected_value(FILE_LINE_ARGS, "0b010000"sv, 0b10000);
parse_expected_value(FILE_LINE_ARGS, "0b01_00_00"sv, 0b10000); parse_expected_value(FILE_LINE_ARGS, "0b01_00_00"sv, 0b10000);
parse_expected_value(FILE_LINE_ARGS, "0b111111"sv, 0b111111); parse_expected_value(FILE_LINE_ARGS, "0b111111"sv, 0b111111);
} }

View File

@ -7,50 +7,46 @@
TEST_CASE("parsing - key-value pairs") TEST_CASE("parsing - key-value pairs")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( key = "value"
key = "value" bare_key = "value"
bare_key = "value" bare-key = "value"
bare-key = "value" 1234 = "value"
1234 = "value" "" = "blank"
"" = "blank" )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl.size() == 5);
CHECK(tbl.size() == 5); CHECK(tbl["key"] == "value"sv);
CHECK(tbl["key"] == "value"sv); CHECK(tbl["bare_key"] == "value"sv);
CHECK(tbl["bare_key"] == "value"sv); CHECK(tbl["bare-key"] == "value"sv);
CHECK(tbl["bare-key"] == "value"sv); CHECK(tbl["1234"] == "value"sv);
CHECK(tbl["1234"] == "value"sv); CHECK(tbl[""] == "blank"sv);
CHECK(tbl[""] == "blank"sv); });
}
);
parsing_should_fail(FILE_LINE_ARGS, R"(key = # INVALID)"sv); parsing_should_fail(FILE_LINE_ARGS, R"(key = # INVALID)"sv);
#if UNICODE_LITERALS_OK #if UNICODE_LITERALS_OK
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( "127.0.0.1" = "value"
"127.0.0.1" = "value" "character encoding" = "value"
"character encoding" = "value" "ʎǝʞ" = "value"
"ʎǝʞ" = "value" 'key2' = "value"
'key2' = "value" 'quoted "value"' = "value"
'quoted "value"' = "value" '' = 'blank'
'' = 'blank' )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl["127.0.0.1"] == "value"sv);
CHECK(tbl["127.0.0.1"] == "value"sv); CHECK(tbl["character encoding"] == "value"sv);
CHECK(tbl["character encoding"] == "value"sv); CHECK(tbl["ʎǝʞ"] == "value"sv);
CHECK(tbl["ʎǝʞ"] == "value"sv); CHECK(tbl["key2"] == "value"sv);
CHECK(tbl["key2"] == "value"sv); CHECK(tbl["quoted \"value\""] == "value"sv);
CHECK(tbl["quoted \"value\""] == "value"sv); CHECK(tbl[""] == "blank"sv);
CHECK(tbl[""] == "blank"sv); });
} #endif // UNICODE_LITERALS_OK
);
#endif // UNICODE_LITERALS_OK
parsing_should_fail(FILE_LINE_ARGS, R"(= "no key name")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(= "no key name")"sv);
@ -63,39 +59,34 @@ TEST_CASE("parsing - key-value pairs")
TEST_CASE("parsing - key-value pairs (dotted)") TEST_CASE("parsing - key-value pairs (dotted)")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( name = "Orange"
name = "Orange" physical.color = "orange"
physical.color = "orange" physical.shape = "round"
physical.shape = "round" site."google.com" = true
site."google.com" = true 3.14159 = "pi"
3.14159 = "pi" )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl.size() == 4);
CHECK(tbl.size() == 4); CHECK(tbl["name"] == "Orange"sv);
CHECK(tbl["name"] == "Orange"sv); CHECK(tbl["physical"]["color"] == "orange"sv);
CHECK(tbl["physical"]["color"] == "orange"sv); CHECK(tbl["physical"]["shape"] == "round"sv);
CHECK(tbl["physical"]["shape"] == "round"sv); CHECK(tbl["site"]["google.com"] == true);
CHECK(tbl["site"]["google.com"] == true); CHECK(tbl["3"]["14159"] == "pi"sv);
CHECK(tbl["3"]["14159"] == "pi"sv); });
}
);
parsing_should_succeed(FILE_LINE_ARGS,
parsing_should_succeed( R"(
FILE_LINE_ARGS, fruit.apple.smooth = true
R"( fruit.orange = 2
fruit.apple.smooth = true )"sv,
fruit.orange = 2 [](table&& tbl)
)"sv, {
[](table&& tbl) CHECK(tbl["fruit"]["apple"]["smooth"] == true);
{ CHECK(tbl["fruit"]["orange"] == 2);
CHECK(tbl["fruit"]["apple"]["smooth"] == true); });
CHECK(tbl["fruit"]["orange"] == 2);
}
);
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
# THIS IS INVALID # THIS IS INVALID
@ -103,83 +94,77 @@ TEST_CASE("parsing - key-value pairs (dotted)")
fruit.apple.smooth = true fruit.apple.smooth = true
)"sv); )"sv);
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( # VALID BUT DISCOURAGED
# VALID BUT DISCOURAGED
apple.type = "fruit" apple.type = "fruit"
orange.type = "fruit" orange.type = "fruit"
apple.skin = "thin" apple.skin = "thin"
orange.skin = "thick" orange.skin = "thick"
apple.color = "red" apple.color = "red"
orange.color = "orange" orange.color = "orange"
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["apple"]["type"] == "fruit"sv); CHECK(tbl["apple"]["type"] == "fruit"sv);
CHECK(tbl["apple"]["skin"] == "thin"sv); CHECK(tbl["apple"]["skin"] == "thin"sv);
CHECK(tbl["apple"]["color"] == "red"sv); CHECK(tbl["apple"]["color"] == "red"sv);
CHECK(tbl["orange"]["type"] == "fruit"sv); CHECK(tbl["orange"]["type"] == "fruit"sv);
CHECK(tbl["orange"]["skin"] == "thick"sv); CHECK(tbl["orange"]["skin"] == "thick"sv);
CHECK(tbl["orange"]["color"] == "orange"sv); CHECK(tbl["orange"]["color"] == "orange"sv);
} });
);
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( # RECOMMENDED
# RECOMMENDED
apple.type = "fruit" apple.type = "fruit"
apple.skin = "thin" apple.skin = "thin"
apple.color = "red" apple.color = "red"
orange.type = "fruit" orange.type = "fruit"
orange.skin = "thick" orange.skin = "thick"
orange.color = "orange" orange.color = "orange"
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["apple"]["type"] == "fruit"sv); CHECK(tbl["apple"]["type"] == "fruit"sv);
CHECK(tbl["apple"]["skin"] == "thin"sv); CHECK(tbl["apple"]["skin"] == "thin"sv);
CHECK(tbl["apple"]["color"] == "red"sv); CHECK(tbl["apple"]["color"] == "red"sv);
CHECK(tbl["orange"]["type"] == "fruit"sv); CHECK(tbl["orange"]["type"] == "fruit"sv);
CHECK(tbl["orange"]["skin"] == "thick"sv); CHECK(tbl["orange"]["skin"] == "thick"sv);
CHECK(tbl["orange"]["color"] == "orange"sv); CHECK(tbl["orange"]["color"] == "orange"sv);
} });
);
// toml/issues/644 ('+' in bare keys) & toml/issues/687 (unicode bare keys) // toml/issues/644 ('+' in bare keys) & toml/issues/687 (unicode bare keys)
#if UNICODE_LITERALS_OK #if UNICODE_LITERALS_OK
#if TOML_LANG_UNRELEASED #if TOML_LANG_UNRELEASED
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( key+1 = 0
key+1 = 0 ʎǝʞ2 = 0
ʎǝʞ2 = 0 )"sv,
)"sv, [](table&& tbl)
[](table&& tbl) {
{ CHECK(tbl.size() == 2);
CHECK(tbl.size() == 2); CHECK(tbl["key+1"] == 0);
CHECK(tbl["key+1"] == 0); CHECK(tbl["ʎǝʞ2"] == 0);
CHECK(tbl["ʎǝʞ2"] == 0); });
} #else
); parsing_should_fail(FILE_LINE_ARGS, R"(key+1 = 0)"sv);
#else parsing_should_fail(FILE_LINE_ARGS, R"(ʎǝʞ2 = 0)"sv);
parsing_should_fail(FILE_LINE_ARGS, R"(key+1 = 0)"sv); #endif
parsing_should_fail(FILE_LINE_ARGS, R"(ʎǝʞ2 = 0)"sv); #endif // UNICODE_LITERALS_OK
#endif
#endif // UNICODE_LITERALS_OK
} }
TEST_CASE("parsing - key-value pairs (string keys)") TEST_CASE("parsing - key-value pairs (string keys)")
{ {
// these are all derived from the discussion at // these are all derived from the discussion at
// https://github.com/toml-lang/toml/issues/733. // https://github.com/toml-lang/toml/issues/733.
// whitespace stripped, fail duplicate keys // whitespace stripped, fail duplicate keys
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
a = 2 a = 2
@ -244,14 +229,16 @@ TEST_CASE("parsing - key-value pairs (string keys)")
parsing_should_fail(FILE_LINE_ARGS, R"(a."""b""" = 3)"sv); parsing_should_fail(FILE_LINE_ARGS, R"(a."""b""" = 3)"sv);
// whitespace relevant (success test, values are NOTE equal) // whitespace relevant (success test, values are NOTE equal)
parsing_should_succeed(FILE_LINE_ARGS, R"( parsing_should_succeed(FILE_LINE_ARGS,
a = " to do " R"(
b = "to do" a = " to do "
)"sv, [](table&& tbl) b = "to do"
{ )"sv,
CHECK(tbl["a"] == " to do "sv); [](table&& tbl)
CHECK(tbl["b"] == "to do"sv); {
}); CHECK(tbl["a"] == " to do "sv);
CHECK(tbl["b"] == "to do"sv);
});
// values must be quoted, syntax error // values must be quoted, syntax error
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
@ -284,14 +271,16 @@ TEST_CASE("parsing - key-value pairs (string keys)")
)"sv); )"sv);
// inner quotes are not stripped from value, a & b are equal, value surrounded by quotes // inner quotes are not stripped from value, a & b are equal, value surrounded by quotes
parsing_should_succeed(FILE_LINE_ARGS, R"( parsing_should_succeed(FILE_LINE_ARGS,
a = "\"quoted\"" R"(
b = """"quoted"""" a = "\"quoted\""
)"sv, [](table&& tbl) b = """"quoted""""
{ )"sv,
CHECK(tbl["a"] == "\"quoted\""sv); [](table&& tbl)
CHECK(tbl["b"] == "\"quoted\""sv); {
}); CHECK(tbl["a"] == "\"quoted\""sv);
CHECK(tbl["b"] == "\"quoted\""sv);
});
// quote correction is not applied, fail syntax error // quote correction is not applied, fail syntax error
parsing_should_fail(FILE_LINE_ARGS, R"("a = "test")"sv); parsing_should_fail(FILE_LINE_ARGS, R"("a = "test")"sv);

View File

@ -7,9 +7,8 @@
TEST_CASE("parsing - strings") TEST_CASE("parsing - strings")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
str1 = """ str1 = """
@ -21,17 +20,16 @@ str2 = """
Roses are red Roses are red
Violets are blue""" Violets are blue"""
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["str"] == "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."sv); CHECK(tbl["str"]
CHECK(tbl["str1"] == "Roses are red\nViolets are blue"sv); == "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."sv);
CHECK(tbl["str2"] == "\nRoses are red\nViolets are blue"sv); CHECK(tbl["str1"] == "Roses are red\nViolets are blue"sv);
} CHECK(tbl["str2"] == "\nRoses are red\nViolets are blue"sv);
); });
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
# The following strings are byte-for-byte equivalent: # The following strings are byte-for-byte equivalent:
str1 = "The quick brown fox jumps over the lazy dog." str1 = "The quick brown fox jumps over the lazy dog."
@ -56,24 +54,22 @@ str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
# "This," she said, "is just a pointless statement." # "This," she said, "is just a pointless statement."
str7 = """"This," she said, "is just a pointless statement."""" str7 = """"This," she said, "is just a pointless statement.""""
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
static constexpr auto quick_brown_fox = "The quick brown fox jumps over the lazy dog."sv; static constexpr auto quick_brown_fox = "The quick brown fox jumps over the lazy dog."sv;
CHECK(tbl["str1"] == quick_brown_fox); CHECK(tbl["str1"] == quick_brown_fox);
CHECK(tbl["str2"] == quick_brown_fox); CHECK(tbl["str2"] == quick_brown_fox);
CHECK(tbl["str3"] == quick_brown_fox); CHECK(tbl["str3"] == quick_brown_fox);
CHECK(tbl["str4"] == R"(Here are two quotation marks: "". Simple enough.)"sv); CHECK(tbl["str4"] == R"(Here are two quotation marks: "". Simple enough.)"sv);
CHECK(tbl["str5"] == R"(Here are three quotation marks: """.)"sv); CHECK(tbl["str5"] == R"(Here are three quotation marks: """.)"sv);
CHECK(tbl["str6"] == R"(Here are fifteen quotation marks: """"""""""""""".)"sv); CHECK(tbl["str6"] == R"(Here are fifteen quotation marks: """"""""""""""".)"sv);
CHECK(tbl["str7"] == R"("This," she said, "is just a pointless statement.")"sv); CHECK(tbl["str7"] == R"("This," she said, "is just a pointless statement.")"sv);
} });
);
parsing_should_fail(FILE_LINE_ARGS, R"(str5 = """Here are three quotation marks: """.""")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str5 = """Here are three quotation marks: """.""")"sv);
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
# What you see is what you get. # What you see is what you get.
winpath = 'C:\Users\nodejs\templates' winpath = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\' winpath2 = '\\ServerX\admin$\system32\'
@ -94,30 +90,28 @@ trimmed in raw strings.
is preserved. is preserved.
''' '''
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["winpath"] == R"(C:\Users\nodejs\templates)"sv); CHECK(tbl["winpath"] == R"(C:\Users\nodejs\templates)"sv);
CHECK(tbl["winpath2"] == R"(\\ServerX\admin$\system32\)"sv); CHECK(tbl["winpath2"] == R"(\\ServerX\admin$\system32\)"sv);
CHECK(tbl["quoted"] == R"(Tom "Dubs" Preston-Werner)"sv); CHECK(tbl["quoted"] == R"(Tom "Dubs" Preston-Werner)"sv);
CHECK(tbl["regex"] == R"(<\i\c*\s*>)"sv); CHECK(tbl["regex"] == R"(<\i\c*\s*>)"sv);
CHECK(tbl["regex2"] == R"(I [dw]on't need \d{2} apples)"sv); CHECK(tbl["regex2"] == R"(I [dw]on't need \d{2} apples)"sv);
CHECK(tbl["lines"] == R"(The first newline is CHECK(tbl["lines"] == R"(The first newline is
trimmed in raw strings. trimmed in raw strings.
All other whitespace All other whitespace
is preserved. is preserved.
)"sv); )"sv);
CHECK(tbl["lines2"] == R"( CHECK(tbl["lines2"] == R"(
The first newline is The first newline is
trimmed in raw strings. trimmed in raw strings.
All other whitespace All other whitespace
is preserved. is preserved.
)"sv); )"sv);
} });
);
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
quot15 = '''Here are fifteen quotation marks: """""""""""""""''' quot15 = '''Here are fifteen quotation marks: """""""""""""""'''
# apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID # apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID
@ -126,77 +120,63 @@ apos15 = "Here are fifteen apostrophes: '''''''''''''''"
# 'That's still pointless', she said. # 'That's still pointless', she said.
str = ''''That's still pointless', she said.''' str = ''''That's still pointless', she said.'''
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["quot15"] == R"(Here are fifteen quotation marks: """"""""""""""")"sv); CHECK(tbl["quot15"] == R"(Here are fifteen quotation marks: """"""""""""""")"sv);
CHECK(tbl["apos15"] == R"(Here are fifteen apostrophes: ''''''''''''''')"sv); CHECK(tbl["apos15"] == R"(Here are fifteen apostrophes: ''''''''''''''')"sv);
CHECK(tbl["str"] == R"('That's still pointless', she said.)"sv); CHECK(tbl["str"] == R"('That's still pointless', she said.)"sv);
} });
);
parsing_should_fail(FILE_LINE_ARGS, R"(apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID)"sv); parsing_should_fail(FILE_LINE_ARGS, R"(apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID)"sv);
// value tests // value tests
parse_expected_value( parse_expected_value(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"("The quick brown fox jumps over the lazy dog")"sv,
R"("The quick brown fox jumps over the lazy dog")"sv, "The quick brown fox jumps over the lazy dog"sv);
"The quick brown fox jumps over the lazy dog"sv); parse_expected_value(FILE_LINE_ARGS,
parse_expected_value( R"('The quick brown fox jumps over the lazy dog')"sv,
FILE_LINE_ARGS, "The quick brown fox jumps over the lazy dog"sv);
R"('The quick brown fox jumps over the lazy dog')"sv, parse_expected_value(FILE_LINE_ARGS,
"The quick brown fox jumps over the lazy dog"sv); R"("""The quick brown fox jumps over the lazy dog""")"sv,
parse_expected_value( "The quick brown fox jumps over the lazy dog"sv);
FILE_LINE_ARGS, parse_expected_value(FILE_LINE_ARGS,
R"("""The quick brown fox jumps over the lazy dog""")"sv, R"('''The quick brown fox jumps over the lazy dog''')"sv,
"The quick brown fox jumps over the lazy dog"sv); "The quick brown fox jumps over the lazy dog"sv);
parse_expected_value(
FILE_LINE_ARGS,
R"('''The quick brown fox jumps over the lazy dog''')"sv,
"The quick brown fox jumps over the lazy dog"sv);
#if UNICODE_LITERALS_OK #if UNICODE_LITERALS_OK
parse_expected_value( parse_expected_value(FILE_LINE_ARGS, R"("Ýôú' λáƭè è áƒƭèř ƭλïƨ - #")"sv, R"(Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #)"sv);
FILE_LINE_ARGS, parse_expected_value(FILE_LINE_ARGS,
R"("Ýôú' λáƭè è áƒƭèř ƭλïƨ - #")"sv, R"(" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"")"sv,
R"(Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #)"sv); R"( Âñδ ωλèñ "'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áôñϱ ωïƭλ # ")"sv);
parse_expected_value( parse_expected_value(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"("Ýôú δôñ'ƭ ƭλïñƙ ƨôè úƨèř ωôñ'ƭ δô ƭλáƭ?")"sv,
R"(" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"")"sv, R"(Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?)"sv);
R"( Âñδ ωλèñ "'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áôñϱ ωïƭλ # ")"sv); #endif // UNICODE_LITERALS_OK
parse_expected_value(
FILE_LINE_ARGS,
R"("Ýôú δôñ'ƭ ƭλïñƙ ƨôè úƨèř ωôñ'ƭ δô ƭλáƭ?")"sv,
R"(Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?)"sv);
#endif // UNICODE_LITERALS_OK
parse_expected_value( parse_expected_value(FILE_LINE_ARGS, R"("\"\u03B1\u03B2\u03B3\"")"sv, "\"\u03B1\u03B2\u03B3\""sv);
FILE_LINE_ARGS,
R"("\"\u03B1\u03B2\u03B3\"")"sv,
"\"\u03B1\u03B2\u03B3\""sv);
// toml/pull/709 (\xHH unicode scalars) // toml/pull/709 (\xHH unicode scalars)
#if TOML_LANG_UNRELEASED #if TOML_LANG_UNRELEASED
parse_expected_value( parse_expected_value(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"("\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv,
R"("\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv, "\u0000\u0010\u0020\u0030\u0040\u0050\u0060\u0070\u0080\u0090\u0011\u00FF\u00EE"sv);
"\u0000\u0010\u0020\u0030\u0040\u0050\u0060\u0070\u0080\u0090\u0011\u00FF\u00EE"sv); #else
#else parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv);
parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv); #endif
#endif
// check 8-digit \U scalars with insufficient digits // check 8-digit \U scalars with insufficient digits
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U1234567")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\U1234567")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U123456")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\U123456")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U12345")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\U12345")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U1234")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\U1234")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U123")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\U123")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U12")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\U12")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\U1")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\U1")"sv);
// check 4-digit \u scalars with insufficient digits // check 4-digit \u scalars with insufficient digits
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\u123")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\u123")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\u12")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\u12")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\u1")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\u1")"sv);
// check 2-digit \x scalars with insufficient digits // check 2-digit \x scalars with insufficient digits
parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x1")"sv); parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x1")"sv);

View File

@ -10,22 +10,20 @@ TEST_CASE("parsing - tables")
// these are the examples from https://toml.io/en/v1.0.0#table // these are the examples from https://toml.io/en/v1.0.0#table
// "Tables are defined by headers, with square brackets on a line by themselves." // "Tables are defined by headers, with square brackets on a line by themselves."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, "[table]"sv, "[table]"sv,
[](table&& tbl) [](table&& tbl)
{ {
REQUIRE(tbl["table"].as_table()); REQUIRE(tbl["table"].as_table());
CHECK(tbl["table"].as_table()->empty()); CHECK(tbl["table"].as_table()->empty());
CHECK(tbl["table"].as_table()->size() == 0u); CHECK(tbl["table"].as_table()->size() == 0u);
} });
);
parsing_should_fail(FILE_LINE_ARGS, "[]"sv); parsing_should_fail(FILE_LINE_ARGS, "[]"sv);
// "Under that, and until the next header or EOF, are the key/values of that table. // "Under that, and until the next header or EOF, are the key/values of that table.
// Key/value pairs within tables are not guaranteed to be in any specific order." // Key/value pairs within tables are not guaranteed to be in any specific order."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
[table-1] [table-1]
key1 = "some string" key1 = "some string"
key2 = 123 key2 = 123
@ -34,71 +32,65 @@ TEST_CASE("parsing - tables")
key1 = "another string" key1 = "another string"
key2 = 456 key2 = 456
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
REQUIRE(tbl["table-1"].as_table()); REQUIRE(tbl["table-1"].as_table());
CHECK(tbl["table-1"].as_table()->size() == 2u); CHECK(tbl["table-1"].as_table()->size() == 2u);
CHECK(tbl["table-1"]["key1"] == "some string"sv); CHECK(tbl["table-1"]["key1"] == "some string"sv);
CHECK(tbl["table-1"]["key2"] == 123); CHECK(tbl["table-1"]["key2"] == 123);
REQUIRE(tbl["table-2"].as_table()); REQUIRE(tbl["table-2"].as_table());
CHECK(tbl["table-2"].as_table()->size() == 2u); CHECK(tbl["table-2"].as_table()->size() == 2u);
CHECK(tbl["table-2"]["key1"] == "another string"sv); CHECK(tbl["table-2"]["key1"] == "another string"sv);
CHECK(tbl["table-2"]["key2"] == 456); CHECK(tbl["table-2"]["key2"] == 456);
} });
);
// "Naming rules for tables are the same as for keys." (i.e. can be quoted) // "Naming rules for tables are the same as for keys." (i.e. can be quoted)
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
[dog."tater.man"] [dog."tater.man"]
type.name = "pug" type.name = "pug"
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
REQUIRE(tbl["dog"].as_table()); REQUIRE(tbl["dog"].as_table());
CHECK(tbl["dog"].as_table()->size() == 1u); CHECK(tbl["dog"].as_table()->size() == 1u);
REQUIRE(tbl["dog"]["tater.man"].as_table()); REQUIRE(tbl["dog"]["tater.man"].as_table());
CHECK(tbl["dog"]["tater.man"].as_table()->size() == 1u); CHECK(tbl["dog"]["tater.man"].as_table()->size() == 1u);
CHECK(tbl["dog"]["tater.man"]["type"]["name"] == "pug"sv); CHECK(tbl["dog"]["tater.man"]["type"]["name"] == "pug"sv);
} });
);
// "Whitespace around the key is ignored. However, best practice is to not use any extraneous whitespace." // "Whitespace around the key is ignored. However, best practice is to not use any extraneous whitespace."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
[a.b.c] # this is best practice [a.b.c] # this is best practice
[ d.e.f ] # same as [d.e.f] [ d.e.f ] # same as [d.e.f]
[ g . h . i ] # same as [g.h.i] [ g . h . i ] # same as [g.h.i]
[ j . "k" . 'l' ] # same as [j."k".'l'] [ j . "k" . 'l' ] # same as [j."k".'l']
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["a"].as_table()); CHECK(tbl["a"].as_table());
CHECK(tbl["a"]["b"].as_table()); CHECK(tbl["a"]["b"].as_table());
CHECK(tbl["a"]["b"]["c"].as_table()); CHECK(tbl["a"]["b"]["c"].as_table());
CHECK(tbl["d"].as_table()); CHECK(tbl["d"].as_table());
CHECK(tbl["d"]["e"].as_table()); CHECK(tbl["d"]["e"].as_table());
CHECK(tbl["d"]["e"]["f"].as_table()); CHECK(tbl["d"]["e"]["f"].as_table());
CHECK(tbl["g"].as_table()); CHECK(tbl["g"].as_table());
CHECK(tbl["g"]["h"].as_table()); CHECK(tbl["g"]["h"].as_table());
CHECK(tbl["g"]["h"]["i"].as_table()); CHECK(tbl["g"]["h"]["i"].as_table());
CHECK(tbl["j"].as_table()); CHECK(tbl["j"].as_table());
CHECK(tbl["j"]["k"].as_table()); CHECK(tbl["j"]["k"].as_table());
CHECK(tbl["j"]["k"]["l"].as_table()); CHECK(tbl["j"]["k"]["l"].as_table());
} });
);
// "You don't need to specify all the super-tables if you don't want to. TOML knows how to do it for you." // "You don't need to specify all the super-tables if you don't want to. TOML knows how to do it for you."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
# [x] you # [x] you
# [x.y] don't # [x.y] don't
# [x.y.z] need these # [x.y.z] need these
@ -106,14 +98,13 @@ TEST_CASE("parsing - tables")
[x] # defining a super-table afterwards is ok [x] # defining a super-table afterwards is ok
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["x"].as_table()); CHECK(tbl["x"].as_table());
CHECK(tbl["x"]["y"].as_table()); CHECK(tbl["x"]["y"].as_table());
CHECK(tbl["x"]["y"]["z"].as_table()); CHECK(tbl["x"]["y"]["z"].as_table());
CHECK(tbl["x"]["y"]["z"]["w"].as_table()); CHECK(tbl["x"]["y"]["z"]["w"].as_table());
} });
);
// "Like keys, you cannot define a table more than once. Doing so is invalid." // "Like keys, you cannot define a table more than once. Doing so is invalid."
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
@ -136,44 +127,39 @@ TEST_CASE("parsing - tables")
)"sv); )"sv);
// "Defining tables out-of-order is discouraged." // "Defining tables out-of-order is discouraged."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
# VALID BUT DISCOURAGED # VALID BUT DISCOURAGED
[fruit.apple] [fruit.apple]
[animal] [animal]
[fruit.orange] [fruit.orange]
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["fruit"].as_table()); CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table()); CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["animal"].as_table()); CHECK(tbl["animal"].as_table());
CHECK(tbl["fruit"]["orange"].as_table()); CHECK(tbl["fruit"]["orange"].as_table());
} });
); parsing_should_succeed(FILE_LINE_ARGS,
parsing_should_succeed( R"(
FILE_LINE_ARGS,
R"(
# RECOMMENDED # RECOMMENDED
[fruit.apple] [fruit.apple]
[fruit.orange] [fruit.orange]
[animal] [animal]
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["fruit"].as_table()); CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table()); CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["orange"].as_table()); CHECK(tbl["fruit"]["orange"].as_table());
CHECK(tbl["animal"].as_table()); CHECK(tbl["animal"].as_table());
} });
);
// "The top-level table, also called the root table, starts at the beginning of the document // "The top-level table, also called the root table, starts at the beginning of the document
// and ends just before the first table header (or EOF)." // and ends just before the first table header (or EOF)."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
# Top-level table begins. # Top-level table begins.
name = "Fido" name = "Fido"
breed = "pug" breed = "pug"
@ -183,26 +169,24 @@ TEST_CASE("parsing - tables")
name = "Regina Dogman" name = "Regina Dogman"
member_since = 1999-08-04 member_since = 1999-08-04
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["name"].as_string()); CHECK(tbl["name"].as_string());
CHECK(*tbl["name"].as_string() == "Fido"sv); CHECK(*tbl["name"].as_string() == "Fido"sv);
CHECK(tbl["breed"].as_string()); CHECK(tbl["breed"].as_string());
CHECK(*tbl["breed"].as_string() == "pug"sv); CHECK(*tbl["breed"].as_string() == "pug"sv);
CHECK(tbl["owner"].as_table()); CHECK(tbl["owner"].as_table());
CHECK(*tbl["owner"]["name"].as_string() == "Regina Dogman"sv); CHECK(*tbl["owner"]["name"].as_string() == "Regina Dogman"sv);
static constexpr auto member_since = toml::date{ 1999, 8, 4 }; static constexpr auto member_since = toml::date{ 1999, 8, 4 };
CHECK(*tbl["owner"]["member_since"].as_date() == member_since); CHECK(*tbl["owner"]["member_since"].as_date() == member_since);
} });
);
// "Dotted keys create and define a table for each key part before the last one, // "Dotted keys create and define a table for each key part before the last one,
// provided that such tables were not previously created." // provided that such tables were not previously created."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
fruit.apple.color = "red" fruit.apple.color = "red"
# Defines a table named fruit # Defines a table named fruit
# Defines a table named fruit.apple # Defines a table named fruit.apple
@ -211,18 +195,17 @@ TEST_CASE("parsing - tables")
# Defines a table named fruit.apple.taste # Defines a table named fruit.apple.taste
# fruit and fruit.apple were already created # fruit and fruit.apple were already created
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["fruit"].as_table()); CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table()); CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string()); CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv); CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
CHECK(tbl["fruit"]["apple"]["taste"].as_table()); CHECK(tbl["fruit"]["apple"]["taste"].as_table());
CHECK(tbl["fruit"]["apple"]["taste"]["sweet"].as_boolean()); CHECK(tbl["fruit"]["apple"]["taste"]["sweet"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["taste"]["sweet"].as_boolean() == true); CHECK(*tbl["fruit"]["apple"]["taste"]["sweet"].as_boolean() == true);
} });
);
// "Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed." // "Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed."
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
@ -257,9 +240,8 @@ TEST_CASE("parsing - tables")
)"sv); )"sv);
// "The [table] form can, however, be used to define sub-tables within tables defined via dotted keys." // "The [table] form can, however, be used to define sub-tables within tables defined via dotted keys."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
[fruit] [fruit]
apple.color = "red" apple.color = "red"
apple.taste.sweet = true apple.taste.sweet = true
@ -267,18 +249,17 @@ TEST_CASE("parsing - tables")
[fruit.apple.texture] # you can add sub-tables [fruit.apple.texture] # you can add sub-tables
smooth = true smooth = true
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["fruit"].as_table()); CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table()); CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string()); CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv); CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
CHECK(tbl["fruit"]["apple"]["texture"].as_table()); CHECK(tbl["fruit"]["apple"]["texture"].as_table());
CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean()); CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true); CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true);
} });
);
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
[fruit] [fruit]
apple.color = "red" apple.color = "red"
@ -293,9 +274,8 @@ TEST_CASE("parsing - tables")
// same as above but the table order is reversed. // same as above but the table order is reversed.
// see: https://github.com/toml-lang/toml/issues/769 // see: https://github.com/toml-lang/toml/issues/769
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
[fruit.apple.texture] [fruit.apple.texture]
smooth = true smooth = true
@ -303,53 +283,50 @@ TEST_CASE("parsing - tables")
apple.color = "red" apple.color = "red"
apple.taste.sweet = true apple.taste.sweet = true
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
CHECK(tbl["fruit"].as_table()); CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table()); CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string()); CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv); CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
CHECK(tbl["fruit"]["apple"]["texture"].as_table()); CHECK(tbl["fruit"]["apple"]["texture"].as_table());
CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean()); CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true); CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true);
} });
);
} }
TEST_CASE("parsing - inline tables") TEST_CASE("parsing - inline tables")
{ {
// these are the examples from https://toml.io/en/v1.0.0#inline-table // these are the examples from https://toml.io/en/v1.0.0#inline-table
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
name = { first = "Tom", last = "Preston-Werner" } name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 } point = { x = 1, y = 2 }
animal = { type.name = "pug" } animal = { type.name = "pug" }
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
REQUIRE(tbl["name"].as_table()); REQUIRE(tbl["name"].as_table());
CHECK(tbl["name"].as_table()->size() == 2u); CHECK(tbl["name"].as_table()->size() == 2u);
CHECK(tbl["name"].as_table()->is_inline()); CHECK(tbl["name"].as_table()->is_inline());
CHECK(tbl["name"]["first"] == "Tom"sv); CHECK(tbl["name"]["first"] == "Tom"sv);
CHECK(tbl["name"]["last"] == "Preston-Werner"sv); CHECK(tbl["name"]["last"] == "Preston-Werner"sv);
REQUIRE(tbl["point"].as_table()); REQUIRE(tbl["point"].as_table());
CHECK(tbl["point"].as_table()->size() == 2u); CHECK(tbl["point"].as_table()->size() == 2u);
CHECK(tbl["point"].as_table()->is_inline()); CHECK(tbl["point"].as_table()->is_inline());
CHECK(tbl["point"]["x"] == 1); CHECK(tbl["point"]["x"] == 1);
CHECK(tbl["point"]["y"] == 2); CHECK(tbl["point"]["y"] == 2);
REQUIRE(tbl["animal"].as_table()); REQUIRE(tbl["animal"].as_table());
CHECK(tbl["animal"].as_table()->size() == 1u); CHECK(tbl["animal"].as_table()->size() == 1u);
CHECK(tbl["animal"].as_table()->is_inline()); CHECK(tbl["animal"].as_table()->is_inline());
REQUIRE(tbl["animal"]["type"].as_table()); REQUIRE(tbl["animal"]["type"].as_table());
CHECK(tbl["animal"]["type"].as_table()->size() == 1u); CHECK(tbl["animal"]["type"].as_table()->size() == 1u);
CHECK(tbl["animal"]["type"]["name"] == "pug"sv); CHECK(tbl["animal"]["type"]["name"] == "pug"sv);
} });
);
// "Inline tables are fully self-contained and define all keys and sub-tables within them. // "Inline tables are fully self-contained and define all keys and sub-tables within them.
// Keys and sub-tables cannot be added outside the braces." // Keys and sub-tables cannot be added outside the braces."
@ -367,176 +344,167 @@ TEST_CASE("parsing - inline tables")
)"sv); )"sv);
// "newlines are allowed between the curly braces [if] they are valid within a value." // "newlines are allowed between the curly braces [if] they are valid within a value."
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"(
test = { val1 = "foo", val2 = [ test = { val1 = "foo", val2 = [
1, 2, 1, 2,
3 3
], val3 = "bar" } ], val3 = "bar" }
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
REQUIRE(tbl["test"].as_table()); REQUIRE(tbl["test"].as_table());
CHECK(tbl["test"].as_table()->size() == 3u); CHECK(tbl["test"].as_table()->size() == 3u);
CHECK(tbl["test"]["val1"] == "foo"sv); CHECK(tbl["test"]["val1"] == "foo"sv);
REQUIRE(tbl["test"]["val2"].as<array>()); REQUIRE(tbl["test"]["val2"].as<array>());
CHECK(tbl["test"]["val2"].as<array>()->size() == 3u); CHECK(tbl["test"]["val2"].as<array>()->size() == 3u);
CHECK(tbl["test"]["val2"][0] == 1); CHECK(tbl["test"]["val2"][0] == 1);
CHECK(tbl["test"]["val2"][1] == 2); CHECK(tbl["test"]["val2"][1] == 2);
CHECK(tbl["test"]["val2"][2] == 3); CHECK(tbl["test"]["val2"][2] == 3);
CHECK(tbl["test"]["val3"] == "bar"sv); CHECK(tbl["test"]["val3"] == "bar"sv);
} });
);
// toml/issues/516 (newlines/trailing commas in inline tables) // toml/issues/516 (newlines/trailing commas in inline tables)
#if TOML_LANG_UNRELEASED #if TOML_LANG_UNRELEASED
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( name = {
name = { first = "Tom",
first = "Tom", last = "Preston-Werner",
last = "Preston-Werner",
}
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["name"].as_table());
CHECK(tbl["name"].as_table()->size() == 2u);
CHECK(tbl["name"]["first"] == "Tom"sv);
CHECK(tbl["name"]["last"] == "Preston-Werner"sv);
} }
); )"sv,
[](table&& tbl)
{
REQUIRE(tbl["name"].as_table());
CHECK(tbl["name"].as_table()->size() == 2u);
CHECK(tbl["name"]["first"] == "Tom"sv);
CHECK(tbl["name"]["last"] == "Preston-Werner"sv);
});
} }
#else #else
{ {
// "A terminating comma (also called trailing comma) is not permitted after the last key/value pair in an inline table." // "A terminating comma (also called trailing comma) is not permitted after the last key/value pair in an inline
// table."
parsing_should_fail(FILE_LINE_ARGS, R"(name = { first = "Tom", last = "Preston-Werner", })"sv); parsing_should_fail(FILE_LINE_ARGS, R"(name = { first = "Tom", last = "Preston-Werner", })"sv);
// "No newlines are allowed between the curly braces unless they are valid within a value." // "No newlines are allowed between the curly braces unless they are valid within a value."
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
name = { name = {
first = "Tom", first = "Tom",
last = "Preston-Werner" last = "Preston-Werner"
} }
)"sv); )"sv);
} }
#endif #endif
} }
TEST_CASE("parsing - arrays-of-tables") TEST_CASE("parsing - arrays-of-tables")
{ {
parsing_should_succeed( parsing_should_succeed(FILE_LINE_ARGS,
FILE_LINE_ARGS, R"(
R"( points = [ { x = 1, y = 2, z = 3 },
points = [ { x = 1, y = 2, z = 3 }, { x = 7, y = 8, z = 9 },
{ x = 7, y = 8, z = 9 }, { x = 2, y = 4, z = 8 } ]
{ x = 2, y = 4, z = 8 } ]
[[products]] [[products]]
name = "Hammer" name = "Hammer"
sku = 738594937 sku = 738594937
[[products]] [[products]]
[[products]] [[products]]
name = "Nail" name = "Nail"
sku = 284758393 sku = 284758393
color = "gray" color = "gray"
[[fruit]] [[fruit]]
name = "apple" name = "apple"
[fruit.physical] # subtable [fruit.physical] # subtable
color = "red" color = "red"
shape = "round" shape = "round"
[[fruit.variety]] # nested array of tables [[fruit.variety]] # nested array of tables
name = "red delicious" name = "red delicious"
[[fruit.variety]] [[fruit.variety]]
name = "granny smith" name = "granny smith"
[[fruit]] [[fruit]]
name = "banana" name = "banana"
[[fruit.variety]] [[fruit.variety]]
name = "plantain" name = "plantain"
)"sv, )"sv,
[](table&& tbl) [](table&& tbl)
{ {
REQUIRE(tbl["points"].as<array>()); REQUIRE(tbl["points"].as<array>());
CHECK(tbl["points"].as<array>()->size() == 3u); CHECK(tbl["points"].as<array>()->size() == 3u);
CHECK(tbl["points"].as<array>()->is_homogeneous()); CHECK(tbl["points"].as<array>()->is_homogeneous());
CHECK(tbl["points"].as<array>()->is_array_of_tables()); CHECK(tbl["points"].as<array>()->is_array_of_tables());
CHECK(tbl["points"][0]["x"] == 1); CHECK(tbl["points"][0]["x"] == 1);
CHECK(tbl["points"][0]["y"] == 2); CHECK(tbl["points"][0]["y"] == 2);
CHECK(tbl["points"][0]["z"] == 3); CHECK(tbl["points"][0]["z"] == 3);
CHECK(tbl["points"][1]["x"] == 7); CHECK(tbl["points"][1]["x"] == 7);
CHECK(tbl["points"][1]["y"] == 8); CHECK(tbl["points"][1]["y"] == 8);
CHECK(tbl["points"][1]["z"] == 9); CHECK(tbl["points"][1]["z"] == 9);
CHECK(tbl["points"][2]["x"] == 2); CHECK(tbl["points"][2]["x"] == 2);
CHECK(tbl["points"][2]["y"] == 4); CHECK(tbl["points"][2]["y"] == 4);
CHECK(tbl["points"][2]["z"] == 8); CHECK(tbl["points"][2]["z"] == 8);
REQUIRE(tbl["products"].as<array>()); REQUIRE(tbl["products"].as<array>());
CHECK(tbl["products"].as<array>()->size() == 3u); CHECK(tbl["products"].as<array>()->size() == 3u);
CHECK(tbl["products"].as<array>()->is_homogeneous()); CHECK(tbl["products"].as<array>()->is_homogeneous());
CHECK(tbl["products"].as<array>()->is_array_of_tables()); CHECK(tbl["products"].as<array>()->is_array_of_tables());
REQUIRE(tbl["products"][0].as_table()); REQUIRE(tbl["products"][0].as_table());
CHECK(tbl["products"][0].as_table()->size() == 2u); CHECK(tbl["products"][0].as_table()->size() == 2u);
CHECK(tbl["products"][0]["name"] == "Hammer"sv); CHECK(tbl["products"][0]["name"] == "Hammer"sv);
CHECK(tbl["products"][0]["sku"] == 738594937); CHECK(tbl["products"][0]["sku"] == 738594937);
REQUIRE(tbl["products"][1].as_table()); REQUIRE(tbl["products"][1].as_table());
CHECK(tbl["products"][1].as_table()->size() == 0u); CHECK(tbl["products"][1].as_table()->size() == 0u);
REQUIRE(tbl["products"][2].as_table()); REQUIRE(tbl["products"][2].as_table());
CHECK(tbl["products"][2].as_table()->size() == 3u); CHECK(tbl["products"][2].as_table()->size() == 3u);
CHECK(tbl["products"][2]["name"] == "Nail"sv); CHECK(tbl["products"][2]["name"] == "Nail"sv);
CHECK(tbl["products"][2]["sku"] == 284758393); CHECK(tbl["products"][2]["sku"] == 284758393);
CHECK(tbl["products"][2]["color"] == "gray"sv); CHECK(tbl["products"][2]["color"] == "gray"sv);
REQUIRE(tbl["fruit"].as<array>());
CHECK(tbl["fruit"].as<array>()->size() == 2u);
CHECK(tbl["fruit"].as<array>()->is_homogeneous());
CHECK(tbl["fruit"].as<array>()->is_array_of_tables());
REQUIRE(tbl["fruit"].as<array>()); REQUIRE(tbl["fruit"][0].as_table());
CHECK(tbl["fruit"].as<array>()->size() == 2u); CHECK(tbl["fruit"][0].as_table()->size() == 3u);
CHECK(tbl["fruit"].as<array>()->is_homogeneous()); CHECK(tbl["fruit"][0]["name"] == "apple"sv);
CHECK(tbl["fruit"].as<array>()->is_array_of_tables());
REQUIRE(tbl["fruit"][0].as_table()); REQUIRE(tbl["fruit"][0]["physical"].as_table());
CHECK(tbl["fruit"][0].as_table()->size() == 3u); CHECK(tbl["fruit"][0]["physical"].as_table()->size() == 2u);
CHECK(tbl["fruit"][0]["name"] == "apple"sv); CHECK(tbl["fruit"][0]["physical"]["color"] == "red"sv);
CHECK(tbl["fruit"][0]["physical"]["shape"] == "round"sv);
REQUIRE(tbl["fruit"][0]["physical"].as_table()); REQUIRE(tbl["fruit"][0]["variety"].as<array>());
CHECK(tbl["fruit"][0]["physical"].as_table()->size() == 2u); CHECK(tbl["fruit"][0]["variety"].as<array>()->size() == 2u);
CHECK(tbl["fruit"][0]["physical"]["color"] == "red"sv); CHECK(tbl["fruit"][0]["variety"].as<array>()->is_homogeneous());
CHECK(tbl["fruit"][0]["physical"]["shape"] == "round"sv); CHECK(tbl["fruit"][0]["variety"].as<array>()->is_array_of_tables());
CHECK(tbl["fruit"][0]["variety"][0]["name"] == "red delicious"sv);
CHECK(tbl["fruit"][0]["variety"][1]["name"] == "granny smith"sv);
REQUIRE(tbl["fruit"][0]["variety"].as<array>()); REQUIRE(tbl["fruit"][1].as_table());
CHECK(tbl["fruit"][0]["variety"].as<array>()->size() == 2u); CHECK(tbl["fruit"][1].as_table()->size() == 2u);
CHECK(tbl["fruit"][0]["variety"].as<array>()->is_homogeneous()); CHECK(tbl["fruit"][1]["name"] == "banana"sv);
CHECK(tbl["fruit"][0]["variety"].as<array>()->is_array_of_tables());
CHECK(tbl["fruit"][0]["variety"][0]["name"] == "red delicious"sv);
CHECK(tbl["fruit"][0]["variety"][1]["name"] == "granny smith"sv);
REQUIRE(tbl["fruit"][1].as_table()); REQUIRE(tbl["fruit"][1]["variety"].as<array>());
CHECK(tbl["fruit"][1].as_table()->size() == 2u); CHECK(tbl["fruit"][1]["variety"].as<array>()->size() == 1u);
CHECK(tbl["fruit"][1]["name"] == "banana"sv); CHECK(tbl["fruit"][1]["variety"].as<array>()->is_homogeneous());
CHECK(tbl["fruit"][1]["variety"].as<array>()->is_array_of_tables());
REQUIRE(tbl["fruit"][1]["variety"].as<array>()); CHECK(tbl["fruit"][1]["variety"][0]["name"] == "plantain"sv);
CHECK(tbl["fruit"][1]["variety"].as<array>()->size() == 1u); });
CHECK(tbl["fruit"][1]["variety"].as<array>()->is_homogeneous());
CHECK(tbl["fruit"][1]["variety"].as<array>()->is_array_of_tables());
CHECK(tbl["fruit"][1]["variety"][0]["name"] == "plantain"sv);
}
);
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS, R"(
# INVALID TOML DOC # INVALID TOML DOC

View File

@ -2,33 +2,32 @@
// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> // Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#pragma once #pragma once
// toml++ config // toml++ config
#define TOML_UNDEF_MACROS 0 #define TOML_UNDEF_MACROS 0
#ifndef TOML_HEADER_ONLY #ifndef TOML_HEADER_ONLY
#define TOML_HEADER_ONLY 0 #define TOML_HEADER_ONLY 0
#endif #endif
#ifndef USE_SINGLE_HEADER #ifndef USE_SINGLE_HEADER
#define USE_SINGLE_HEADER 0 #define USE_SINGLE_HEADER 0
#endif #endif
#if defined(LEAK_TESTS) && LEAK_TESTS #if defined(LEAK_TESTS) && LEAK_TESTS
#define TOML_CONFIG_HEADER "leakproof.h" #define TOML_CONFIG_HEADER "leakproof.h"
#else #else
#undef LEAK_TESTS #undef LEAK_TESTS
#define LEAK_TESTS 0 #define LEAK_TESTS 0
#endif #endif
// use tl::optional? // use tl::optional?
#if defined(USE_TARTANLLAMA_OPTIONAL) && USE_TARTANLLAMA_OPTIONAL #if defined(USE_TARTANLLAMA_OPTIONAL) && USE_TARTANLLAMA_OPTIONAL
#define TOML_OPTIONAL_TYPE tl::optional #define TOML_OPTIONAL_TYPE tl::optional
#else #else
#undef USE_TARTANLLAMA_OPTIONAL #undef USE_TARTANLLAMA_OPTIONAL
#define USE_TARTANLLAMA_OPTIONAL 0 #define USE_TARTANLLAMA_OPTIONAL 0
#endif #endif
//catch2 config // catch2 config
#define CATCH_CONFIG_CPP11_TO_STRING #define CATCH_CONFIG_CPP11_TO_STRING
#define CATCH_CONFIG_CPP17_OPTIONAL #define CATCH_CONFIG_CPP17_OPTIONAL
#define CATCH_CONFIG_CPP17_STRING_VIEW #define CATCH_CONFIG_CPP17_STRING_VIEW
@ -38,65 +37,64 @@
#define CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_CONFIG_NO_NOMINMAX #define CATCH_CONFIG_NO_NOMINMAX
//windows.h config (included transitively by catch2 on windows) // windows.h config (included transitively by catch2 on windows)
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN #define VC_EXTRALEAN
#define NOATOM // - Atom Manager routines #define NOATOM // Atom Manager routines
#define NOBITMAP #define NOBITMAP //
#define NOCLIPBOARD // - Clipboard routines #define NOCLIPBOARD // Clipboard routines
#define NOCOLOR // - Screen colors #define NOCOLOR // Screen colors
#define NOCOMM // - COMM driver routines #define NOCOMM // COMM driver routines
#define NOCTLMGR // - Control and Dialog routines #define NOCTLMGR // Control and Dialog routines
#define NODEFERWINDOWPOS // - DeferWindowPos routines #define NODEFERWINDOWPOS // DeferWindowPos routines
#define NODRAWTEXT // - DrawText() and DT_* #define NODRAWTEXT // DrawText() and DT_*
#define NOGDI // - All GDI defines and routines #define NOGDI // All GDI defines and routines
#define NOGDICAPMASKS // - CC_*, LC_*, PC_*, CP_*, TC_*, RC_ #define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
#define NOHELP // - Help engine interface. #define NOHELP // Help engine interface.
#define NOICONS // - IDI_* #define NOICONS // IDI_*
#define NOKANJI // - Kanji support stuff. #define NOKANJI // Kanji support stuff.
#define NOKEYSTATES // - MK_* #define NOKEYSTATES // MK_*
#define NOKERNEL // - All KERNEL defines and routines #define NOKERNEL // All KERNEL defines and routines
#define NOMB // - MB_* and MessageBox() #define NOMB // MB_* and MessageBox()
#define NOMCX // - Modem Configuration Extensions #define NOMCX // Modem Configuration Extensions
#define NOMENUS // - MF_* #define NOMENUS // MF_*
#define NOMEMMGR // - GMEM_*, LMEM_*, GHND, LHND, associated routines #define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
#define NOMETAFILE // - typedef METAFILEPICT #define NOMETAFILE // typedef METAFILEPICT
//#define NOMINMAX // - Macros min(a,b) and max(a,b) #define NOMSG // typedef MSG and associated routines
#define NOMSG // - typedef MSG and associated routines #define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
//#define NONLS // - All NLS defines and routines #define NOPROFILER // Profiler interface.
#define NOOPENFILE // - OpenFile(), OemToAnsi, AnsiToOem, and OF_* #define NORASTEROPS // Binary and Tertiary raster ops
#define NOPROFILER // - Profiler interface. #define NOSCROLL // SB_* and scrolling routines
#define NORASTEROPS // - Binary and Tertiary raster ops #define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
#define NOSCROLL // - SB_* and scrolling routines #define NOSHOWWINDOW // SW_*
#define NOSERVICE // - All Service Controller routines, SERVICE_ equates, etc. #define NOSOUND // Sound driver routines
#define NOSHOWWINDOW // - SW_* #define NOSYSCOMMANDS // SC_*
#define NOSOUND // - Sound driver routines #define NOSYSMETRICS // SM_*
#define NOSYSCOMMANDS // - SC_* #define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
#define NOSYSMETRICS // - SM_* #define NOUSER // All USER defines and routines
#define NOTEXTMETRIC // - typedef TEXTMETRIC and associated routines #define NOVIRTUALKEYCODES // VK_*
#define NOUSER // - All USER defines and routines #define NOWH // SetWindowsHook and WH_*
#define NOVIRTUALKEYCODES // - VK_* #define NOWINOFFSETS // GWL_*, GCL_*, associated routines
#define NOWH // - SetWindowsHook and WH_* #define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_*
#define NOWINOFFSETS // - GWL_*, GCL_*, associated routines #define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
#define NOWINMESSAGES // - WM_*, EM_*, LB_*, CB_* //#define NOMINMAX // Macros min(a,b) and max(a,b)
#define NOWINSTYLES // - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* //#define NONLS // All NLS defines and routines
#endif #endif
// test harness stuff // test harness stuff
#ifndef SHOULD_HAVE_FP16 #ifndef SHOULD_HAVE_FP16
#define SHOULD_HAVE_FP16 0 #define SHOULD_HAVE_FP16 0
#endif #endif
#ifndef SHOULD_HAVE_FLOAT16 #ifndef SHOULD_HAVE_FLOAT16
#define SHOULD_HAVE_FLOAT16 0 #define SHOULD_HAVE_FLOAT16 0
#endif #endif
#ifndef SHOULD_HAVE_FLOAT128 #ifndef SHOULD_HAVE_FLOAT128
#define SHOULD_HAVE_FLOAT128 0 #define SHOULD_HAVE_FLOAT128 0
#endif #endif
#ifndef SHOULD_HAVE_INT128 #ifndef SHOULD_HAVE_INT128
#define SHOULD_HAVE_INT128 0 #define SHOULD_HAVE_INT128 0
#endif #endif
#ifndef SHOULD_HAVE_EXCEPTIONS #ifndef SHOULD_HAVE_EXCEPTIONS
#define SHOULD_HAVE_EXCEPTIONS 1 #define SHOULD_HAVE_EXCEPTIONS 1
#endif #endif

View File

@ -5,14 +5,14 @@
#include "tests.h" #include "tests.h"
bool parsing_should_succeed( bool parsing_should_succeed(std::string_view test_file,
std::string_view test_file, uint32_t test_line,
uint32_t test_line, std::string_view toml_str,
std::string_view toml_str, pss_func&& func,
pss_func&& func, std::string_view source_path)
std::string_view source_path)
{ {
INFO("["sv << test_file << ", line "sv << test_line << "] "sv << "parsing_should_succeed(\""sv << toml_str << "\")"sv) INFO("["sv << test_file << ", line "sv << test_line << "] "sv
<< "parsing_should_succeed(\""sv << toml_str << "\")"sv)
constexpr auto validate_table = [](table&& tabl, std::string_view path) -> table&& constexpr auto validate_table = [](table&& tabl, std::string_view path) -> table&&
{ {
@ -29,7 +29,7 @@ bool parsing_should_succeed(
return std::move(tabl); return std::move(tabl);
}; };
#if TOML_EXCEPTIONS #if TOML_EXCEPTIONS
try try
{ {
@ -52,15 +52,12 @@ bool parsing_should_succeed(
} }
catch (const parse_error& err) catch (const parse_error& err)
{ {
FORCE_FAIL( FORCE_FAIL("Parse error on line "sv << err.source().begin.line << ", column "sv << err.source().begin.column
"Parse error on line "sv << err.source().begin.line << ":\n"sv << err.description());
<< ", column "sv << err.source().begin.column
<< ":\n"sv << err.description()
);
return false; return false;
} }
#else #else
{ {
INFO("Parsing string directly"sv) INFO("Parsing string directly"sv)
@ -74,11 +71,9 @@ bool parsing_should_succeed(
} }
else else
{ {
FORCE_FAIL( FORCE_FAIL("Parse error on line "sv << result.error().source().begin.line << ", column "sv
"Parse error on line "sv << result.error().source().begin.line << result.error().source().begin.column << ":\n"sv
<< ", column "sv << result.error().source().begin.column << result.error().description());
<< ":\n"sv << result.error().description()
);
} }
} }
@ -96,29 +91,27 @@ bool parsing_should_succeed(
} }
else else
{ {
FORCE_FAIL( FORCE_FAIL("Parse error on line "sv << result.error().source().begin.line << ", column "sv
"Parse error on line "sv << result.error().source().begin.line << result.error().source().begin.column << ":\n"sv
<< ", column "sv << result.error().source().begin.column << result.error().description());
<< ":\n"sv << result.error().description()
);
} }
} }
#endif #endif
return true; return true;
} }
bool parsing_should_fail( bool parsing_should_fail(std::string_view test_file,
std::string_view test_file, uint32_t test_line,
uint32_t test_line, std::string_view toml_str,
std::string_view toml_str, source_index expected_failure_line,
source_index expected_failure_line, source_index expected_failure_column)
source_index expected_failure_column)
{ {
INFO("["sv << test_file << ", line "sv << test_line << "] "sv << "parsing_should_fail(\""sv << toml_str << "\")"sv) INFO("["sv << test_file << ", line "sv << test_line << "] "sv
<< "parsing_should_fail(\""sv << toml_str << "\")"sv)
#if TOML_EXCEPTIONS #if TOML_EXCEPTIONS
static constexpr auto run_tests = [](source_index ex_line, source_index ex_col, auto&& fn) static constexpr auto run_tests = [](source_index ex_line, source_index ex_col, auto&& fn)
{ {
@ -130,17 +123,15 @@ bool parsing_should_fail(
{ {
if (ex_line != static_cast<source_index>(-1) && err.source().begin.line != ex_line) if (ex_line != static_cast<source_index>(-1) && err.source().begin.line != ex_line)
{ {
FORCE_FAIL("Expected parse_error at line "sv << ex_line FORCE_FAIL("Expected parse_error at line "sv << ex_line << ", actually occured at line "sv
<< ", actually occured at line "sv << err.source().begin.line << err.source().begin.line);
);
return false; return false;
} }
if (ex_col != static_cast<source_index>(-1) && err.source().begin.column != ex_col) if (ex_col != static_cast<source_index>(-1) && err.source().begin.column != ex_col)
{ {
FORCE_FAIL("Expected parse_error at column "sv << ex_col FORCE_FAIL("Expected parse_error at column "sv << ex_col << ", actually occured at column "sv
<< ", actually occured at column "sv << err.source().begin.column << err.source().begin.column);
);
return false; return false;
} }
@ -162,19 +153,21 @@ bool parsing_should_fail(
return false; return false;
}; };
auto result = run_tests(expected_failure_line, expected_failure_column, [=]() auto result = run_tests(expected_failure_line,
{ expected_failure_column,
[[maybe_unused]] auto res = toml::parse(toml_str); [=]() { [[maybe_unused]] auto res = toml::parse(toml_str); });
}); result = result
result = result && run_tests(expected_failure_line, expected_failure_column, [=]() && run_tests(expected_failure_line,
{ expected_failure_column,
std::stringstream ss; [=]()
ss.write(toml_str.data(), static_cast<std::streamsize>(toml_str.length())); {
[[maybe_unused]] auto res = toml::parse(ss); std::stringstream ss;
}); ss.write(toml_str.data(), static_cast<std::streamsize>(toml_str.length()));
[[maybe_unused]] auto res = toml::parse(ss);
});
return result; return result;
#else #else
static constexpr auto run_tests = [](source_index ex_line, source_index ex_col, auto&& fn) static constexpr auto run_tests = [](source_index ex_line, source_index ex_col, auto&& fn)
{ {
@ -182,16 +175,14 @@ bool parsing_should_fail(
{ {
if (ex_line != static_cast<source_index>(-1) && result.error().source().begin.line != ex_line) if (ex_line != static_cast<source_index>(-1) && result.error().source().begin.line != ex_line)
{ {
FORCE_FAIL("Expected parse_error at line "sv << ex_line FORCE_FAIL("Expected parse_error at line "sv << ex_line << ", actually occured at line "sv
<< ", actually occured at line "sv << result.error().source().begin.line << result.error().source().begin.line);
);
} }
if (ex_col != static_cast<source_index>(-1) && result.error().source().begin.column != ex_col) if (ex_col != static_cast<source_index>(-1) && result.error().source().begin.column != ex_col)
{ {
FORCE_FAIL("Expected parse_error at column "sv << ex_col FORCE_FAIL("Expected parse_error at column "sv << ex_col << ", actually occured at column "sv
<< ", actually occured at column "sv << result.error().source().begin.column << result.error().source().begin.column);
);
} }
SUCCEED("parse_error generated OK"sv); SUCCEED("parse_error generated OK"sv);
@ -202,14 +193,16 @@ bool parsing_should_fail(
}; };
return run_tests(expected_failure_line, expected_failure_column, [=]() { return toml::parse(toml_str); }) return run_tests(expected_failure_line, expected_failure_column, [=]() { return toml::parse(toml_str); })
&& run_tests(expected_failure_line, expected_failure_column, [=]() && run_tests(expected_failure_line,
{ expected_failure_column,
std::stringstream ss; [=]()
ss.write(toml_str.data(), static_cast<std::streamsize>(toml_str.length())); {
return toml::parse(ss); std::stringstream ss;
}); ss.write(toml_str.data(), static_cast<std::streamsize>(toml_str.length()));
return toml::parse(ss);
});
#endif #endif
} }
template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const int&); template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const int&);
@ -227,8 +220,8 @@ namespace Catch
{ {
template struct StringMaker<node_view<node>>; template struct StringMaker<node_view<node>>;
template struct StringMaker<node_view<const node>>; template struct StringMaker<node_view<const node>>;
template ReusableStringStream& ReusableStringStream::operator << (toml::node_view<toml::node> const&); template ReusableStringStream& ReusableStringStream::operator<<(toml::node_view<toml::node> const&);
template ReusableStringStream& ReusableStringStream::operator << (toml::node_view<const toml::node> const&); template ReusableStringStream& ReusableStringStream::operator<<(toml::node_view<const toml::node> const&);
namespace Detail namespace Detail
{ {
template std::string stringify(const node_view<node>&); template std::string stringify(const node_view<node>&);

View File

@ -7,82 +7,92 @@
#include "settings.h" #include "settings.h"
#if USE_TARTANLLAMA_OPTIONAL #if USE_TARTANLLAMA_OPTIONAL
#include "tloptional.h" #include "lib_tloptional.h"
#endif #endif
#if USE_SINGLE_HEADER #if USE_SINGLE_HEADER
#include "../toml.hpp" #include "../toml.hpp"
#else #else
#include "../include/toml++/toml.h" #include "../include/toml++/toml.h"
#endif #endif
#if defined(TOML_FP16) ^ SHOULD_HAVE_FP16 #if defined(TOML_FP16) ^ SHOULD_HAVE_FP16
#error TOML_FP16 was not deduced correctly #error TOML_FP16 was not deduced correctly
#endif #endif
#if defined(TOML_FLOAT16) ^ SHOULD_HAVE_FLOAT16 #if defined(TOML_FLOAT16) ^ SHOULD_HAVE_FLOAT16
#error TOML_FLOAT16 was not deduced correctly #error TOML_FLOAT16 was not deduced correctly
#endif #endif
#if defined(TOML_FLOAT128) ^ SHOULD_HAVE_FLOAT128 #if defined(TOML_FLOAT128) ^ SHOULD_HAVE_FLOAT128
#error TOML_FLOAT128 was not deduced correctly #error TOML_FLOAT128 was not deduced correctly
#endif #endif
#if defined(TOML_INT128) ^ SHOULD_HAVE_INT128 #if defined(TOML_INT128) ^ SHOULD_HAVE_INT128
#error TOML_INT128 was not deduced correctly #error TOML_INT128 was not deduced correctly
#endif #endif
#if defined(TOML_INT128) ^ defined(TOML_UINT128) #if defined(TOML_INT128) ^ defined(TOML_UINT128)
#error TOML_INT128 and TOML_UINT128 must both be defined, or neither be defined #error TOML_INT128 and TOML_UINT128 must both be defined, or neither be defined
#endif #endif
#if TOML_COMPILER_EXCEPTIONS != SHOULD_HAVE_EXCEPTIONS #if TOML_COMPILER_EXCEPTIONS != SHOULD_HAVE_EXCEPTIONS
#error TOML_COMPILER_EXCEPTIONS was not deduced correctly #error TOML_COMPILER_EXCEPTIONS was not deduced correctly
#endif #endif
#if TOML_COMPILER_EXCEPTIONS != TOML_EXCEPTIONS #if TOML_COMPILER_EXCEPTIONS != TOML_EXCEPTIONS
#error TOML_EXCEPTIONS does not match TOML_COMPILER_EXCEPTIONS (default behaviour should be to match) #error TOML_EXCEPTIONS does not match TOML_COMPILER_EXCEPTIONS (default behaviour should be to match)
#endif #endif
#if (defined(_WIN32) && !TOML_WINDOWS_COMPAT) || (!defined(_WIN32) && TOML_WINDOWS_COMPAT) #if (defined(_WIN32) && !TOML_WINDOWS_COMPAT) || (!defined(_WIN32) && TOML_WINDOWS_COMPAT)
#error TOML_WINDOWS_COMPAT does not match _WIN32 (default behaviour should be to match) #error TOML_WINDOWS_COMPAT does not match _WIN32 (default behaviour should be to match)
#endif #endif
#if TOML_ICC #if TOML_ICC
#define UNICODE_LITERALS_OK 0 #define UNICODE_LITERALS_OK 0
#else #else
#define UNICODE_LITERALS_OK 1 #define UNICODE_LITERALS_OK 1
#endif #endif
TOML_DISABLE_SPAM_WARNINGS; TOML_DISABLE_SPAM_WARNINGS;
TOML_DISABLE_ARITHMETIC_WARNINGS; TOML_DISABLE_ARITHMETIC_WARNINGS;
TOML_DISABLE_WARNINGS; TOML_DISABLE_WARNINGS;
#include "catch2.h" #include "lib_catch2.h"
#include <sstream> #include <sstream>
namespace toml {} namespace toml
{
}
using namespace Catch::literals; using namespace Catch::literals;
using namespace toml; using namespace toml;
TOML_ENABLE_WARNINGS; TOML_ENABLE_WARNINGS;
#define FILE_LINE_ARGS std::string_view{ __FILE__ }, __LINE__ TOML_NODISCARD
#define BOM_PREFIX "\xEF\xBB\xBF" TOML_ATTR(const)
TOML_ALWAYS_INLINE
constexpr size_t operator"" _sz(unsigned long long n) noexcept
{
return static_cast<size_t>(n);
}
#define FILE_LINE_ARGS std::string_view{ __FILE__ }, __LINE__
#define BOM_PREFIX "\xEF\xBB\xBF"
#if TOML_EXCEPTIONS #if TOML_EXCEPTIONS
#define FORCE_FAIL(...) FAIL(__VA_ARGS__) #define FORCE_FAIL(...) FAIL(__VA_ARGS__)
#else #else
#define FORCE_FAIL(...) \ #define FORCE_FAIL(...) \
do \ do \
{ \ { \
FAIL(__VA_ARGS__); \ FAIL(__VA_ARGS__); \
std::exit(-1); \ std::exit(-1); \
TOML_UNREACHABLE; \ TOML_UNREACHABLE; \
} \ } \
while (false) while (false)
#endif #endif
#define CHECK_SYMMETRIC_RELOP(lhs, op, rhs, result) \ #define CHECK_SYMMETRIC_RELOP(lhs, op, rhs, result) \
CHECK(((lhs) op (rhs)) == (result)); \ CHECK(((lhs)op(rhs)) == (result)); \
CHECK(((rhs) op (lhs)) == (result)) CHECK(((rhs)op(lhs)) == (result))
#define CHECK_SYMMETRIC_EQUAL(lhs, rhs) \ #define CHECK_SYMMETRIC_EQUAL(lhs, rhs) \
CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, true); \ CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, true); \
CHECK_SYMMETRIC_RELOP(lhs, !=, rhs, false) CHECK_SYMMETRIC_RELOP(lhs, !=, rhs, false)
#define CHECK_SYMMETRIC_INEQUAL(lhs, rhs) \ #define CHECK_SYMMETRIC_INEQUAL(lhs, rhs) \
CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, false); \ CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, false); \
CHECK_SYMMETRIC_RELOP(lhs, !=, rhs, true) CHECK_SYMMETRIC_RELOP(lhs, !=, rhs, true)
// function_view - adapted from here: https://vittorioromeo.info/index/blog/passing_functions_to_functions.html // function_view - adapted from here: https://vittorioromeo.info/index/blog/passing_functions_to_functions.html
@ -91,59 +101,57 @@ class function_view;
template <typename R, typename... P> template <typename R, typename... P>
class function_view<R(P...)> final class function_view<R(P...)> final
{ {
private: private:
using func_type = R(P...); using func_type = R(P...);
using eraser_func_type = R(void*, P&&...); using eraser_func_type = R(void*, P&&...);
mutable void* ptr_ = {}; mutable void* ptr_ = {};
mutable eraser_func_type* eraser = {}; mutable eraser_func_type* eraser = {};
public: public:
function_view() noexcept = default;
function_view() noexcept = default; template <typename T>
function_view(T&& x) noexcept : ptr_{ reinterpret_cast<void*>(std::addressof(x)) }
{
eraser = [](void* ptr, P&&... xs) -> R
{ return (*reinterpret_cast<std::add_pointer_t<std::remove_reference_t<T>>>(ptr))(std::forward<P>(xs)...); };
}
template <typename T> decltype(auto) operator()(P&&... xs) const
function_view(T&& x) noexcept {
: ptr_{ reinterpret_cast<void*>(std::addressof(x)) } return eraser(ptr_, std::forward<P>(xs)...);
{ }
eraser = [](void* ptr, P&&... xs) -> R
{
return (*reinterpret_cast<std::add_pointer_t<std::remove_reference_t<T>>>(ptr))(std::forward<P>(xs)...);
};
}
decltype(auto) operator()(P&&... xs) const TOML_NODISCARD
{ operator bool() const noexcept
return eraser(ptr_, std::forward<P>(xs)...); {
} return !!ptr_;
}
[[nodiscard]] operator bool() const noexcept { return !!ptr_; }
}; };
using pss_func = function_view<void(toml::table&&)>; using pss_func = function_view<void(toml::table&&)>;
bool parsing_should_succeed( bool parsing_should_succeed(std::string_view test_file,
std::string_view test_file, uint32_t test_line,
uint32_t test_line, std::string_view toml_str,
std::string_view toml_str, pss_func&& func = {},
pss_func&& func = {}, std::string_view source_path = {});
std::string_view source_path = {});
bool parsing_should_fail( bool parsing_should_fail(std::string_view test_file,
std::string_view test_file, uint32_t test_line,
uint32_t test_line, std::string_view toml_str,
std::string_view toml_str, source_index expected_failure_line = static_cast<source_index>(-1),
source_index expected_failure_line = static_cast<source_index>(-1), source_index expected_failure_column = static_cast<source_index>(-1));
source_index expected_failure_column = static_cast<source_index>(-1));
template <typename T> template <typename T>
inline bool parse_expected_value( inline bool parse_expected_value(std::string_view test_file,
std::string_view test_file, uint32_t test_line,
uint32_t test_line, std::string_view value_str,
std::string_view value_str, const T& expected)
const T& expected)
{ {
INFO("["sv << test_file << ", line "sv << test_line << "] "sv << "parse_expected_value(\""sv << value_str << "\")"sv) INFO("["sv << test_file << ", line "sv << test_line << "] "sv
<< "parse_expected_value(\""sv << value_str << "\")"sv)
std::string val; std::string val;
static constexpr auto key = "val = "sv; static constexpr auto key = "val = "sv;
@ -159,7 +167,7 @@ inline bool parse_expected_value(
return !impl::is_whitespace(codepoint); return !impl::is_whitespace(codepoint);
}; };
source_position pos{ 1, static_cast<source_index>(key.length()) }; source_position pos{ 1, static_cast<source_index>(key.length()) };
source_position begin{}, end{}; source_position begin{}, end{};
{ {
impl::utf8_decoder decoder; impl::utf8_decoder decoder;
@ -196,7 +204,8 @@ inline bool parse_expected_value(
using value_type = impl::native_type_of<impl::remove_cvref_t<T>>; using value_type = impl::native_type_of<impl::remove_cvref_t<T>>;
value<value_type> val_parsed; value<value_type> val_parsed;
{ {
INFO("["sv << test_file << ", line "sv << test_line << "] "sv << "parse_expected_value: Checking initial parse"sv) INFO("["sv << test_file << ", line "sv << test_line << "] "sv
<< "parse_expected_value: Checking initial parse"sv)
bool stolen_value = false; // parsing_should_succeed invokes the functor more than once bool stolen_value = false; // parsing_should_succeed invokes the functor more than once
const auto result = parsing_should_succeed( const auto result = parsing_should_succeed(
@ -310,11 +319,10 @@ inline bool parse_expected_value(
// steal the val for round-trip tests // steal the val for round-trip tests
if (!stolen_value) if (!stolen_value)
{ {
val_parsed = std::move(*nv.as<value_type>()); val_parsed = std::move(*nv.as<value_type>());
stolen_value = true; stolen_value = true;
} }
} });
);
if (!result) if (!result)
return false; return false;
@ -322,7 +330,8 @@ inline bool parse_expected_value(
// check round-tripping // check round-tripping
{ {
INFO("["sv << test_file << ", line "sv << test_line << "] "sv << "parse_expected_value: Checking round-trip"sv) INFO("["sv << test_file << ", line "sv << test_line << "] "sv
<< "parse_expected_value: Checking round-trip"sv)
{ {
std::string str; std::string str;
{ {
@ -333,25 +342,24 @@ inline bool parse_expected_value(
} }
bool value_ok = true; bool value_ok = true;
const auto parse_ok = parsing_should_succeed( const auto parse_ok =
test_file, parsing_should_succeed(test_file,
test_line, test_line,
std::string_view{ str }, std::string_view{ str },
[&](table&& tbl) [&](table&& tbl)
{ {
REQUIRE(tbl.size() == 1); REQUIRE(tbl.size() == 1);
auto nv = tbl["val"sv]; auto nv = tbl["val"sv];
REQUIRE(nv); REQUIRE(nv);
REQUIRE(nv.as<value_type>()); REQUIRE(nv.as<value_type>());
REQUIRE(nv.node()->type() == impl::node_type_of<T>); REQUIRE(nv.node()->type() == impl::node_type_of<T>);
if (value_ok && nv.ref<value_type>() != expected) if (value_ok && nv.ref<value_type>() != expected)
{ {
value_ok = false; value_ok = false;
FORCE_FAIL("Value was not the same after round-tripping"sv); FORCE_FAIL("Value was not the same after round-tripping"sv);
} }
} });
);
if (!parse_ok || value_ok) if (!parse_ok || value_ok)
return false; return false;
@ -377,8 +385,8 @@ namespace Catch
{ {
extern template struct StringMaker<node_view<node>>; extern template struct StringMaker<node_view<node>>;
extern template struct StringMaker<node_view<const node>>; extern template struct StringMaker<node_view<const node>>;
extern template ReusableStringStream& ReusableStringStream::operator << (node_view<node> const&); extern template ReusableStringStream& ReusableStringStream::operator<<(node_view<node> const&);
extern template ReusableStringStream& ReusableStringStream::operator << (node_view<const node> const&); extern template ReusableStringStream& ReusableStringStream::operator<<(node_view<const node> const&);
namespace Detail namespace Detail
{ {
extern template std::string stringify(const node_view<node>&); extern template std::string stringify(const node_view<node>&);

View File

@ -6,24 +6,16 @@
#include "tests.h" #include "tests.h"
using namespace toml::impl; using namespace toml::impl;
using func_type = bool(char32_t)noexcept; using func_type = bool(char32_t) noexcept;
inline constexpr func_type* funcs[] = inline constexpr func_type* funcs[] = {
{
// these must be mutually-exclusive // these must be mutually-exclusive
impl::is_ascii_letter, impl::is_ascii_letter, impl::is_ascii_whitespace, impl::is_ascii_line_break<true>,
impl::is_ascii_whitespace, impl::is_decimal_digit, impl::is_string_delimiter, impl::is_non_ascii_whitespace,
impl::is_ascii_line_break<true>, impl::is_non_ascii_line_break, impl::is_unicode_surrogate,
impl::is_decimal_digit, #if TOML_LANG_UNRELEASED
impl::is_string_delimiter, impl::is_non_ascii_letter, impl::is_non_ascii_number, impl::is_combining_mark,
impl::is_non_ascii_whitespace, #endif
impl::is_non_ascii_line_break,
impl::is_unicode_surrogate,
#if TOML_LANG_UNRELEASED
impl::is_non_ascii_letter,
impl::is_non_ascii_number,
impl::is_combining_mark,
#endif
}; };
template <typename T> template <typename T>
@ -52,7 +44,7 @@ struct codepoint_range
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
constexpr codepoint_range(T first_, U last_) noexcept constexpr codepoint_range(T first_, U last_) noexcept
: first{ static_cast<char32_t>(first_) }, : first{ static_cast<char32_t>(first_) },
last{ static_cast<char32_t>(last_) } last{ static_cast<char32_t>(last_) }
{ {
if (last < first) if (last < first)
std::swap(first, last); std::swap(first, last);
@ -60,9 +52,7 @@ struct codepoint_range
template <typename T> template <typename T>
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
constexpr codepoint_range(T first_) noexcept constexpr codepoint_range(T first_) noexcept : first{ static_cast<char32_t>(first_) }, last{ first }
: first{ static_cast<char32_t>(first_) },
last{ first }
{} {}
}; };
@ -93,53 +83,53 @@ inline bool not_in(func_type* fptr, codepoint_range range) noexcept
TEST_CASE("unicode - is_ascii_letter") TEST_CASE("unicode - is_ascii_letter")
{ {
static constexpr auto fn = is_ascii_letter; static constexpr auto fn = is_ascii_letter;
REQUIRE(not_in(fn, { U'\0', U'@' })); REQUIRE(not_in(fn, { U'\0', U'@' }));
REQUIRE(in_only(fn, { U'A', U'Z' })); REQUIRE(in_only(fn, { U'A', U'Z' }));
REQUIRE(not_in(fn, { U'[', U'`' })); REQUIRE(not_in(fn, { U'[', U'`' }));
REQUIRE(in_only(fn, { U'a', U'z' })); REQUIRE(in_only(fn, { U'a', U'z' }));
REQUIRE(not_in(fn, { U'{', unimax })); REQUIRE(not_in(fn, { U'{', unimax }));
} }
TEST_CASE("unicode - is_ascii_whitespace") TEST_CASE("unicode - is_ascii_whitespace")
{ {
static constexpr auto fn = is_ascii_whitespace; static constexpr auto fn = is_ascii_whitespace;
REQUIRE(not_in(fn, { U'\0', U'\u0008' })); REQUIRE(not_in(fn, { U'\0', U'\u0008' }));
REQUIRE(in_only(fn, U'\t' )); REQUIRE(in_only(fn, U'\t'));
REQUIRE(not_in(fn, { U'\n', U'\u001F' })); REQUIRE(not_in(fn, { U'\n', U'\u001F' }));
REQUIRE(in_only(fn, U' ' )); REQUIRE(in_only(fn, U' '));
REQUIRE(not_in(fn, { U'!', unimax })); REQUIRE(not_in(fn, { U'!', unimax }));
} }
TEST_CASE("unicode - is_ascii_line_break") TEST_CASE("unicode - is_ascii_line_break")
{ {
static constexpr auto fn = is_ascii_line_break<true>; static constexpr auto fn = is_ascii_line_break<true>;
REQUIRE(not_in(fn, { U'\0', U'\t' })); REQUIRE(not_in(fn, { U'\0', U'\t' }));
REQUIRE(in_only(fn, { U'\n', U'\r' })); REQUIRE(in_only(fn, { U'\n', U'\r' }));
REQUIRE(not_in(fn, { U'\u000E', unimax })); REQUIRE(not_in(fn, { U'\u000E', unimax }));
} }
TEST_CASE("unicode - is_binary_digit") TEST_CASE("unicode - is_binary_digit")
{ {
static constexpr auto fn = is_binary_digit; static constexpr auto fn = is_binary_digit;
REQUIRE(not_in(fn, { U'\0', U'/' })); REQUIRE(not_in(fn, { U'\0', U'/' }));
REQUIRE(in(fn, { U'0', U'1' })); REQUIRE(in(fn, { U'0', U'1' }));
REQUIRE(not_in(fn, { U'2', unimax })); REQUIRE(not_in(fn, { U'2', unimax }));
} }
TEST_CASE("unicode - is_octal_digit") TEST_CASE("unicode - is_octal_digit")
{ {
static constexpr auto fn = is_octal_digit; static constexpr auto fn = is_octal_digit;
REQUIRE(not_in(fn, { U'\0', U'/' })); REQUIRE(not_in(fn, { U'\0', U'/' }));
REQUIRE(in(fn, { U'0', U'7' })); REQUIRE(in(fn, { U'0', U'7' }));
REQUIRE(not_in(fn, { U'8', unimax })); REQUIRE(not_in(fn, { U'8', unimax }));
} }
TEST_CASE("unicode - is_decimal_digit") TEST_CASE("unicode - is_decimal_digit")
{ {
static constexpr auto fn = is_decimal_digit; static constexpr auto fn = is_decimal_digit;
REQUIRE(not_in(fn, { U'\0', U'/' })); REQUIRE(not_in(fn, { U'\0', U'/' }));
REQUIRE(in(fn, { U'0', U'9' })); REQUIRE(in(fn, { U'0', U'9' }));
REQUIRE(not_in(fn, { U':', unimax })); REQUIRE(not_in(fn, { U':', unimax }));
} }
TEST_CASE("unicode - hex_to_dec") TEST_CASE("unicode - hex_to_dec")
@ -171,45 +161,45 @@ TEST_CASE("unicode - hex_to_dec")
TEST_CASE("unicode - is_string_delimiter") TEST_CASE("unicode - is_string_delimiter")
{ {
static constexpr auto fn = is_string_delimiter; static constexpr auto fn = is_string_delimiter;
REQUIRE(not_in(fn, { U'\0', U'!' })); REQUIRE(not_in(fn, { U'\0', U'!' }));
REQUIRE(in_only(fn, U'"' )); REQUIRE(in_only(fn, U'"'));
REQUIRE(not_in(fn, { U'#', U'&' })); REQUIRE(not_in(fn, { U'#', U'&' }));
REQUIRE(in_only(fn, U'\'' )); REQUIRE(in_only(fn, U'\''));
REQUIRE(not_in(fn, { U'(', unimax })); REQUIRE(not_in(fn, { U'(', unimax }));
} }
TEST_CASE("unicode - is_non_ascii_whitespace") TEST_CASE("unicode - is_non_ascii_whitespace")
{ {
static constexpr auto fn = is_non_ascii_whitespace; static constexpr auto fn = is_non_ascii_whitespace;
REQUIRE(not_in(fn, { U'\0', U'\u009F' })); REQUIRE(not_in(fn, { U'\0', U'\u009F' }));
REQUIRE(in_only(fn, U'\u00A0' )); REQUIRE(in_only(fn, U'\u00A0'));
REQUIRE(not_in(fn, { U'\u00A1', U'\u167F' })); REQUIRE(not_in(fn, { U'\u00A1', U'\u167F' }));
REQUIRE(in_only(fn, U'\u1680' )); REQUIRE(in_only(fn, U'\u1680'));
REQUIRE(not_in(fn, { U'\u1681', U'\u1FFF' })); REQUIRE(not_in(fn, { U'\u1681', U'\u1FFF' }));
REQUIRE(in_only(fn, { U'\u2000', U'\u200A' })); REQUIRE(in_only(fn, { U'\u2000', U'\u200A' }));
REQUIRE(not_in(fn, { U'\u200B', U'\u202E' })); REQUIRE(not_in(fn, { U'\u200B', U'\u202E' }));
REQUIRE(in_only(fn, U'\u202F' )); REQUIRE(in_only(fn, U'\u202F'));
REQUIRE(not_in(fn, { U'\u2030', U'\u205E' })); REQUIRE(not_in(fn, { U'\u2030', U'\u205E' }));
REQUIRE(in_only(fn, U'\u205F' )); REQUIRE(in_only(fn, U'\u205F'));
REQUIRE(not_in(fn, { U'\u2060', U'\u2FFF' })); REQUIRE(not_in(fn, { U'\u2060', U'\u2FFF' }));
REQUIRE(in_only(fn, U'\u3000' )); REQUIRE(in_only(fn, U'\u3000'));
REQUIRE(not_in(fn, { U'\u3001', unimax })); REQUIRE(not_in(fn, { U'\u3001', unimax }));
} }
TEST_CASE("unicode - is_non_ascii_line_break") TEST_CASE("unicode - is_non_ascii_line_break")
{ {
static constexpr auto fn = is_non_ascii_line_break; static constexpr auto fn = is_non_ascii_line_break;
REQUIRE(not_in(fn, { U'\0', U'\u0084' })); REQUIRE(not_in(fn, { U'\0', U'\u0084' }));
REQUIRE(in_only(fn, U'\u0085' )); REQUIRE(in_only(fn, U'\u0085'));
REQUIRE(not_in(fn, { U'\u0086', U'\u2027' })); REQUIRE(not_in(fn, { U'\u0086', U'\u2027' }));
REQUIRE(in_only(fn, { U'\u2028', U'\u2029' })); REQUIRE(in_only(fn, { U'\u2028', U'\u2029' }));
REQUIRE(not_in(fn, { U'\u202A', unimax })); REQUIRE(not_in(fn, { U'\u202A', unimax }));
} }
TEST_CASE("unicode - is_unicode_surrogate") TEST_CASE("unicode - is_unicode_surrogate")
{ {
static constexpr auto fn = is_unicode_surrogate; static constexpr auto fn = is_unicode_surrogate;
REQUIRE(not_in(fn, { U'\0', 0xD7FFu })); REQUIRE(not_in(fn, { U'\0', 0xD7FFu }));
REQUIRE(in_only(fn, { 0xD800u, 0xDFFF })); REQUIRE(in_only(fn, { 0xD800u, 0xDFFF }));
REQUIRE(not_in(fn, { 0xE000, unimax })); REQUIRE(not_in(fn, { 0xE000, unimax }));
} }

View File

@ -13,77 +13,64 @@ TEST_CASE("user feedback")
{ {
toml::table t1; toml::table t1;
t1.insert_or_assign("bar1", toml::array{ 1, 2, 3 }); t1.insert_or_assign("bar1", toml::array{ 1, 2, 3 });
CHECK(t1 == toml::table{{ CHECK(t1 == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } } } });
{ "bar1"sv, toml::array{ 1, 2, 3 } }
}});
t1.insert_or_assign("foo1", *t1.get("bar1")); t1.insert_or_assign("foo1", *t1.get("bar1"));
CHECK(t1 == toml::table{{ CHECK(t1 == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } }, { "foo1"sv, toml::array{ 1, 2, 3 } } } });
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3 } }
}});
//t1["foo1"] = t1["bar1"]; // does nothing, should this fail to compile? // t1["foo1"] = t1["bar1"]; // does nothing, should this fail to compile?
// - yes - // - yes -
//*t1["foo1"].node() = *t1["bar1"].node(); // compile failure; copying node_view would be a bad thing //*t1["foo1"].node() = *t1["bar1"].node(); // compile failure; copying node_view would be a bad thing
// - correct; copying toml::node directly like that is impossible b.c. it's an abstract base class- // - correct; copying toml::node directly like that is impossible b.c. it's an abstract base class-
toml::array* array1 = t1["foo1"].node()->as_array(); toml::array* array1 = t1["foo1"].node()->as_array();
array1->push_back(4); array1->push_back(4);
CHECK(t1 == toml::table{{ CHECK(t1 == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } }, { "foo1"sv, toml::array{ 1, 2, 3, 4 } } } });
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } }
}});
t1.insert_or_assign("foo3", t1["foo1"]); t1.insert_or_assign("foo3", t1["foo1"]);
CHECK(t1 == toml::table{{ CHECK(t1
{ "bar1"sv, toml::array{ 1, 2, 3 } }, == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } }, { "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } { "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
}});
t1.insert_or_assign("foo2", *t1["foo1"].node()); t1.insert_or_assign("foo2", *t1["foo1"].node());
CHECK(t1 == toml::table{{ CHECK(t1
{ "bar1"sv, toml::array{ 1, 2, 3 } }, == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } }, { "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4 } }, { "foo2"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } { "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
}});
toml::array* array2 = t1["foo2"].node()->as_array(); toml::array* array2 = t1["foo2"].node()->as_array();
array2->push_back("wrench"); array2->push_back("wrench");
CHECK(t1 == toml::table{{ CHECK(t1
{ "bar1"sv, toml::array{ 1, 2, 3 } }, == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } }, { "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } }, { "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } { "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
}});
toml::table t2 = t1; toml::table t2 = t1;
CHECK(t2 == t1); CHECK(t2 == t1);
CHECK(&t2 != &t1); CHECK(&t2 != &t1);
//t2.emplace("bar", toml::array{6, 7}); // fails to compile? not sure what I did wrong // t2.emplace("bar", toml::array{6, 7}); // fails to compile? not sure what I did wrong
// - it should be this: - // - it should be this: -
t2.emplace<toml::array>("bar", 6, 7); t2.emplace<toml::array>("bar", 6, 7);
CHECK(t2 == toml::table{{ CHECK(t2
{ "bar"sv, toml::array{ 6, 7 } }, == toml::table{ { { "bar"sv, toml::array{ 6, 7 } },
{ "bar1"sv, toml::array{ 1, 2, 3 } }, { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } }, { "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } }, { "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } { "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
}});
t2.insert_or_assign("bar2", toml::array{ 6, 7 }); t2.insert_or_assign("bar2", toml::array{ 6, 7 });
CHECK(t2 == toml::table{{ CHECK(t2
{ "bar"sv, toml::array{ 6, 7 } }, == toml::table{ { { "bar"sv, toml::array{ 6, 7 } },
{ "bar1"sv, toml::array{ 1, 2, 3 } }, { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "bar2"sv, toml::array{ 6, 7 } }, { "bar2"sv, toml::array{ 6, 7 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } }, { "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } }, { "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } { "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
}});
} }
SECTION("github/issues/65") // https://github.com/marzer/tomlplusplus/issues/65 SECTION("github/issues/65") // https://github.com/marzer/tomlplusplus/issues/65
@ -94,47 +81,52 @@ TEST_CASE("user feedback")
// - a malformed UTF-8 sequence during a KVP // - a malformed UTF-8 sequence during a KVP
// - overlong numeric literals // - overlong numeric literals
// all should fail to parse, but correctly issue an error (not crash!) // all should fail to parse, but correctly issue an error (not crash!)
parsing_should_fail(FILE_LINE_ARGS, "#\xf1\x63"); parsing_should_fail(FILE_LINE_ARGS, "#\xf1\x63");
parsing_should_fail(FILE_LINE_ARGS, "1= 0x6cA#+\xf1"); parsing_should_fail(FILE_LINE_ARGS, "1= 0x6cA#+\xf1");
parsing_should_fail(FILE_LINE_ARGS, "p=06:06:06#\x0b\xff"); parsing_should_fail(FILE_LINE_ARGS, "p=06:06:06#\x0b\xff");
parsing_should_fail(FILE_LINE_ARGS, "''''d' 't' '+o\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" parsing_should_fail(
FILE_LINE_ARGS,
"''''d' 't' '+o\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
"\x0c\x0c\x0c\x0c\x0c\r\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c\r\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
"\x0c\x0c\x0c\x0c\x0c\x0c\x0cop1\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c\x0c\x0cop1\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c' 'ml'\n\n%\x87" "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c' 'ml'\n\n%\x87");
); parsing_should_fail(
parsing_should_fail(FILE_LINE_ARGS, FILE_LINE_ARGS,
R"(t =[ 9, 2, 1,"r", 9999999999999999999999999999999999999999999999999999999999999995.0 ])" R"(t =[ 9, 2, 1,"r", 9999999999999999999999999999999999999999999999999999999999999995.0 ])");
);
} }
SECTION("github/issues/67") // https://github.com/marzer/tomlplusplus/issues/67 SECTION("github/issues/67") // https://github.com/marzer/tomlplusplus/issues/67
{ {
const auto data = R"(array=["v1", "v2", "v3"])"sv; const auto data = R"(array=["v1", "v2", "v3"])"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table) parsing_should_succeed(FILE_LINE_ARGS,
{ data,
auto arr = table["array"].as_array(); [](auto&& table)
for (auto it = arr->cbegin(); it != arr->cend();) {
if (it->value_or(std::string_view{}) == "v2"sv) auto arr = table["array"].as_array();
it = arr->erase(it); for (auto it = arr->cbegin(); it != arr->cend();)
else if (it->value_or(std::string_view{}) == "v2"sv)
++it; it = arr->erase(it);
CHECK(arr->size() == 2); else
}); ++it;
CHECK(arr->size() == 2);
});
} }
SECTION("github/issues/68") // https://github.com/marzer/tomlplusplus/issues/68 SECTION("github/issues/68") // https://github.com/marzer/tomlplusplus/issues/68
{ {
const auto data = R"(array=["v1", "v2", "v3"])"sv; const auto data = R"(array=["v1", "v2", "v3"])"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table) parsing_should_succeed(FILE_LINE_ARGS,
{ data,
std::stringstream ss; [](auto&& table)
ss << table; {
CHECK(ss.str() == "array = [ 'v1', 'v2', 'v3' ]"sv); std::stringstream ss;
}); ss << table;
CHECK(ss.str() == "array = [ 'v1', 'v2', 'v3' ]"sv);
});
} }
SECTION("github/issues/69") // https://github.com/marzer/tomlplusplus/issues/69 SECTION("github/issues/69") // https://github.com/marzer/tomlplusplus/issues/69
@ -151,15 +143,17 @@ TEST_CASE("user feedback")
[[c]] # array-of-tables with a single, empty table element [[c]] # array-of-tables with a single, empty table element
)"sv; )"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table) parsing_should_succeed(FILE_LINE_ARGS,
{ data,
std::stringstream ss; [](auto&& table)
ss << table; {
CHECK(ss.str() == R"(a = { key = 1 } std::stringstream ss;
ss << table;
CHECK(ss.str() == R"(a = { key = 1 }
b = [] b = []
[[c]])"sv); [[c]])"sv);
}); });
} }
SECTION("github/issues/100") // https://github.com/marzer/tomlplusplus/issues/100 SECTION("github/issues/100") // https://github.com/marzer/tomlplusplus/issues/100
@ -178,22 +172,24 @@ b = []
SECTION("github/issues/112") // https://github.com/marzer/tomlplusplus/issues/112 SECTION("github/issues/112") // https://github.com/marzer/tomlplusplus/issues/112
{ {
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS,
R"(
[a.b.c.d] [a.b.c.d]
u = 6 u = 6
[a] [a]
b.t = 8 b.t = 8
[a.b] # should cause redefinition error here [a.b] # should cause redefinition error here
u = 0 u = 0
)", 6); )",
6);
parsing_should_fail(FILE_LINE_ARGS, R"( parsing_should_fail(FILE_LINE_ARGS,
R"(
[a] [a]
b.t = 8 b.t = 8
[a.b] # should cause redefinition error here [a.b] # should cause redefinition error here
u = 0 u = 0
)", 4); )",
4);
} }
} }

View File

@ -9,47 +9,45 @@ TEST_CASE("using iterators")
constexpr auto data = R"(array=[1,"Foo",true] constexpr auto data = R"(array=[1,"Foo",true]
string="Bar" string="Bar"
number=5)"sv; number=5)"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table) parsing_should_succeed(
{ FILE_LINE_ARGS,
const auto table_begin = table.begin(); data,
const auto table_end = table.end(); [](auto&& table)
auto count_table_lambda = [table_begin, table_end](node_type type) noexcept
{ {
return std::count_if(table_begin, table_end, [type](const auto& pair) noexcept const auto table_begin = table.begin();
const auto table_end = table.end();
auto count_table_lambda = [table_begin, table_end](node_type type) noexcept
{ {
return pair.second.type() == type; return std::count_if(table_begin,
}); table_end,
}; [type](const auto& pair) noexcept { return pair.second.type() == type; });
};
CHECK(std::distance(table_begin, table_end) == 3); CHECK(std::distance(table_begin, table_end) == 3);
CHECK(count_table_lambda(node_type::table) == 0); CHECK(count_table_lambda(node_type::table) == 0);
CHECK(count_table_lambda(node_type::integer) == 1); CHECK(count_table_lambda(node_type::integer) == 1);
CHECK(count_table_lambda(node_type::string) == 1); CHECK(count_table_lambda(node_type::string) == 1);
CHECK(std::next(table_begin, 3) == table_end); CHECK(std::next(table_begin, 3) == table_end);
const auto array_iter = std::find_if(table_begin, table_end, [](const auto& pair) noexcept const auto array_iter =
{ std::find_if(table_begin, table_end, [](const auto& pair) noexcept { return pair.second.is_array(); });
return pair.second.is_array();
REQUIRE(array_iter != table_end);
const auto& array = array_iter->second.as_array();
const auto array_begin = array->begin();
const auto array_end = array->end();
auto count_array_lambda = [array_begin, array_end](node_type type) noexcept {
return std::count_if(array_begin,
array_end,
[type](const auto& node) noexcept { return node.type() == type; });
};
CHECK(std::distance(array_begin, array_end) == 3);
CHECK(count_array_lambda(node_type::table) == 0);
CHECK(count_array_lambda(node_type::integer) == 1);
CHECK(count_array_lambda(node_type::string) == 1);
CHECK(std::next(array_begin, 2) != array_end);
}); });
REQUIRE(array_iter != table_end);
const auto& array = array_iter->second.as_array();
const auto array_begin = array->begin();
const auto array_end = array->end();
auto count_array_lambda = [array_begin, array_end](node_type type) noexcept
{
return std::count_if(array_begin, array_end, [type](const auto& node) noexcept
{
return node.type() == type;
});
};
CHECK(std::distance(array_begin, array_end) == 3);
CHECK(count_array_lambda(node_type::table) == 0);
CHECK(count_array_lambda(node_type::integer) == 1);
CHECK(count_array_lambda(node_type::string) == 1);
CHECK(std::next(array_begin, 2) != array_end);
});
} }

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -108,11 +108,11 @@
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />

View File

@ -24,9 +24,9 @@ TEST_CASE("windows compat")
)"sv; )"sv;
auto res = toml::parse(toml_text, L"kek.toml"); auto res = toml::parse(toml_text, L"kek.toml");
#if !TOML_EXCEPTIONS #if !TOML_EXCEPTIONS
REQUIRE(res.succeeded()); REQUIRE(res.succeeded());
#endif #endif
toml::table& tbl = res; toml::table& tbl = res;
// source paths // source paths

239
toml.hpp
View File

@ -546,13 +546,6 @@
#define TOML_UNREACHABLE TOML_ASSERT(false) #define TOML_UNREACHABLE TOML_ASSERT(false)
#endif #endif
#if defined(__cpp_consteval) && __cpp_consteval >= 201811 && !defined(_MSC_VER)
// https://developercommunity.visualstudio.com/t/Erroneous-C7595-error-with-consteval-in/1404234
#define TOML_CONSTEVAL consteval
#else
#define TOML_CONSTEVAL constexpr
#endif
#ifdef __has_cpp_attribute #ifdef __has_cpp_attribute
#define TOML_HAS_ATTR(...) __has_cpp_attribute(__VA_ARGS__) #define TOML_HAS_ATTR(...) __has_cpp_attribute(__VA_ARGS__)
#else #else
@ -766,7 +759,9 @@
#define TOML_EXTERNAL_LINKAGE inline #define TOML_EXTERNAL_LINKAGE inline
#define TOML_INTERNAL_LINKAGE inline #define TOML_INTERNAL_LINKAGE inline
#else #else
#define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); using namespace toml; namespace #define TOML_ANON_NAMESPACE_START static_assert(TOML_IMPLEMENTATION); \
using namespace toml; \
namespace
#define TOML_ANON_NAMESPACE_END static_assert(true) #define TOML_ANON_NAMESPACE_END static_assert(true)
#define TOML_ANON_NAMESPACE #define TOML_ANON_NAMESPACE
#define TOML_EXTERNAL_LINKAGE #define TOML_EXTERNAL_LINKAGE
@ -1024,15 +1019,6 @@ TOML_NAMESPACE_START
class parse_result; class parse_result;
#endif #endif
TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS TOML_ABI_NAMESPACE_END; // TOML_EXCEPTIONS
TOML_NODISCARD
TOML_ATTR(const)
TOML_ALWAYS_INLINE
TOML_CONSTEVAL
size_t operator"" _sz(unsigned long long n) noexcept
{
return static_cast<size_t>(n);
}
} }
TOML_NAMESPACE_END; TOML_NAMESPACE_END;
@ -4736,14 +4722,13 @@ TOML_NAMESPACE_START
TOML_API TOML_API
array& operator=(array&& rhs) noexcept; array& operator=(array&& rhs) noexcept;
TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0_sz TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
typename ElemType, typename ElemType,
typename... ElemTypes) typename... ElemTypes)
TOML_NODISCARD_CTOR TOML_NODISCARD_CTOR
explicit array(ElemType&& val, ElemTypes&&... vals) explicit array(ElemType&& val, ElemTypes&&... vals)
{ {
elements.reserve(sizeof...(ElemTypes) + 1_sz); elements.reserve(sizeof...(ElemTypes) + 1u);
emplace_back_if_not_empty_view(static_cast<ElemType&&>(val)); emplace_back_if_not_empty_view(static_cast<ElemType&&>(val));
if constexpr (sizeof...(ElemTypes) > 0) if constexpr (sizeof...(ElemTypes) > 0)
{ {
@ -4949,7 +4934,7 @@ TOML_NAMESPACE_START
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin()); const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
preinsertion_resize(start_idx, count); preinsertion_resize(start_idx, count);
size_t i = start_idx; size_t i = start_idx;
for (size_t e = start_idx + count - 1_sz; i < e; i++) for (size_t e = start_idx + count - 1u; i < e; i++)
elements[i].reset(impl::make_node(val)); elements[i].reset(impl::make_node(val));
elements[i].reset(impl::make_node(static_cast<ElemType&&>(val))); elements[i].reset(impl::make_node(static_cast<ElemType&&>(val)));
@ -5119,7 +5104,7 @@ TOML_NAMESPACE_START
if (lhs.size() != rhs.size()) if (lhs.size() != rhs.size())
return false; return false;
if (rhs.size() == 0_sz) if (rhs.size() == 0u)
return true; return true;
size_t i{}; size_t i{};
@ -5501,12 +5486,15 @@ TOML_NAMESPACE_START
} }
TOML_NODISCARD TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype) const noexcept final; bool is_homogeneous(node_type ntype) const noexcept final;
TOML_NODISCARD TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final; bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final;
TOML_NODISCARD TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final; bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final;
template <typename ElemType = void> template <typename ElemType = void>
@ -7528,7 +7516,7 @@ TOML_NAMESPACE_START
std::vector<std::string> key_path_; std::vector<std::string> key_path_;
bool pending_table_separator_ = false; bool pending_table_separator_ = false;
static constexpr size_t line_wrap_cols = 120_sz; static constexpr size_t line_wrap_cols = 120;
TOML_NODISCARD TOML_NODISCARD
TOML_API TOML_API
@ -8057,26 +8045,26 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
void print_to_stream(std::ostream & stream, const toml::date& val) void print_to_stream(std::ostream & stream, const toml::date& val)
{ {
print_integer_leftpad_zeros(stream, val.year, 4_sz); print_integer_leftpad_zeros(stream, val.year, 4u);
stream.put('-'); stream.put('-');
print_integer_leftpad_zeros(stream, val.month, 2_sz); print_integer_leftpad_zeros(stream, val.month, 2u);
stream.put('-'); stream.put('-');
print_integer_leftpad_zeros(stream, val.day, 2_sz); print_integer_leftpad_zeros(stream, val.day, 2u);
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
void print_to_stream(std::ostream & stream, const toml::time& val) void print_to_stream(std::ostream & stream, const toml::time& val)
{ {
print_integer_leftpad_zeros(stream, val.hour, 2_sz); print_integer_leftpad_zeros(stream, val.hour, 2u);
stream.put(':'); stream.put(':');
print_integer_leftpad_zeros(stream, val.minute, 2_sz); print_integer_leftpad_zeros(stream, val.minute, 2u);
stream.put(':'); stream.put(':');
print_integer_leftpad_zeros(stream, val.second, 2_sz); print_integer_leftpad_zeros(stream, val.second, 2u);
if (val.nanosecond && val.nanosecond <= 999999999u) if (val.nanosecond && val.nanosecond <= 999999999u)
{ {
stream.put('.'); stream.put('.');
auto ns = val.nanosecond; auto ns = val.nanosecond;
size_t digits = 9_sz; size_t digits = 9u;
while (ns % 10u == 0u) while (ns % 10u == 0u)
{ {
ns /= 10u; ns /= 10u;
@ -8106,13 +8094,13 @@ TOML_IMPL_NAMESPACE_START
const auto hours = mins / 60; const auto hours = mins / 60;
if (hours) if (hours)
{ {
print_integer_leftpad_zeros(stream, static_cast<unsigned int>(hours), 2_sz); print_integer_leftpad_zeros(stream, static_cast<unsigned int>(hours), 2u);
mins -= hours * 60; mins -= hours * 60;
} }
else else
print_to_stream(stream, "00"sv); print_to_stream(stream, "00"sv);
stream.put(':'); stream.put(':');
print_integer_leftpad_zeros(stream, static_cast<unsigned int>(mins), 2_sz); print_integer_leftpad_zeros(stream, static_cast<unsigned int>(mins), 2u);
} }
TOML_EXTERNAL_LINKAGE TOML_EXTERNAL_LINKAGE
@ -8476,14 +8464,14 @@ TOML_NAMESPACE_START
void array::preinsertion_resize(size_t idx, size_t count) noexcept void array::preinsertion_resize(size_t idx, size_t count) noexcept
{ {
TOML_ASSERT(idx <= elements.size()); TOML_ASSERT(idx <= elements.size());
TOML_ASSERT(count >= 1_sz); TOML_ASSERT(count >= 1u);
const auto old_size = elements.size(); const auto old_size = elements.size();
const auto new_size = old_size + count; const auto new_size = old_size + count;
const auto inserting_at_end = idx == old_size; const auto inserting_at_end = idx == old_size;
elements.resize(new_size); elements.resize(new_size);
if (!inserting_at_end) if (!inserting_at_end)
{ {
for (size_t left = old_size, right = new_size - 1_sz; left-- > idx; right--) for (size_t left = old_size, right = new_size - 1u; left-- > idx; right--)
elements[right] = std::move(elements[left]); elements[right] = std::move(elements[left]);
} }
} }
@ -8547,7 +8535,7 @@ TOML_NAMESPACE_START
for (size_t i = 0, e = elements.size(); i < e; i++) for (size_t i = 0, e = elements.size(); i < e; i++)
{ {
auto arr = elements[i]->as_array(); auto arr = elements[i]->as_array();
leaves += arr ? arr->total_leaf_count() : 1_sz; leaves += arr ? arr->total_leaf_count() : size_t{ 1 };
} }
return leaves; return leaves;
} }
@ -8577,14 +8565,14 @@ TOML_NAMESPACE_START
bool requires_flattening = false; bool requires_flattening = false;
size_t size_after_flattening = elements.size(); size_t size_after_flattening = elements.size();
for (size_t i = elements.size(); i-- > 0_sz;) for (size_t i = elements.size(); i-- > 0u;)
{ {
auto arr = elements[i]->as_array(); auto arr = elements[i]->as_array();
if (!arr) if (!arr)
continue; continue;
size_after_flattening--; // discount the array itself size_after_flattening--; // discount the array itself
const auto leaf_count = arr->total_leaf_count(); const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 0_sz) if (leaf_count > 0u)
{ {
requires_flattening = true; requires_flattening = true;
size_after_flattening += leaf_count; size_after_flattening += leaf_count;
@ -8610,8 +8598,8 @@ TOML_NAMESPACE_START
std::unique_ptr<node> arr_storage = std::move(elements[i]); std::unique_ptr<node> arr_storage = std::move(elements[i]);
const auto leaf_count = arr->total_leaf_count(); const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 1_sz) if (leaf_count > 1u)
preinsertion_resize(i + 1_sz, leaf_count - 1_sz); preinsertion_resize(i + 1u, leaf_count - 1u);
flatten_child(std::move(*arr), i); // increments i flatten_child(std::move(*arr), i); // increments i
} }
@ -8814,7 +8802,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char> template <typename Char>
class utf8_byte_stream<std::basic_string_view<Char>> class utf8_byte_stream<std::basic_string_view<Char>>
{ {
static_assert(sizeof(Char) == 1_sz); static_assert(sizeof(Char) == 1);
private: private:
std::basic_string_view<Char> source_; std::basic_string_view<Char> source_;
@ -8828,20 +8816,20 @@ TOML_ANON_NAMESPACE_START
// trim trailing nulls // trim trailing nulls
const size_t initial_len = source_.length(); const size_t initial_len = source_.length();
size_t actual_len = initial_len; size_t actual_len = initial_len;
for (size_t i = actual_len; i-- > 0_sz;) for (size_t i = actual_len; i-- > 0u;)
{ {
if (source_[i] != Char{}) // not '\0' if (source_[i] != Char{}) // not '\0'
{ {
actual_len = i + 1_sz; actual_len = i + 1u;
break; break;
} }
} }
if (initial_len != actual_len) if (initial_len != actual_len)
source_ = source_.substr(0_sz, actual_len); source_ = source_.substr(0u, actual_len);
// skip bom // skip bom
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source_.data(), 3_sz) == 0) if (actual_len >= 3u && memcmp(utf8_byte_order_mark.data(), source_.data(), 3u) == 0)
position_ += 3_sz; position_ += 3u;
} }
TOML_NODISCARD TOML_NODISCARD
@ -8877,7 +8865,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char> template <typename Char>
class utf8_byte_stream<std::basic_istream<Char>> class utf8_byte_stream<std::basic_istream<Char>>
{ {
static_assert(sizeof(Char) == 1_sz); static_assert(sizeof(Char) == 1);
private: private:
std::basic_istream<Char>* source_; std::basic_istream<Char>* source_;
@ -8893,7 +8881,7 @@ TOML_ANON_NAMESPACE_START
const auto initial_pos = source_->tellg(); const auto initial_pos = source_->tellg();
Char bom[3]; Char bom[3];
source_->read(bom, 3); source_->read(bom, 3);
if (source_->bad() || (source_->gcount() == 3 && memcmp(utf8_byte_order_mark.data(), bom, 3_sz) == 0)) if (source_->bad() || (source_->gcount() == 3 && memcmp(utf8_byte_order_mark.data(), bom, 3u) == 0))
return; return;
source_->clear(); source_->clear();
@ -8941,7 +8929,7 @@ TOML_ANON_NAMESPACE_START
TOML_NODISCARD TOML_NODISCARD
std::string_view as_view() const noexcept std::string_view as_view() const noexcept
{ {
return bytes[3] ? std::string_view{ bytes, 4_sz } : std::string_view{ bytes }; return bytes[3] ? std::string_view{ bytes, 4u } : std::string_view{ bytes };
} }
TOML_NODISCARD TOML_NODISCARD
@ -9032,7 +9020,7 @@ TOML_ANON_NAMESPACE_START
{ {
TOML_ERROR_CHECK; TOML_ERROR_CHECK;
auto& prev = codepoints_[(cp_idx_ - 1_sz) % 2_sz]; auto& prev = codepoints_[(cp_idx_ - 1u) % 2u];
if (stream_.eof()) if (stream_.eof())
return nullptr; return nullptr;
@ -9096,7 +9084,7 @@ TOML_ANON_NAMESPACE_START
TOML_ERROR_CHECK; TOML_ERROR_CHECK;
auto& current = codepoints_[cp_idx_ % 2_sz]; auto& current = codepoints_[cp_idx_ % 2u];
current.bytes[current_byte_count_++] = static_cast<char>(next_byte); current.bytes[current_byte_count_++] = static_cast<char>(next_byte);
if (decoder_.has_code_point()) if (decoder_.has_code_point())
{ {
@ -9725,7 +9713,7 @@ TOML_IMPL_NAMESPACE_START
TOML_NEVER_INLINE TOML_NEVER_INLINE
void set_error_at(source_position pos, const T&... reason) const TOML_MAY_THROW void set_error_at(source_position pos, const T&... reason) const TOML_MAY_THROW
{ {
static_assert(sizeof...(T) > 0_sz); static_assert(sizeof...(T) > 0);
#if !TOML_EXCEPTIONS #if !TOML_EXCEPTIONS
if (err) if (err)
return; return;
@ -9750,7 +9738,7 @@ TOML_IMPL_NAMESPACE_START
set_error_at(current_position(1), reason...); set_error_at(current_position(1), reason...);
} }
void go_back(size_t count = 1_sz) noexcept void go_back(size_t count = 1) noexcept
{ {
return_if_error(); return_if_error();
assert_or_assume(count); assert_or_assume(count);
@ -9793,7 +9781,7 @@ TOML_IMPL_NAMESPACE_START
recording_buffer.append(cp->as_view()); recording_buffer.append(cp->as_view());
} }
void stop_recording(size_t pop_bytes = 0_sz) noexcept void stop_recording(size_t pop_bytes = 0) noexcept
{ {
return_if_error(); return_if_error();
@ -9802,7 +9790,7 @@ TOML_IMPL_NAMESPACE_START
{ {
if (pop_bytes >= recording_buffer.length()) if (pop_bytes >= recording_buffer.length())
recording_buffer.clear(); recording_buffer.clear();
else if (pop_bytes == 1_sz) else if (pop_bytes == 1u)
recording_buffer.pop_back(); recording_buffer.pop_back();
else else
recording_buffer.erase(recording_buffer.begin() recording_buffer.erase(recording_buffer.begin()
@ -10081,7 +10069,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line) if (multi_line)
{ {
size_t lookaheads = {}; size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz; size_t consecutive_delimiters = 1;
do do
{ {
advance_and_return_if_error({}); advance_and_return_if_error({});
@ -10091,30 +10079,30 @@ TOML_IMPL_NAMESPACE_START
else else
break; break;
} }
while (lookaheads < 4_sz); while (lookaheads < 4u);
switch (consecutive_delimiters) switch (consecutive_delimiters)
{ {
// """ " (one quote somewhere in a ML string) // """ " (one quote somewhere in a ML string)
case 1_sz: case 1:
str += '"'; str += '"';
skipping_whitespace = false; skipping_whitespace = false;
continue; continue;
// """ "" (two quotes somewhere in a ML string) // """ "" (two quotes somewhere in a ML string)
case 2_sz: case 2:
str.append("\"\""sv); str.append("\"\""sv);
skipping_whitespace = false; skipping_whitespace = false;
continue; continue;
// """ """ (the end of the string) // """ """ (the end of the string)
case 3_sz: return str; case 3: return str;
// """ """" (one at the end of the string) // """ """" (one at the end of the string)
case 4_sz: str += '"'; return str; case 4: str += '"'; return str;
// """ """"" (two quotes at the end of the string) // """ """"" (two quotes at the end of the string)
case 5_sz: case 5:
str.append("\"\""sv); str.append("\"\""sv);
advance_and_return_if_error({}); // skip the last '"' advance_and_return_if_error({}); // skip the last '"'
return str; return str;
@ -10210,7 +10198,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line) if (multi_line)
{ {
size_t lookaheads = {}; size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz; size_t consecutive_delimiters = 1;
do do
{ {
advance_and_return_if_error({}); advance_and_return_if_error({});
@ -10220,24 +10208,24 @@ TOML_IMPL_NAMESPACE_START
else else
break; break;
} }
while (lookaheads < 4_sz); while (lookaheads < 4u);
switch (consecutive_delimiters) switch (consecutive_delimiters)
{ {
// ''' ' (one quote somewhere in a ML string) // ''' ' (one quote somewhere in a ML string)
case 1_sz: str += '\''; continue; case 1: str += '\''; continue;
// ''' '' (two quotes somewhere in a ML string) // ''' '' (two quotes somewhere in a ML string)
case 2_sz: str.append("''"sv); continue; case 2: str.append("''"sv); continue;
// ''' ''' (the end of the string) // ''' ''' (the end of the string)
case 3_sz: return str; case 3: return str;
// ''' '''' (one at the end of the string) // ''' '''' (one at the end of the string)
case 4_sz: str += '\''; return str; case 4: str += '\''; return str;
// ''' ''''' (two quotes at the end of the string) // ''' ''''' (two quotes at the end of the string)
case 5_sz: case 5:
str.append("''"sv); str.append("''"sv);
advance_and_return_if_error({}); // skip the last ' advance_and_return_if_error({}); // skip the last '
return str; return str;
@ -10320,7 +10308,7 @@ TOML_IMPL_NAMESPACE_START
{ {
// step back two characters so that the current // step back two characters so that the current
// character is the string delimiter // character is the string delimiter
go_back(2_sz); go_back(2u);
return { first == U'\'' ? parse_literal_string(false) : parse_basic_string(false), false }; return { first == U'\'' ? parse_literal_string(false) : parse_basic_string(false), false };
} }
@ -10630,7 +10618,7 @@ TOML_IMPL_NAMESPACE_START
set_error_and_return_default("expected exponent digit or sign, saw '"sv, to_sv(*cp), "'"sv); set_error_and_return_default("expected exponent digit or sign, saw '"sv, to_sv(*cp), "'"sv);
// 0x.p-0 (mantissa is just '.') // 0x.p-0 (mantissa is just '.')
else if (fragments[0].length == 0_sz && fragments[1].length == 0_sz) else if (fragments[0].length == 0u && fragments[1].length == 0u)
set_error_and_return_default("expected hexadecimal digit, saw '"sv, to_sv(*cp), "'"sv); set_error_and_return_default("expected hexadecimal digit, saw '"sv, to_sv(*cp), "'"sv);
else else
@ -10665,7 +10653,7 @@ TOML_IMPL_NAMESPACE_START
} }
// sanity-check ending state // sanity-check ending state
if (current_fragment != fragments + 2 || current_fragment->length == 0_sz) if (current_fragment != fragments + 2 || current_fragment->length == 0u)
{ {
set_error_and_return_if_eof({}); set_error_and_return_if_eof({});
set_error_and_return_default("missing exponent"sv); set_error_and_return_default("missing exponent"sv);
@ -10696,7 +10684,7 @@ TOML_IMPL_NAMESPACE_START
// calculate value // calculate value
auto place = 1u; auto place = 1u;
for (size_t i = 0; i < f.length - 1_sz; i++) for (size_t i = 0; i < f.length - 1u; i++)
place *= base; place *= base;
uint32_t val{}; uint32_t val{};
while (place) while (place)
@ -10810,7 +10798,7 @@ TOML_IMPL_NAMESPACE_START
} }
// single digits can be converted trivially // single digits can be converted trivially
if (length == 1_sz) if (length == 1u)
{ {
if constexpr (base == 16) if constexpr (base == 16)
return static_cast<int64_t>(hex_to_dec(chars[0])); return static_cast<int64_t>(hex_to_dec(chars[0]));
@ -10860,7 +10848,7 @@ TOML_IMPL_NAMESPACE_START
// "YYYY" // "YYYY"
uint32_t digits[4]; uint32_t digits[4];
if (!consume_digit_sequence(digits, 4_sz)) if (!consume_digit_sequence(digits, 4u))
set_error_and_return_default("expected 4-digit year, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 4-digit year, saw '"sv, to_sv(cp), "'"sv);
const auto year = digits[3] + digits[2] * 10u + digits[1] * 100u + digits[0] * 1000u; const auto year = digits[3] + digits[2] * 10u + digits[1] * 100u + digits[0] * 1000u;
const auto is_leap_year = (year % 4u == 0u) && ((year % 100u != 0u) || (year % 400u == 0u)); const auto is_leap_year = (year % 4u == 0u) && ((year % 100u != 0u) || (year % 400u == 0u));
@ -10872,7 +10860,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "MM" // "MM"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit month, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit month, saw '"sv, to_sv(cp), "'"sv);
const auto month = digits[1] + digits[0] * 10u; const auto month = digits[1] + digits[0] * 10u;
if (month == 0u || month > 12u) if (month == 0u || month > 12u)
@ -10889,7 +10877,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "DD" // "DD"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit day, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit day, saw '"sv, to_sv(cp), "'"sv);
const auto day = digits[1] + digits[0] * 10u; const auto day = digits[1] + digits[0] * 10u;
if (day == 0u || day > max_days_in_month) if (day == 0u || day > max_days_in_month)
@ -10912,11 +10900,11 @@ TOML_IMPL_NAMESPACE_START
assert_or_assume(is_decimal_digit(*cp)); assert_or_assume(is_decimal_digit(*cp));
push_parse_scope("time"sv); push_parse_scope("time"sv);
static constexpr auto max_digits = 9_sz; static constexpr size_t max_digits = 9;
uint32_t digits[max_digits]; uint32_t digits[max_digits];
// "HH" // "HH"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv);
const auto hour = digits[1] + digits[0] * 10u; const auto hour = digits[1] + digits[0] * 10u;
if (hour > 23u) if (hour > 23u)
@ -10930,7 +10918,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "MM" // "MM"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv);
const auto minute = digits[1] + digits[0] * 10u; const auto minute = digits[1] + digits[0] * 10u;
if (minute > 59u) if (minute > 59u)
@ -10954,7 +10942,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "SS" // "SS"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit second, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit second, saw '"sv, to_sv(cp), "'"sv);
const auto second = digits[1] + digits[0] * 10u; const auto second = digits[1] + digits[0] * 10u;
if (second > 59u) if (second > 59u)
@ -10970,7 +10958,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "FFFFFFFFF" // "FFFFFFFFF"
auto digit_count = consume_variable_length_digit_sequence(digits, max_digits); size_t digit_count = consume_variable_length_digit_sequence(digits, max_digits);
if (!digit_count) if (!digit_count)
{ {
set_error_and_return_if_eof({}); set_error_and_return_if_eof({});
@ -10987,7 +10975,7 @@ TOML_IMPL_NAMESPACE_START
uint32_t value = 0u; uint32_t value = 0u;
uint32_t place = 1u; uint32_t place = 1u;
for (auto i = digit_count; i-- > 0_sz;) for (auto i = digit_count; i-- > 0u;)
{ {
value += digits[i] * place; value += digits[i] * place;
place *= 10u; place *= 10u;
@ -11039,7 +11027,7 @@ TOML_IMPL_NAMESPACE_START
// "HH" // "HH"
int digits[2]; int digits[2];
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv);
const auto hour = digits[1] + digits[0] * 10; const auto hour = digits[1] + digits[0] * 10;
if (hour > 23) if (hour > 23)
@ -11053,7 +11041,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({}); advance_and_return_if_error_or_eof({});
// "MM" // "MM"
if (!consume_digit_sequence(digits, 2_sz)) if (!consume_digit_sequence(digits, 2u))
set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv); set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv);
const auto minute = digits[1] + digits[0] * 10; const auto minute = digits[1] + digits[0] * 10;
if (minute > 59) if (minute > 59)
@ -11223,19 +11211,19 @@ TOML_IMPL_NAMESPACE_START
switch (static_cast<char32_t>(c | 32u)) switch (static_cast<char32_t>(c | 32u))
{ {
case U'b': case U'b':
if (char_count == 2_sz && has_any(begins_zero)) if (char_count == 2u && has_any(begins_zero))
add_trait(has_b); add_trait(has_b);
break; break;
case U'e': case U'e':
if (char_count > 1_sz if (char_count > 1u
&& has_none(has_b | has_o | has_p | has_t | has_x | has_z | has_colon) && has_none(has_b | has_o | has_p | has_t | has_x | has_z | has_colon)
&& (has_none(has_plus | has_minus) || has_any(begins_sign))) && (has_none(has_plus | has_minus) || has_any(begins_sign)))
add_trait(has_e); add_trait(has_e);
break; break;
case U'o': case U'o':
if (char_count == 2_sz && has_any(begins_zero)) if (char_count == 2u && has_any(begins_zero))
add_trait(has_o); add_trait(has_o);
break; break;
@ -11245,8 +11233,8 @@ TOML_IMPL_NAMESPACE_START
break; break;
case U'x': case U'x':
if ((char_count == 2_sz && has_any(begins_zero)) if ((char_count == 2u && has_any(begins_zero))
|| (char_count == 3_sz && has_any(begins_sign) && chars[1] == U'0')) || (char_count == 3u && has_any(begins_sign) && chars[1] == U'0'))
add_trait(has_x); add_trait(has_x);
break; break;
@ -11278,7 +11266,7 @@ TOML_IMPL_NAMESPACE_START
return_if_error({}); return_if_error({});
// force further scanning if this could have been a date-time with a space instead of a T // force further scanning if this could have been a date-time with a space instead of a T
if (char_count == 10_sz && traits == (bdigit_msk | has_minus) && chars[4] == U'-' && chars[7] == U'-' if (char_count == 10u && traits == (bdigit_msk | has_minus) && chars[4] == U'-' && chars[7] == U'-'
&& !is_eof() && *cp == U' ') && !is_eof() && *cp == U' ')
{ {
const auto pre_advance_count = advance_count; const auto pre_advance_count = advance_count;
@ -11291,7 +11279,7 @@ TOML_IMPL_NAMESPACE_START
go_back(advance_count - pre_advance_count); go_back(advance_count - pre_advance_count);
advance_count = pre_advance_count; advance_count = pre_advance_count;
traits = pre_scan_traits; traits = pre_scan_traits;
char_count = 10_sz; char_count = 10u;
}; };
advance_and_return_if_error({}); advance_and_return_if_error({});
@ -11309,19 +11297,19 @@ TOML_IMPL_NAMESPACE_START
scan(); scan();
return_if_error({}); return_if_error({});
if (char_count == 12_sz) if (char_count == 12u)
backpedal(); backpedal();
} }
} }
// set the reader back to where we started // set the reader back to where we started
go_back(advance_count); go_back(advance_count);
if (char_count < utf8_buffered_reader::max_history_length - 1_sz) if (char_count < utf8_buffered_reader::max_history_length - 1u)
chars[char_count] = U'\0'; chars[char_count] = U'\0';
// if after scanning ahead we still only have one value character, // if after scanning ahead we still only have one value character,
// the only valid value type is an integer. // the only valid value type is an integer.
if (char_count == 1_sz) if (char_count == 1u)
{ {
if (has_any(begins_zero | begins_digit)) if (has_any(begins_zero | begins_digit))
{ {
@ -11338,7 +11326,7 @@ TOML_IMPL_NAMESPACE_START
// now things that can be identified from two or more characters // now things that can be identified from two or more characters
return_if_error({}); return_if_error({});
assert_or_assume(char_count >= 2_sz); assert_or_assume(char_count >= 2u);
// do some 'fuzzy matching' where there's no ambiguity, since that allows the specific // do some 'fuzzy matching' where there's no ambiguity, since that allows the specific
// typed parse functions to take over and show better diagnostics if there's an issue // typed parse functions to take over and show better diagnostics if there's an issue
@ -11364,7 +11352,7 @@ TOML_IMPL_NAMESPACE_START
else if (has_any(begins_sign)) else if (has_any(begins_sign))
{ {
// single-digit signed integers // single-digit signed integers
if (char_count == 2_sz && has_any(has_digits)) if (char_count == 2u && has_any(has_digits))
{ {
val = new value{ static_cast<int64_t>(chars[1] - U'0') * (chars[0] == U'-' ? -1LL : 1LL) }; val = new value{ static_cast<int64_t>(chars[1] - U'0') * (chars[0] == U'-' ? -1LL : 1LL) };
advance(); // skip the sign advance(); // skip the sign
@ -11670,7 +11658,7 @@ TOML_IMPL_NAMESPACE_START
// get the key // get the key
start_recording(); start_recording();
auto key = parse_key(); auto key = parse_key();
stop_recording(1_sz); stop_recording(1u);
// skip past any whitespace that followed the key // skip past any whitespace that followed the key
consume_leading_whitespace(); consume_leading_whitespace();
@ -11736,7 +11724,7 @@ TOML_IMPL_NAMESPACE_START
// get the actual key // get the actual key
start_recording(); start_recording();
key = parse_key(); key = parse_key();
stop_recording(1_sz); stop_recording(1u);
return_if_error({}); return_if_error({});
// skip past any whitespace that followed the key // skip past any whitespace that followed the key
@ -11765,7 +11753,7 @@ TOML_IMPL_NAMESPACE_START
// check if each parent is a table/table array, or can be created implicitly as a table. // check if each parent is a table/table array, or can be created implicitly as a table.
auto parent = &root; auto parent = &root;
for (size_t i = 0; i < key.segments.size() - 1_sz; i++) for (size_t i = 0; i < key.segments.size() - 1u; i++)
{ {
auto child = parent->get(key.segments[i]); auto child = parent->get(key.segments[i]);
if (!child) if (!child)
@ -11893,13 +11881,13 @@ TOML_IMPL_NAMESPACE_START
auto kvp = parse_key_value_pair(); auto kvp = parse_key_value_pair();
return_if_error(); return_if_error();
TOML_ASSERT(kvp.key.segments.size() >= 1_sz); TOML_ASSERT(kvp.key.segments.size() >= 1u);
// if it's a dotted kvp we need to spawn the sub-tables if necessary, // if it's a dotted kvp we need to spawn the sub-tables if necessary,
// and set the target table to the second-to-last one in the chain // and set the target table to the second-to-last one in the chain
if (kvp.key.segments.size() > 1_sz) if (kvp.key.segments.size() > 1u)
{ {
for (size_t i = 0; i < kvp.key.segments.size() - 1_sz; i++) for (size_t i = 0; i < kvp.key.segments.size() - 1u; i++)
{ {
auto child = tab->get(kvp.key.segments[i]); auto child = tab->get(kvp.key.segments[i]);
if (!child) if (!child)
@ -12279,7 +12267,7 @@ TOML_ANON_NAMESPACE_START
// open file with a custom-sized stack buffer // open file with a custom-sized stack buffer
std::ifstream file; std::ifstream file;
char file_buffer[sizeof(void*) * 1024_sz]; char file_buffer[sizeof(void*) * 1024u];
file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer)); file.rdbuf()->pubsetbuf(file_buffer, sizeof(file_buffer));
file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate); file.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
if (!file.is_open()) if (!file.is_open())
@ -12657,7 +12645,7 @@ TOML_NAMESPACE_START
if (requires_quotes) if (requires_quotes)
{ {
std::string s; std::string s;
s.reserve(str.length() + 2_sz); s.reserve(str.length() + 2u);
s += '"'; s += '"';
for (auto c : str) for (auto c : str)
{ {
@ -12687,11 +12675,11 @@ TOML_NAMESPACE_START
{ {
auto& n = *reinterpret_cast<const table*>(&node); auto& n = *reinterpret_cast<const table*>(&node);
if (n.empty()) if (n.empty())
return 2_sz; // "{}" return 2u; // "{}"
size_t weight = 3_sz; // "{ }" size_t weight = 3u; // "{ }"
for (auto&& [k, v] : n) for (auto&& [k, v] : n)
{ {
weight += k.length() + count_inline_columns(v) + 2_sz; // + ", " weight += k.length() + count_inline_columns(v) + 2u; // + ", "
if (weight >= line_wrap_cols) if (weight >= line_wrap_cols)
break; break;
} }
@ -12702,11 +12690,11 @@ TOML_NAMESPACE_START
{ {
auto& n = *reinterpret_cast<const array*>(&node); auto& n = *reinterpret_cast<const array*>(&node);
if (n.empty()) if (n.empty())
return 2_sz; // "[]" return 2u; // "[]"
size_t weight = 3_sz; // "[ ]" size_t weight = 3u; // "[ ]"
for (auto& elem : n) for (auto& elem : n)
{ {
weight += count_inline_columns(elem) + 2_sz; // + ", " weight += count_inline_columns(elem) + 2u; // + ", "
if (weight >= line_wrap_cols) if (weight >= line_wrap_cols)
break; break;
} }
@ -12716,7 +12704,7 @@ TOML_NAMESPACE_START
case node_type::string: case node_type::string:
{ {
auto& n = *reinterpret_cast<const value<std::string>*>(&node); auto& n = *reinterpret_cast<const value<std::string>*>(&node);
return n.get().length() + 2_sz; // + "" return n.get().length() + 2u; // + ""
} }
case node_type::integer: case node_type::integer:
@ -12724,14 +12712,14 @@ TOML_NAMESPACE_START
auto& n = *reinterpret_cast<const value<int64_t>*>(&node); auto& n = *reinterpret_cast<const value<int64_t>*>(&node);
auto v = n.get(); auto v = n.get();
if (!v) if (!v)
return 1_sz; return 1u;
size_t weight = {}; size_t weight = {};
if (v < 0) if (v < 0)
{ {
weight += 1; weight += 1u;
v *= -1; v *= -1;
} }
return weight + static_cast<size_t>(log10(static_cast<double>(v))) + 1_sz; return weight + static_cast<size_t>(log10(static_cast<double>(v))) + 1u;
} }
case node_type::floating_point: case node_type::floating_point:
@ -12739,21 +12727,21 @@ TOML_NAMESPACE_START
auto& n = *reinterpret_cast<const value<double>*>(&node); auto& n = *reinterpret_cast<const value<double>*>(&node);
auto v = n.get(); auto v = n.get();
if (v == 0.0) if (v == 0.0)
return 3_sz; // "0.0" return 3u; // "0.0"
size_t weight = 2_sz; // ".0" size_t weight = 2u; // ".0"
if (v < 0.0) if (v < 0.0)
{ {
weight += 1; weight += 1u;
v *= -1.0; v *= -1.0;
} }
return weight + static_cast<size_t>(log10(v)) + 1_sz; return weight + static_cast<size_t>(log10(v)) + 1u;
break; break;
} }
case node_type::boolean: return 5_sz; case node_type::boolean: return 5u;
case node_type::date: [[fallthrough]]; case node_type::date: [[fallthrough]];
case node_type::time: return 10_sz; case node_type::time: return 10u;
case node_type::date_time: return 30_sz; case node_type::date_time: return 30u;
case node_type::none: TOML_UNREACHABLE; case node_type::none: TOML_UNREACHABLE;
default: TOML_UNREACHABLE; default: TOML_UNREACHABLE;
} }
@ -12879,7 +12867,7 @@ TOML_NAMESPACE_START
for (size_t i = 0; i < arr.size(); i++) for (size_t i = 0; i < arr.size(); i++)
{ {
if (i > 0_sz) if (i > 0u)
{ {
impl::print_to_stream(base::stream(), ','); impl::print_to_stream(base::stream(), ',');
if (!multiline) if (!multiline)
@ -12921,7 +12909,7 @@ TOML_NAMESPACE_START
static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept
{ {
auto arr = nde.as_array(); auto arr = nde.as_array();
return arr && arr->is_array_of_tables() && !arr->template get_as<table>(0_sz)->is_inline(); return arr && arr->is_array_of_tables() && !arr->template get_as<table>(0u)->is_inline();
}; };
// values, arrays, and inline tables/table arrays // values, arrays, and inline tables/table arrays
@ -12984,7 +12972,7 @@ TOML_NAMESPACE_START
} }
} }
bool skip_self = false; bool skip_self = false;
if (child_value_count == 0_sz && (child_table_count > 0_sz || child_table_array_count > 0_sz)) if (child_value_count == 0u && (child_table_count > 0u || child_table_array_count > 0u))
skip_self = true; skip_self = true;
key_path_.push_back(make_key_segment(k)); key_path_.push_back(make_key_segment(k));
@ -13121,7 +13109,7 @@ TOML_NAMESPACE_START
base::increase_indent(); base::increase_indent();
for (size_t i = 0; i < arr.size(); i++) for (size_t i = 0; i < arr.size(); i++)
{ {
if (i > 0_sz) if (i > 0u)
impl::print_to_stream(base::stream(), ','); impl::print_to_stream(base::stream(), ',');
base::print_newline(true); base::print_newline(true);
base::print_indent(); base::print_indent();
@ -13186,7 +13174,6 @@ TOML_POP_WARNINGS;
#undef TOML_COMPILER_EXCEPTIONS #undef TOML_COMPILER_EXCEPTIONS
#undef TOML_CONCAT #undef TOML_CONCAT
#undef TOML_CONCAT_1 #undef TOML_CONCAT_1
#undef TOML_CONSTEVAL
#undef TOML_CONSTRAINED_TEMPLATE #undef TOML_CONSTRAINED_TEMPLATE
#undef TOML_CPP #undef TOML_CPP
#undef TOML_DISABLE_ARITHMETIC_WARNINGS #undef TOML_DISABLE_ARITHMETIC_WARNINGS

View File

@ -10,6 +10,7 @@ REM ----------------------------------------------------------------------------
CALL :RunClangFormatOnDirectories ^ CALL :RunClangFormatOnDirectories ^
include\toml++ ^ include\toml++ ^
include\toml++\impl ^ include\toml++\impl ^
tests ^
examples examples
GOTO FINISH GOTO FINISH

View File

@ -412,16 +412,17 @@ def write_test_file(name, all_tests):
write = lambda txt,end='\n': print(txt, file=test_file, end=end) write = lambda txt,end='\n': print(txt, file=test_file, end=end)
# preamble # preamble
write('// This file is a part of toml++ and is subject to the the terms of the MIT license.') write(r'// This file is a part of toml++ and is subject to the the terms of the MIT license.')
write('// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>') write(r'// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>')
write('// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.') write(r'// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.')
write('// SPDX-License-Identifier: MIT') write(r'// SPDX-License-Identifier: MIT')
write('//-----') write(r'//-----')
write('// this file was generated by generate_conformance_tests.py - do not modify it directly') write(r'// this file was generated by generate_conformance_tests.py - do not modify it directly')
write('') write(r'// clang-format off')
write('#include "tests.h"') write(r'')
write('using namespace toml::impl;') write(r'#include "tests.h"')
write('') write(r'using namespace toml::impl;')
write(r'')
# test data # test data
write('TOML_DISABLE_WARNINGS; // unused variable spam') write('TOML_DISABLE_WARNINGS; // unused variable spam')

View File

@ -151,11 +151,11 @@ def main():
<Natvis Include="..\..\toml++.natvis" /> <Natvis Include="..\..\toml++.natvis" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" /> <ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" /> <ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" /> <ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\cpp.hint" /> <None Include="..\cpp.hint" />