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_API
- TOML_ATTR
- TOML_CONSTEVAL
- TOML_EXTERNAL_LINKAGE
- TOML_INTERNAL_LINKAGE
- TOML_MEMBER_ATTR

View File

@ -6,7 +6,6 @@
#define TOML_ABSTRACT_BASE
#define TOML_EMPTY_BASES
#define TOML_MAY_THROW
#define TOML_CONSTEVAL constexpr
#define TOML_CONSTRAINED_TEMPLATE(cond, ...) template <__VA_ARGS__>
#define TOML_LIKELY(...) (__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).
/// \param val The node or value used to initialize element 0.
/// \param vals The nodes or values used to initialize elements 1...N.
TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0_sz
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
typename ElemType,
typename... ElemTypes)
TOML_NODISCARD_CTOR
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));
if constexpr (sizeof...(ElemTypes) > 0)
{
@ -659,7 +658,7 @@ TOML_NAMESPACE_START
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
preinsertion_resize(start_idx, count);
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));
//# potentially move the initial value into the last element
@ -1087,7 +1086,7 @@ TOML_NAMESPACE_START
if (lhs.size() != rhs.size())
return false;
if (rhs.size() == 0_sz)
if (rhs.size() == 0u)
return true;
size_t i{};

View File

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

View File

@ -46,7 +46,7 @@ TOML_NAMESPACE_START
std::vector<std::string> key_path_;
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_API

View File

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

View File

@ -110,15 +110,6 @@ TOML_NAMESPACE_START
class parse_result;
#endif
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;

View File

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

View File

@ -51,7 +51,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char>
class utf8_byte_stream<std::basic_string_view<Char>>
{
static_assert(sizeof(Char) == 1_sz);
static_assert(sizeof(Char) == 1);
private:
std::basic_string_view<Char> source_;
@ -65,20 +65,20 @@ TOML_ANON_NAMESPACE_START
// trim trailing nulls
const size_t initial_len = source_.length();
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'
{
actual_len = i + 1_sz;
actual_len = i + 1u;
break;
}
}
if (initial_len != actual_len)
source_ = source_.substr(0_sz, actual_len);
source_ = source_.substr(0u, actual_len);
// skip bom
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source_.data(), 3_sz) == 0)
position_ += 3_sz;
if (actual_len >= 3u && memcmp(utf8_byte_order_mark.data(), source_.data(), 3u) == 0)
position_ += 3u;
}
TOML_NODISCARD
@ -114,7 +114,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char>
class utf8_byte_stream<std::basic_istream<Char>>
{
static_assert(sizeof(Char) == 1_sz);
static_assert(sizeof(Char) == 1);
private:
std::basic_istream<Char>* source_;
@ -130,7 +130,7 @@ TOML_ANON_NAMESPACE_START
const auto initial_pos = source_->tellg();
Char 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;
source_->clear();
@ -178,7 +178,7 @@ TOML_ANON_NAMESPACE_START
TOML_NODISCARD
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
@ -269,7 +269,7 @@ TOML_ANON_NAMESPACE_START
{
TOML_ERROR_CHECK;
auto& prev = codepoints_[(cp_idx_ - 1_sz) % 2_sz];
auto& prev = codepoints_[(cp_idx_ - 1u) % 2u];
if (stream_.eof())
return nullptr;
@ -333,7 +333,7 @@ TOML_ANON_NAMESPACE_START
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);
if (decoder_.has_code_point())
{
@ -966,7 +966,7 @@ TOML_IMPL_NAMESPACE_START
TOML_NEVER_INLINE
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 (err)
return;
@ -991,7 +991,7 @@ TOML_IMPL_NAMESPACE_START
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();
assert_or_assume(count);
@ -1034,7 +1034,7 @@ TOML_IMPL_NAMESPACE_START
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();
@ -1043,7 +1043,7 @@ TOML_IMPL_NAMESPACE_START
{
if (pop_bytes >= recording_buffer.length())
recording_buffer.clear();
else if (pop_bytes == 1_sz)
else if (pop_bytes == 1u)
recording_buffer.pop_back();
else
recording_buffer.erase(recording_buffer.begin()
@ -1322,7 +1322,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line)
{
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
size_t consecutive_delimiters = 1;
do
{
advance_and_return_if_error({});
@ -1332,30 +1332,30 @@ TOML_IMPL_NAMESPACE_START
else
break;
}
while (lookaheads < 4_sz);
while (lookaheads < 4u);
switch (consecutive_delimiters)
{
// """ " (one quote somewhere in a ML string)
case 1_sz:
case 1:
str += '"';
skipping_whitespace = false;
continue;
// """ "" (two quotes somewhere in a ML string)
case 2_sz:
case 2:
str.append("\"\""sv);
skipping_whitespace = false;
continue;
// """ """ (the end of the string)
case 3_sz: return str;
case 3: return str;
// """ """" (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)
case 5_sz:
case 5:
str.append("\"\""sv);
advance_and_return_if_error({}); // skip the last '"'
return str;
@ -1451,7 +1451,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line)
{
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
size_t consecutive_delimiters = 1;
do
{
advance_and_return_if_error({});
@ -1461,24 +1461,24 @@ TOML_IMPL_NAMESPACE_START
else
break;
}
while (lookaheads < 4_sz);
while (lookaheads < 4u);
switch (consecutive_delimiters)
{
// ''' ' (one quote somewhere in a ML string)
case 1_sz: str += '\''; continue;
case 1: str += '\''; continue;
// ''' '' (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)
case 3_sz: return str;
case 3: return str;
// ''' '''' (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)
case 5_sz:
case 5:
str.append("''"sv);
advance_and_return_if_error({}); // skip the last '
return str;
@ -1561,7 +1561,7 @@ TOML_IMPL_NAMESPACE_START
{
// step back two characters so that the current
// character is the string delimiter
go_back(2_sz);
go_back(2u);
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);
// 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);
else
@ -1906,7 +1906,7 @@ TOML_IMPL_NAMESPACE_START
}
// 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_default("missing exponent"sv);
@ -1937,7 +1937,7 @@ TOML_IMPL_NAMESPACE_START
// calculate value
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;
uint32_t val{};
while (place)
@ -2051,7 +2051,7 @@ TOML_IMPL_NAMESPACE_START
}
// single digits can be converted trivially
if (length == 1_sz)
if (length == 1u)
{
if constexpr (base == 16)
return static_cast<int64_t>(hex_to_dec(chars[0]));
@ -2101,7 +2101,7 @@ TOML_IMPL_NAMESPACE_START
// "YYYY"
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);
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));
@ -2113,7 +2113,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto month = digits[1] + digits[0] * 10u;
if (month == 0u || month > 12u)
@ -2130,7 +2130,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto day = digits[1] + digits[0] * 10u;
if (day == 0u || day > max_days_in_month)
@ -2153,11 +2153,11 @@ TOML_IMPL_NAMESPACE_START
assert_or_assume(is_decimal_digit(*cp));
push_parse_scope("time"sv);
static constexpr auto max_digits = 9_sz;
static constexpr size_t max_digits = 9;
uint32_t digits[max_digits];
// "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);
const auto hour = digits[1] + digits[0] * 10u;
if (hour > 23u)
@ -2171,7 +2171,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto minute = digits[1] + digits[0] * 10u;
if (minute > 59u)
@ -2195,7 +2195,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto second = digits[1] + digits[0] * 10u;
if (second > 59u)
@ -2211,7 +2211,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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)
{
set_error_and_return_if_eof({});
@ -2228,7 +2228,7 @@ TOML_IMPL_NAMESPACE_START
uint32_t value = 0u;
uint32_t place = 1u;
for (auto i = digit_count; i-- > 0_sz;)
for (auto i = digit_count; i-- > 0u;)
{
value += digits[i] * place;
place *= 10u;
@ -2280,7 +2280,7 @@ TOML_IMPL_NAMESPACE_START
// "HH"
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);
const auto hour = digits[1] + digits[0] * 10;
if (hour > 23)
@ -2294,7 +2294,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto minute = digits[1] + digits[0] * 10;
if (minute > 59)
@ -2464,19 +2464,19 @@ TOML_IMPL_NAMESPACE_START
switch (static_cast<char32_t>(c | 32u))
{
case U'b':
if (char_count == 2_sz && has_any(begins_zero))
if (char_count == 2u && has_any(begins_zero))
add_trait(has_b);
break;
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_plus | has_minus) || has_any(begins_sign)))
add_trait(has_e);
break;
case U'o':
if (char_count == 2_sz && has_any(begins_zero))
if (char_count == 2u && has_any(begins_zero))
add_trait(has_o);
break;
@ -2486,8 +2486,8 @@ TOML_IMPL_NAMESPACE_START
break;
case U'x':
if ((char_count == 2_sz && has_any(begins_zero))
|| (char_count == 3_sz && has_any(begins_sign) && chars[1] == U'0'))
if ((char_count == 2u && has_any(begins_zero))
|| (char_count == 3u && has_any(begins_sign) && chars[1] == U'0'))
add_trait(has_x);
break;
@ -2519,7 +2519,7 @@ TOML_IMPL_NAMESPACE_START
return_if_error({});
// 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' ')
{
const auto pre_advance_count = advance_count;
@ -2532,7 +2532,7 @@ TOML_IMPL_NAMESPACE_START
go_back(advance_count - pre_advance_count);
advance_count = pre_advance_count;
traits = pre_scan_traits;
char_count = 10_sz;
char_count = 10u;
};
advance_and_return_if_error({});
@ -2550,19 +2550,19 @@ TOML_IMPL_NAMESPACE_START
scan();
return_if_error({});
if (char_count == 12_sz)
if (char_count == 12u)
backpedal();
}
}
// set the reader back to where we started
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';
// if after scanning ahead we still only have one value character,
// the only valid value type is an integer.
if (char_count == 1_sz)
if (char_count == 1u)
{
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
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
// 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))
{
// 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) };
advance(); // skip the sign
@ -2911,7 +2911,7 @@ TOML_IMPL_NAMESPACE_START
// get the key
start_recording();
auto key = parse_key();
stop_recording(1_sz);
stop_recording(1u);
// skip past any whitespace that followed the key
consume_leading_whitespace();
@ -2977,7 +2977,7 @@ TOML_IMPL_NAMESPACE_START
// get the actual key
start_recording();
key = parse_key();
stop_recording(1_sz);
stop_recording(1u);
return_if_error({});
// 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.
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]);
if (!child)
@ -3134,13 +3134,13 @@ TOML_IMPL_NAMESPACE_START
auto kvp = parse_key_value_pair();
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,
// 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]);
if (!child)
@ -3525,7 +3525,7 @@ TOML_ANON_NAMESPACE_START
// open file with a custom-sized stack buffer
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.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
if (!file.is_open())

View File

@ -531,13 +531,6 @@
#define TOML_UNREACHABLE TOML_ASSERT(false)
#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
#define TOML_HAS_ATTR(...) __has_cpp_attribute(__VA_ARGS__)
#else
@ -758,7 +751,9 @@
#define TOML_EXTERNAL_LINKAGE inline
#define TOML_INTERNAL_LINKAGE inline
#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
#define TOML_EXTERNAL_LINKAGE

View File

@ -314,26 +314,26 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
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('-');
print_integer_leftpad_zeros(stream, val.month, 2_sz);
print_integer_leftpad_zeros(stream, val.month, 2u);
stream.put('-');
print_integer_leftpad_zeros(stream, val.day, 2_sz);
print_integer_leftpad_zeros(stream, val.day, 2u);
}
TOML_EXTERNAL_LINKAGE
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(':');
print_integer_leftpad_zeros(stream, val.minute, 2_sz);
print_integer_leftpad_zeros(stream, val.minute, 2u);
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)
{
stream.put('.');
auto ns = val.nanosecond;
size_t digits = 9_sz;
size_t digits = 9u;
while (ns % 10u == 0u)
{
ns /= 10u;
@ -363,13 +363,13 @@ TOML_IMPL_NAMESPACE_START
const auto hours = mins / 60;
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;
}
else
print_to_stream(stream, "00"sv);
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

View File

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

View File

@ -78,7 +78,6 @@ TOML_POP_WARNINGS;
#undef TOML_COMPILER_EXCEPTIONS
#undef TOML_CONCAT
#undef TOML_CONCAT_1
#undef TOML_CONSTEVAL
#undef TOML_CONSTRAINED_TEMPLATE
#undef TOML_CPP
#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
//-----
// this file was generated by generate_conformance_tests.py - do not modify it directly
// clang-format off
#include "tests.h"
using namespace toml::impl;

View File

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

View File

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

View File

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

View File

@ -5,17 +5,17 @@
#include "settings.h"
#if !TOML_HEADER_ONLY
#define TOML_IMPLEMENTATION
#define TOML_IMPLEMENTATION
#endif
#if USE_TARTANLLAMA_OPTIONAL
#include "tloptional.h"
#include "lib_tloptional.h"
#endif
#if USE_SINGLE_HEADER
#include "../toml.hpp"
#include "../toml.hpp"
#else
#include "../include/toml++/toml.h"
#include "../include/toml++/toml.h"
#endif
namespace toml
@ -23,286 +23,285 @@ namespace toml
using std::declval;
using std::is_same_v;
#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<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<const volatile T> == expected); \
static_assert(impl::node_type_of<const volatile T&> == expected); \
static_assert(impl::node_type_of<const volatile 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<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<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(double, node_type::floating_point);
CHECK_NODE_TYPE_MAPPING(std::string, node_type::string);
CHECK_NODE_TYPE_MAPPING(bool, node_type::boolean);
CHECK_NODE_TYPE_MAPPING(toml::date, node_type::date);
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::array, node_type::array);
CHECK_NODE_TYPE_MAPPING(toml::table, node_type::table);
CHECK_NODE_TYPE_MAPPING(int64_t, node_type::integer);
CHECK_NODE_TYPE_MAPPING(double, node_type::floating_point);
CHECK_NODE_TYPE_MAPPING(std::string, node_type::string);
CHECK_NODE_TYPE_MAPPING(bool, node_type::boolean);
CHECK_NODE_TYPE_MAPPING(toml::date, node_type::date);
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::array, node_type::array);
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) \
static_assert((impl::value_traits<T>::is_native || impl::value_traits<T>::can_represent_native) == expected)
CHECK_CAN_REPRESENT_NATIVE(time, true);
CHECK_CAN_REPRESENT_NATIVE(date, true);
CHECK_CAN_REPRESENT_NATIVE(date_time, true);
CHECK_CAN_REPRESENT_NATIVE(bool, true);
CHECK_CAN_REPRESENT_NATIVE(int8_t, false);
CHECK_CAN_REPRESENT_NATIVE(int16_t, false);
CHECK_CAN_REPRESENT_NATIVE(int32_t, false);
CHECK_CAN_REPRESENT_NATIVE(int64_t, true);
CHECK_CAN_REPRESENT_NATIVE(uint8_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint16_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint32_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint64_t, false);
CHECK_CAN_REPRESENT_NATIVE(float, false);
CHECK_CAN_REPRESENT_NATIVE(double, true);
#ifdef TOML_INT128
CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true);
CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false);
#endif
#ifdef TOML_FP16
CHECK_CAN_REPRESENT_NATIVE(time, true);
CHECK_CAN_REPRESENT_NATIVE(date, true);
CHECK_CAN_REPRESENT_NATIVE(date_time, true);
CHECK_CAN_REPRESENT_NATIVE(bool, true);
CHECK_CAN_REPRESENT_NATIVE(int8_t, false);
CHECK_CAN_REPRESENT_NATIVE(int16_t, false);
CHECK_CAN_REPRESENT_NATIVE(int32_t, false);
CHECK_CAN_REPRESENT_NATIVE(int64_t, true);
CHECK_CAN_REPRESENT_NATIVE(uint8_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint16_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint32_t, false);
CHECK_CAN_REPRESENT_NATIVE(uint64_t, false);
CHECK_CAN_REPRESENT_NATIVE(float, false);
CHECK_CAN_REPRESENT_NATIVE(double, true);
#ifdef TOML_INT128
CHECK_CAN_REPRESENT_NATIVE(TOML_INT128, true);
CHECK_CAN_REPRESENT_NATIVE(TOML_UINT128, false);
#endif
#ifdef TOML_FP16
CHECK_CAN_REPRESENT_NATIVE(TOML_FP16, false);
#endif
#ifdef TOML_FLOAT16
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false);
#endif
#ifdef TOML_FLOAT128
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true);
#endif
#endif
#ifdef TOML_FLOAT16
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT16, false);
#endif
#ifdef TOML_FLOAT128
CHECK_CAN_REPRESENT_NATIVE(TOML_FLOAT128, true);
#endif
CHECK_CAN_REPRESENT_NATIVE(char*, false);
CHECK_CAN_REPRESENT_NATIVE(char*const, false);
CHECK_CAN_REPRESENT_NATIVE(char[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char[2], false);
CHECK_CAN_REPRESENT_NATIVE(char(&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char(&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char*, true);
CHECK_CAN_REPRESENT_NATIVE(const char*const, true);
CHECK_CAN_REPRESENT_NATIVE(std::string, true);
CHECK_CAN_REPRESENT_NATIVE(std::string_view, true);
#if TOML_HAS_CHAR8
CHECK_CAN_REPRESENT_NATIVE(char8_t*, false);
CHECK_CAN_REPRESENT_NATIVE(char8_t*const, false);
CHECK_CAN_REPRESENT_NATIVE(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(const char8_t(&)[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*, true);
CHECK_CAN_REPRESENT_NATIVE(const char8_t*const, true);
CHECK_CAN_REPRESENT_NATIVE(std::u8string, true);
CHECK_CAN_REPRESENT_NATIVE(std::u8string_view, true);
#endif
CHECK_CAN_REPRESENT_NATIVE(wchar_t*, false);
CHECK_CAN_REPRESENT_NATIVE(wchar_t*const, false);
CHECK_CAN_REPRESENT_NATIVE(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(const 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*, 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_view, false);
CHECK_CAN_REPRESENT_NATIVE(char*, false);
CHECK_CAN_REPRESENT_NATIVE(char* const, false);
CHECK_CAN_REPRESENT_NATIVE(char[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char[2], false);
CHECK_CAN_REPRESENT_NATIVE(char (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char (&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(char(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char(&&)[2], false);
CHECK_CAN_REPRESENT_NATIVE(const char*, true);
CHECK_CAN_REPRESENT_NATIVE(const char* const, true);
CHECK_CAN_REPRESENT_NATIVE(std::string, true);
CHECK_CAN_REPRESENT_NATIVE(std::string_view, true);
#if TOML_HAS_CHAR8
CHECK_CAN_REPRESENT_NATIVE(char8_t*, false);
CHECK_CAN_REPRESENT_NATIVE(char8_t* const, false);
CHECK_CAN_REPRESENT_NATIVE(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(const char8_t (&)[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*, true);
CHECK_CAN_REPRESENT_NATIVE(const char8_t* const, true);
CHECK_CAN_REPRESENT_NATIVE(std::u8string, true);
CHECK_CAN_REPRESENT_NATIVE(std::u8string_view, true);
#endif
CHECK_CAN_REPRESENT_NATIVE(wchar_t*, false);
CHECK_CAN_REPRESENT_NATIVE(wchar_t* const, false);
CHECK_CAN_REPRESENT_NATIVE(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(const 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*, 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_view, false);
#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_view<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_EXACT(T, 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<const node>>().value_exact<T>()), optional<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_view<node>>().value_or(declval<T>())), expected>); \
static_assert(is_same_v<decltype(declval<node_view<const node>>().value_or(declval<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_view<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( date, date);
CHECK_VALUE_EXACT( date_time, date_time);
CHECK_VALUE_EXACT( bool, bool);
CHECK_VALUE_EXACT( double, double);
CHECK_VALUE_EXACT( int64_t, int64_t);
CHECK_VALUE_EXACT( const char*, const char*);
CHECK_VALUE_EXACT( std::string_view, std::string_view);
CHECK_VALUE_EXACT( std::string, std::string);
#if TOML_HAS_CHAR8
CHECK_VALUE_EXACT( const char8_t*, const char8_t*);
CHECK_VALUE_EXACT( std::u8string_view, std::u8string_view);
CHECK_VALUE_EXACT( std::u8string, std::u8string);
#endif
CHECK_VALUE_EXACT(time, time);
CHECK_VALUE_EXACT(date, date);
CHECK_VALUE_EXACT(date_time, date_time);
CHECK_VALUE_EXACT(bool, bool);
CHECK_VALUE_EXACT(double, double);
CHECK_VALUE_EXACT(int64_t, int64_t);
CHECK_VALUE_EXACT(const char*, const char*);
CHECK_VALUE_EXACT(std::string_view, std::string_view);
CHECK_VALUE_EXACT(std::string, std::string);
#if TOML_HAS_CHAR8
CHECK_VALUE_EXACT(const char8_t*, const char8_t*);
CHECK_VALUE_EXACT(std::u8string_view, std::u8string_view);
CHECK_VALUE_EXACT(std::u8string, std::u8string);
#endif
CHECK_VALUE_OR( time, time);
CHECK_VALUE_OR( time&, time);
CHECK_VALUE_OR( time&&, 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 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 const, date_time);
CHECK_VALUE_OR( bool, bool);
CHECK_VALUE_OR( bool&, bool);
CHECK_VALUE_OR( bool&&, 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 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 const, int64_t);
#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 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 const, TOML_UINT128);
#endif
CHECK_VALUE_OR( float, float);
CHECK_VALUE_OR( float&, float);
CHECK_VALUE_OR( float&&, 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 const, double);
#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 const, TOML_FLOAT128);
#endif
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[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, 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( 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( 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
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[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, 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( 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( const std::u8string, std::u8string);
CHECK_VALUE_OR( const std::u8string&, std::u8string);
CHECK_VALUE_OR( const std::u8string&&, std::u8string);
#endif
#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*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( 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[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( 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( const std::wstring, std::wstring);
CHECK_VALUE_OR( const std::wstring&, std::wstring);
CHECK_VALUE_OR( const std::wstring&&, std::wstring);
#endif
CHECK_VALUE_OR(time, time);
CHECK_VALUE_OR(time&, time);
CHECK_VALUE_OR(time&&, 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 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 const, date_time);
CHECK_VALUE_OR(bool, bool);
CHECK_VALUE_OR(bool&, bool);
CHECK_VALUE_OR(bool&&, 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 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 const, int64_t);
#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 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 const, TOML_UINT128);
#endif
CHECK_VALUE_OR(float, float);
CHECK_VALUE_OR(float&, float);
CHECK_VALUE_OR(float&&, 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 const, double);
#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 const, TOML_FLOAT128);
#endif
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[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, 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(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(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
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[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, 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(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(const std::u8string, std::u8string);
CHECK_VALUE_OR(const std::u8string&, std::u8string);
CHECK_VALUE_OR(const std::u8string&&, std::u8string);
#endif
#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* 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(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[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(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(const std::wstring, std::wstring);
CHECK_VALUE_OR(const std::wstring&, std::wstring);
CHECK_VALUE_OR(const std::wstring&&, std::wstring);
#endif
#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<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<const T&>>); \
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&&>>)
#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<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<const T&>>); \
static_assert(std::is_same_v<expected, toml::inserted_type_of<T&&>>)
CHECK_INSERTED_AS(table, table);
CHECK_INSERTED_AS(array, array);
CHECK_INSERTED_AS(node, node);
CHECK_INSERTED_AS(time, value<time>);
CHECK_INSERTED_AS(date, value<date>);
CHECK_INSERTED_AS(date_time, value<date_time>);
CHECK_INSERTED_AS(bool, value<bool>);
CHECK_INSERTED_AS(int8_t, value<int64_t>);
CHECK_INSERTED_AS(int16_t, value<int64_t>);
CHECK_INSERTED_AS(int32_t, value<int64_t>);
CHECK_INSERTED_AS(int64_t, value<int64_t>);
CHECK_INSERTED_AS(uint8_t, value<int64_t>);
CHECK_INSERTED_AS(uint16_t, value<int64_t>);
CHECK_INSERTED_AS(uint32_t, value<int64_t>);
CHECK_INSERTED_AS(float, value<double>);
CHECK_INSERTED_AS(double, value<double>);
#ifdef TOML_FP16
CHECK_INSERTED_AS(TOML_FP16, value<double>);
#endif
#ifdef TOML_FLOAT16
CHECK_INSERTED_AS(TOML_FLOAT16, value<double>);
#endif
CHECK_INSERTED_AS(table, table);
CHECK_INSERTED_AS(array, array);
CHECK_INSERTED_AS(node, node);
CHECK_INSERTED_AS(time, value<time>);
CHECK_INSERTED_AS(date, value<date>);
CHECK_INSERTED_AS(date_time, value<date_time>);
CHECK_INSERTED_AS(bool, value<bool>);
CHECK_INSERTED_AS(int8_t, value<int64_t>);
CHECK_INSERTED_AS(int16_t, value<int64_t>);
CHECK_INSERTED_AS(int32_t, value<int64_t>);
CHECK_INSERTED_AS(int64_t, value<int64_t>);
CHECK_INSERTED_AS(uint8_t, value<int64_t>);
CHECK_INSERTED_AS(uint16_t, value<int64_t>);
CHECK_INSERTED_AS(uint32_t, value<int64_t>);
CHECK_INSERTED_AS(float, value<double>);
CHECK_INSERTED_AS(double, value<double>);
#ifdef TOML_FP16
CHECK_INSERTED_AS(TOML_FP16, value<double>);
#endif
#ifdef TOML_FLOAT16
CHECK_INSERTED_AS(TOML_FLOAT16, value<double>);
#endif
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;
}
#define TOML_LIFETIME_HOOKS 1
#define TOML_TABLE_CREATED ::leakproof::table_created()
#define TOML_TABLE_DESTROYED ::leakproof::table_destroyed()
#define TOML_ARRAY_CREATED ::leakproof::array_created()
#define TOML_ARRAY_DESTROYED ::leakproof::array_destroyed()
#define TOML_VALUE_CREATED ::leakproof::value_created()
#define TOML_VALUE_DESTROYED ::leakproof::value_destroyed()
#define TOML_LIFETIME_HOOKS 1
#define TOML_TABLE_CREATED ::leakproof::table_created()
#define TOML_TABLE_DESTROYED ::leakproof::table_destroyed()
#define TOML_ARRAY_CREATED ::leakproof::array_created()
#define TOML_ARRAY_DESTROYED ::leakproof::array_destroyed()
#define TOML_VALUE_CREATED ::leakproof::value_created()
#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>
// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#elif defined (__GNUC__)
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wextra"
@ -17,14 +16,13 @@
#endif
#if __has_include(<tloptional/include/tl/optional.hpp>)
#include <tloptional/include/tl/optional.hpp>
#include <tloptional/include/tl/optional.hpp>
#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
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined (__GNUC__)
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

View File

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

View File

@ -64,8 +64,7 @@ TEST_CASE("arrays - moving")
CHECK(!arr2.source().path);
CHECK(arr2.size() == 0u);
},
filename
);
filename);
}
TEST_CASE("arrays - copying")
@ -116,8 +115,7 @@ TEST_CASE("arrays - copying")
CHECK(arr3 == *arr1);
CHECK(arr3 == arr2);
},
filename
);
filename);
}
TEST_CASE("arrays - construction")
@ -133,7 +131,7 @@ TEST_CASE("arrays - construction")
CHECK(!arr.source().path);
CHECK(!arr.is_homogeneous());
}
{
array arr{ 42 };
CHECK(arr.size() == 1u);
@ -163,7 +161,7 @@ TEST_CASE("arrays - construction")
CHECK(!arr.is_homogeneous());
}
#if TOML_WINDOWS_COMPAT
#if TOML_WINDOWS_COMPAT
{
array arr{ "mixed", "string"sv, L"test", L"kek"sv };
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>(3) == "kek"sv);
}
#endif // TOML_WINDOWS_COMPAT
#endif // TOML_WINDOWS_COMPAT
}
TEST_CASE("arrays - equality")
@ -373,12 +371,12 @@ TEST_CASE("arrays - insertion and erasure")
CHECK(*arr.get_as<double>(5u) == 3.0);
}
#if TOML_WINDOWS_COMPAT
#if TOML_WINDOWS_COMPAT
arr.clear();
it = arr.insert(arr.cbegin(), L"test");
REQUIRE(*arr.get_as<std::string>(0u) == "test"sv);
it = arr.emplace<std::string>(arr.cbegin(), L"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");
REQUIRE(*arr.back().as_string() == "test4"sv);
#endif // TOML_WINDOWS_COMPAT
#endif // TOML_WINDOWS_COMPAT
}
TEST_CASE("arrays - flattening")
{
{
array arr{
1, 2, 3,
1,
2,
3,
array{ 4, 5 },
6,
array{},
array{ 7, array{ 8, array{ 9 }, 10, array{}, }, 11 },
array{ 7,
array{
8,
array{ 9 },
10,
array{},
},
11 },
};
arr.flatten();
REQUIRE(arr == array{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 });
}
{
array arr{
array{},
array{inserter{array{}}},
array{array{},array{array{},array{}},array{}},
array{array{array{array{array{array{ 1 }}}}}}
};
array arr{ array{},
array{ inserter{ array{} } },
array{ array{}, array{ array{}, array{} }, array{} },
array{ array{ array{ array{ array{ array{ 1 } } } } } } };
arr.flatten();
REQUIRE(arr == array{ 1 });
}
@ -442,7 +447,7 @@ TEST_CASE("arrays - resizing and truncation")
REQUIRE(arr.size() == 2u);
REQUIRE(arr == array{ 1, 2 });
//resize up to six elements
// resize up to six elements
arr.resize(6u, 42);
REQUIRE(arr.size() == 6u);
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<const table&>(result).empty());
auto& tbl = static_cast<table&>(result);
CHECK(tbl["key"sv]);
CHECK(result["key"sv]);
@ -38,7 +38,7 @@ TEST_CASE("parse_result - good parse")
CHECK(result.cbegin() != tbl.cend());
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.end() == ctbl.end());
CHECK(cresult.begin() != ctbl.end());
@ -52,19 +52,22 @@ TEST_CASE("parse_result - good parse")
size_t tbl_iterations{};
for (auto&& [k, v] : tbl)
{
(void)k; (void)v;
(void)k;
(void)v;
tbl_iterations++;
}
size_t result_iterations{};
for (auto& [k, v] : result)
{
(void)k; (void)v;
(void)k;
(void)v;
result_iterations++;
}
size_t cresult_iterations{};
for (auto [k, v] : cresult)
{
(void)k; (void)v;
(void)k;
(void)v;
cresult_iterations++;
}
CHECK(tbl_iterations == tbl.size());
@ -72,7 +75,6 @@ TEST_CASE("parse_result - good parse")
CHECK(tbl_iterations == cresult_iterations);
}
TEST_CASE("parse_result - bad parse")
{
auto result = "key = trUe"_toml;
@ -98,15 +100,16 @@ TEST_CASE("parse_result - bad parse")
for (auto [k, v] : result)
{
(void)k; (void)v;
(void)k;
(void)v;
FAIL("This code should not run");
}
for (auto [k, v] : cresult)
{
(void)k; (void)v;
(void)k;
(void)v;
FAIL("This code should not run");
}
}
#endif //!TOML_EXCEPTIONS

View File

@ -64,8 +64,7 @@ TEST_CASE("tables - moving")
CHECK(tbl2.size() == 0u);
CHECK(!tbl2["test"].as<table>());
},
filename
);
filename);
}
TEST_CASE("tables - copying")
@ -114,8 +113,7 @@ TEST_CASE("tables - copying")
CHECK(tbl3 == tbl2);
CHECK(tbl3 == tbl);
},
filename
);
filename);
}
TEST_CASE("tables - construction")
@ -132,9 +130,7 @@ TEST_CASE("tables - construction")
}
{
table tbl{{
{ "foo"sv, 42 }
}};
table tbl{ { { "foo"sv, 42 } } };
CHECK(tbl.size() == 1u);
CHECK(!tbl.empty());
CHECK(tbl.begin() != tbl.end());
@ -144,12 +140,7 @@ TEST_CASE("tables - construction")
}
{
table tbl{{
{ "foo"sv, 42 },
{ "bar"sv, 10.0 },
{ "kek"sv, false },
{ "qux"sv, array{ 1 } }
}};
table tbl{ { { "foo"sv, 42 }, { "bar"sv, 10.0 }, { "kek"sv, false }, { "qux"sv, array{ 1 } } } };
CHECK(tbl.size() == 4u);
CHECK(!tbl.empty());
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 });
}
#if TOML_WINDOWS_COMPAT
#if TOML_WINDOWS_COMPAT
{
table tbl{ {
{ L"foo", L"test1" },
{ L"bar"sv, L"test2"sv },
{ L"kek"s, L"test3"sv },
{ L"qux"sv.data(), L"test4"sv.data() }
} };
table tbl{ { { L"foo", L"test1" },
{ L"bar"sv, L"test2"sv },
{ L"kek"s, L"test3"sv },
{ L"qux"sv.data(), L"test4"sv.data() } } };
CHECK(tbl.size() == 4u);
CHECK(!tbl.empty());
REQUIRE(tbl.get_as<std::string>("foo"sv));
@ -181,46 +170,26 @@ TEST_CASE("tables - construction")
REQUIRE(tbl.get_as<std::string>("qux"sv));
CHECK(*tbl.get_as<std::string>("qux"sv) == "test4"sv);
}
#endif // TOML_WINDOWS_COMPAT
#endif // TOML_WINDOWS_COMPAT
}
TEST_CASE("tables - equality")
{
static constexpr const char* one = "one";
table tbl1{{
{ one, 1 },
{ "two", 2 },
{ "three", 3 }
}};
table tbl1{ { { one, 1 }, { "two", 2 }, { "three", 3 } } };
CHECK(tbl1 == tbl1);
table tbl2{{
{ "one"sv, 1 },
{ "two"sv, 2 },
{ "three"sv, 3 }
}};
table tbl2{ { { "one"sv, 1 }, { "two"sv, 2 }, { "three"sv, 3 } } };
CHECK(tbl1 == tbl2);
table tbl3{{
{ "one"sv, 1 },
{ "two"sv, 2 }
}};
table tbl3{ { { "one"sv, 1 }, { "two"sv, 2 } } };
CHECK(tbl1 != tbl3);
table tbl4{{
{ "one"sv, 1 },
{ "two"sv, 2 },
{ "three"sv, 3 },
{ "four"sv, 4 }
}};
table tbl4{ { { "one"sv, 1 }, { "two"sv, 2 }, { "three"sv, 3 }, { "four"sv, 4 } } };
CHECK(tbl1 != tbl4);
table tbl5{{
{ "one"sv, 1 },
{ "two"sv, 2 },
{ "three"sv, 3.0 }
}};
table tbl5{ { { "one"sv, 1 }, { "two"sv, 2 }, { "three"sv, 3.0 } } };
CHECK(tbl1 != tbl5);
table tbl6{};
@ -260,7 +229,7 @@ TEST_CASE("tables - insertion and erasure")
CHECK(!tbl.empty());
REQUIRE(tbl.get_as<int64_t>("a"sv));
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);
CHECK(res.first == tbl.begin());
@ -268,16 +237,16 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 1u);
REQUIRE(tbl.get_as<int64_t>("a"));
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";
res = tbl.insert_or_assign(a, 69);
res = tbl.insert_or_assign(a, 69);
CHECK(res.first == tbl.begin());
CHECK(res.second == false); // should assign
CHECK(tbl.size() == 1u);
REQUIRE(tbl.get_as<int64_t>("a"));
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");
CHECK(res.first == advance(tbl.begin(), 1));
@ -285,7 +254,7 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 2u);
REQUIRE(tbl.get_as<std::string>("b"));
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);
CHECK(res.first == advance(tbl.begin(), 2));
@ -293,7 +262,7 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<array>("c"));
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);
CHECK(res.first == advance(tbl.begin(), 2));
@ -301,10 +270,10 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 3u);
REQUIRE(!tbl.get_as<int64_t>("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());
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(tbl.size() == 2u);
@ -314,10 +283,10 @@ TEST_CASE("tables - insertion and erasure")
CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<int64_t>("a"));
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));
REQUIRE(tbl == table{{ { "a"sv, 69 } }});
REQUIRE(tbl == table{ { { "a"sv, 69 } } });
CHECK(it == tbl.end());
CHECK(tbl.size() == 1u);
@ -328,11 +297,7 @@ TEST_CASE("tables - insertion and erasure")
// void insert(Iter first, Iter last)
{
std::vector<std::pair<std::string, std::string>> vals{
{ "foo", "foo" },
{ "bar", "bar" },
{ "kek", "kek" }
};
std::vector<std::pair<std::string, std::string>> vals{ { "foo", "foo" }, { "bar", "bar" }, { "kek", "kek" } };
tbl.insert(vals.begin(), vals.end());
CHECK(tbl.size() == 3u);
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)
{
std::vector<std::pair<std::string, std::string>> vals{
{ "foo", "foo" },
{ "bar", "bar" },
{ "kek", "kek" }
};
std::vector<std::pair<std::string, std::string>> vals{ { "foo", "foo" }, { "bar", "bar" }, { "kek", "kek" } };
tbl.insert(std::make_move_iterator(vals.begin()), std::make_move_iterator(vals.end()));
CHECK(tbl.size() == 3u);
REQUIRE(tbl.get_as<std::string>("foo"));
@ -380,8 +341,7 @@ TEST_CASE("tables - insertion and erasure")
tbl.clear();
}
#if TOML_WINDOWS_COMPAT
#if TOML_WINDOWS_COMPAT
tbl.insert(L"a", L"test1");
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);
CHECK(tbl.size() == 0u);
#endif // TOML_WINDOWS_COMPAT
#endif // TOML_WINDOWS_COMPAT
}
TEST_CASE("tables - printing")
@ -458,4 +418,3 @@ c = 3)"sv;
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")
{
#define CHECK_VALUE_INIT2(initializer, target_type, equiv) \
do { \
auto v = value{ initializer }; \
static_assert(std::is_same_v<decltype(v), value<target_type>>); \
CHECK(v == equiv); \
CHECK(equiv == v); \
CHECK(*v == equiv); \
CHECK(v.get() == equiv); \
CHECK(v.is_homogeneous()); \
CHECK(v.is_homogeneous<target_type>()); \
CHECK(v.is_homogeneous(impl::node_type_of<target_type>)); \
} while (false)
#define CHECK_VALUE_INIT2(initializer, target_type, equiv) \
do \
{ \
auto v = value{ initializer }; \
static_assert(std::is_same_v<decltype(v), value<target_type>>); \
CHECK(v == equiv); \
CHECK(equiv == v); \
CHECK(*v == equiv); \
CHECK(v.get() == equiv); \
CHECK(v.is_homogeneous()); \
CHECK(v.is_homogeneous<target_type>()); \
CHECK(v.is_homogeneous(impl::node_type_of<target_type>)); \
} \
while (false)
#define CHECK_VALUE_INIT(initializer, target_type) \
CHECK_VALUE_INIT2(initializer, target_type, initializer)
#define CHECK_VALUE_INIT(initializer, target_type) CHECK_VALUE_INIT2(initializer, target_type, initializer)
CHECK_VALUE_INIT(one<signed char>, int64_t);
CHECK_VALUE_INIT(one<signed short>, int64_t);
CHECK_VALUE_INIT(one<signed int>, int64_t);
CHECK_VALUE_INIT(one<signed 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 short>, 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 long>, int64_t, 1u);
CHECK_VALUE_INIT(true, bool);
CHECK_VALUE_INIT(false, bool);
CHECK_VALUE_INIT("kek", std::string);
CHECK_VALUE_INIT("kek"s, std::string);
CHECK_VALUE_INIT("kek"sv, std::string);
CHECK_VALUE_INIT2("kek"sv.data(), std::string, "kek"sv);
#if TOML_HAS_CHAR8
CHECK_VALUE_INIT2(u8"kek", 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.data(), std::string, "kek"sv);
#endif
CHECK_VALUE_INIT(one<signed char>, int64_t);
CHECK_VALUE_INIT(one<signed short>, int64_t);
CHECK_VALUE_INIT(one<signed int>, int64_t);
CHECK_VALUE_INIT(one<signed 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 short>, 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 long>, int64_t, 1u);
CHECK_VALUE_INIT(true, bool);
CHECK_VALUE_INIT(false, bool);
CHECK_VALUE_INIT("kek", std::string);
CHECK_VALUE_INIT("kek"s, std::string);
CHECK_VALUE_INIT("kek"sv, std::string);
CHECK_VALUE_INIT2("kek"sv.data(), std::string, "kek"sv);
#if TOML_HAS_CHAR8
CHECK_VALUE_INIT2(u8"kek", 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.data(), std::string, "kek"sv);
#endif
#ifdef _WIN32
CHECK_VALUE_INIT(one<BOOL>, int64_t);
CHECK_VALUE_INIT(one<SHORT>, int64_t);
CHECK_VALUE_INIT(one<INT>, int64_t);
CHECK_VALUE_INIT(one<LONG>, int64_t);
CHECK_VALUE_INIT(one<INT_PTR>, int64_t);
CHECK_VALUE_INIT(one<LONG_PTR>, int64_t);
CHECK_VALUE_INIT2(one<USHORT>, int64_t, 1u);
CHECK_VALUE_INIT2(one<UINT>, int64_t, 1u);
CHECK_VALUE_INIT2(one<ULONG>, 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<WORD>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD32>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD64>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORDLONG>, int64_t, 1u);
#ifdef _WIN32
CHECK_VALUE_INIT(one<BOOL>, int64_t);
CHECK_VALUE_INIT(one<SHORT>, int64_t);
CHECK_VALUE_INIT(one<INT>, int64_t);
CHECK_VALUE_INIT(one<LONG>, int64_t);
CHECK_VALUE_INIT(one<INT_PTR>, int64_t);
CHECK_VALUE_INIT(one<LONG_PTR>, int64_t);
CHECK_VALUE_INIT2(one<USHORT>, int64_t, 1u);
CHECK_VALUE_INIT2(one<UINT>, int64_t, 1u);
CHECK_VALUE_INIT2(one<ULONG>, 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<WORD>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD32>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORD64>, int64_t, 1u);
CHECK_VALUE_INIT2(one<DWORDLONG>, int64_t, 1u);
#if TOML_WINDOWS_COMPAT
CHECK_VALUE_INIT2(L"kek", std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"s, std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"sv, std::string, "kek"sv);
CHECK_VALUE_INIT2(L"kek"sv.data(), std::string, "kek"sv);
#endif // TOML_WINDOWS_COMPAT
#if 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")
@ -132,10 +133,8 @@ TEST_CASE("values - printing")
TEST_CASE("nodes - value() int/float/bool conversions")
{
#define CHECK_VALUE_PASS(type, v) \
CHECK(n.value<type>() == static_cast<type>(v))
#define CHECK_VALUE_FAIL(type) \
CHECK(!n.value<type>())
#define CHECK_VALUE_PASS(type, v) CHECK(n.value<type>() == static_cast<type>(v))
#define CHECK_VALUE_FAIL(type) CHECK(!n.value<type>())
// bools
{
@ -328,7 +327,6 @@ TEST_CASE("nodes - value() int/float/bool conversions")
CHECK_VALUE_FAIL(toml::time);
CHECK_VALUE_FAIL(toml::date_time);
*val = 1.0;
CHECK_VALUE_FAIL(bool);
CHECK_VALUE_PASS(int8_t, 1);

View File

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

View File

@ -7,18 +7,16 @@
TEST_CASE("parsing - booleans")
{
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
bool1 = true
bool2 = false
)"sv,
[](table&& tbl)
{
CHECK(tbl["bool1"] == true);
CHECK(tbl["bool2"] == false);
}
);
parsing_should_succeed(FILE_LINE_ARGS,
R"(
bool1 = true
bool2 = false
)"sv,
[](table&& tbl)
{
CHECK(tbl["bool1"] == true);
CHECK(tbl["bool2"] == false);
});
// "Always lowercase."
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);
// 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);
}

View File

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

View File

@ -7,36 +7,34 @@
TEST_CASE("parsing - floats")
{
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
# fractional
flt1 = +1.0
flt2 = 3.1415
flt3 = -0.01
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# fractional
flt1 = +1.0
flt2 = 3.1415
flt3 = -0.01
# exponent
flt4 = 5e+22
flt5 = 1e06
flt6 = -2E-2
# exponent
flt4 = 5e+22
flt5 = 1e06
flt6 = -2E-2
# both
flt7 = 6.626e-34
# both
flt7 = 6.626e-34
flt8 = 224_617.445_991_228
)"sv,
[](table&& tbl)
{
CHECK(tbl["flt1"] == 1.0);
CHECK(tbl["flt2"] == 3.1415);
CHECK(tbl["flt3"] == -0.01);
CHECK(tbl["flt4"].as<double>()->get() == 5e+22_a);
CHECK(tbl["flt5"].as<double>()->get() == 1e6_a);
CHECK(tbl["flt6"] == -2E-2);
CHECK(tbl["flt7"].as<double>()->get() == 6.626e-34_a);
CHECK(tbl["flt8"].as<double>()->get() == 224617.445991228_a);
}
);
flt8 = 224_617.445_991_228
)"sv,
[](table&& tbl)
{
CHECK(tbl["flt1"] == 1.0);
CHECK(tbl["flt2"] == 3.1415);
CHECK(tbl["flt3"] == -0.01);
CHECK(tbl["flt4"].as<double>()->get() == 5e+22_a);
CHECK(tbl["flt5"].as<double>()->get() == 1e6_a);
CHECK(tbl["flt6"] == -2E-2);
CHECK(tbl["flt7"].as<double>()->get() == 6.626e-34_a);
CHECK(tbl["flt8"].as<double>()->get() == 224617.445991228_a);
});
// "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);
@ -44,15 +42,13 @@ TEST_CASE("parsing - floats")
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."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(zeroes = [-0.0, +0.0])"sv,
[](table&& tbl)
{
CHECK(tbl["zeroes"][0] == -0.0);
CHECK(tbl["zeroes"][1] == +0.0);
}
);
parsing_should_succeed(FILE_LINE_ARGS,
R"(zeroes = [-0.0, +0.0])"sv,
[](table&& tbl)
{
CHECK(tbl["zeroes"][0] == -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"
// (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);
// value tests
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, "1.0"sv, 1.0);
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, "+1e1"sv, +1e1);
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.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, "-1.0"sv, -1.0);
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, "0.1"sv, 0.1);
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, "+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, "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, "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, "+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, "-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, "123e-10"sv, 123e-10);
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, "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-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, "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, "6.02e23"sv, 6.02e23);
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, "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, "1.0"sv, 1.0);
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, "+1e1"sv, +1e1);
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.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, "-1.0"sv, -1.0);
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, "0.1"sv, 0.1);
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, "+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, "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, "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, "+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, "-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, "123e-10"sv, 123e-10);
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, "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-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, "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, "6.02e23"sv, 6.02e23);
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);
// toml/issues/562 (hexfloats)
#if TOML_LANG_UNRELEASED
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, " 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, " -0x10p-1"sv, -0x10p-1);
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, " 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.1p-1"sv, -0x10.1p-1);
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);
#else
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 = -0x10p-1"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 = 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.1p-1"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);
#endif
// toml/issues/562 (hexfloats)
#if TOML_LANG_UNRELEASED
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, " 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, " -0x10p-1"sv, -0x10p-1);
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, " 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.1p-1"sv, -0x10.1p-1);
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);
#else
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 = -0x10p-1"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 = 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.1p-1"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);
#endif
}
TEST_CASE("parsing - inf and nan")
{
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
# infinity
sf1 = inf # positive infinity
sf2 = +inf # positive infinity
sf3 = -inf # negative infinity
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# infinity
sf1 = inf # positive infinity
sf2 = +inf # positive infinity
sf3 = -inf # negative infinity
# not a number
sf4 = nan # actual sNaN/qNaN encoding is implementation specific
sf5 = +nan # same as `nan`
sf6 = -nan # valid, actual encoding is implementation specific
)"sv,
[](table&& tbl)
{
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["sf3"].as<double>()) == impl::fp_class::neg_inf);
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["sf6"].as<double>()) == impl::fp_class::nan);
}
);
# not a number
sf4 = nan # actual sNaN/qNaN encoding is implementation specific
sf5 = +nan # same as `nan`
sf6 = -nan # valid, actual encoding is implementation specific
)"sv,
[](table&& tbl)
{
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["sf3"].as<double>()) == impl::fp_class::neg_inf);
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["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);

View File

@ -7,28 +7,26 @@
TEST_CASE("parsing - integers (decimal)")
{
parsing_should_succeed(
FILE_LINE_ARGS,
BOM_PREFIX R"(
int1 = +99
int2 = 42
int3 = 0
int4 = -17
int5 = 1_000
int6 = 5_349_221
int7 = 1_2_3_4_5 # VALID but discouraged
)"sv,
[](table&& tbl)
{
CHECK(tbl["int1"] == 99);
CHECK(tbl["int2"] == 42);
CHECK(tbl["int3"] == 0);
CHECK(tbl["int4"] == -17);
CHECK(tbl["int5"] == 1000);
CHECK(tbl["int6"] == 5349221);
CHECK(tbl["int7"] == 12345);
}
);
parsing_should_succeed(FILE_LINE_ARGS,
BOM_PREFIX R"(
int1 = +99
int2 = 42
int3 = 0
int4 = -17
int5 = 1_000
int6 = 5_349_221
int7 = 1_2_3_4_5 # VALID but discouraged
)"sv,
[](table&& tbl)
{
CHECK(tbl["int1"] == 99);
CHECK(tbl["int2"] == 42);
CHECK(tbl["int3"] == 0);
CHECK(tbl["int4"] == -17);
CHECK(tbl["int5"] == 1000);
CHECK(tbl["int6"] == 5349221);
CHECK(tbl["int7"] == 12345);
});
// "Each underscore must be surrounded by at least one digit on each side."
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);
// "Integer values -0 and +0 are valid and identical to an unprefixed zero."
parsing_should_succeed(
FILE_LINE_ARGS,
"zeroes = [-0, +0]"sv,
[](table&& tbl)
{
CHECK(tbl["zeroes"][0] == 0);
CHECK(tbl["zeroes"][1] == 0);
}
);
parsing_should_succeed(FILE_LINE_ARGS,
"zeroes = [-0, +0]"sv,
[](table&& tbl)
{
CHECK(tbl["zeroes"][0] == 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)."
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, "9223372036854775807"sv, INT64_MAX);
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 = -9223372036854775809"sv); // INT64_MIN - 1
@ -72,46 +68,44 @@ TEST_CASE("parsing - integers (decimal)")
parsing_should_fail(FILE_LINE_ARGS, "val = +1-"sv);
// value tests
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, "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, "123_456_789"sv, 123456789);
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, "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, "123_456_789"sv, 123456789);
}
TEST_CASE("parsing - integers (hex, bin, oct)")
{
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
# hexadecimal with prefix `0x`
hex1 = 0xDEADBEEF
hex2 = 0xdeadbeef
hex3 = 0xdead_beef
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# hexadecimal with prefix `0x`
hex1 = 0xDEADBEEF
hex2 = 0xdeadbeef
hex3 = 0xdead_beef
# octal with prefix `0o`
oct1 = 0o01234567
oct2 = 0o755 # useful for Unix file permissions
# octal with prefix `0o`
oct1 = 0o01234567
oct2 = 0o755 # useful for Unix file permissions
# binary with prefix `0b`
bin1 = 0b11010110
)"sv,
[](table&& tbl)
{
CHECK(tbl["hex1"] == 0xDEADBEEF);
CHECK(tbl["hex2"] == 0xDEADBEEF);
CHECK(tbl["hex3"] == 0xDEADBEEF);
CHECK(tbl["oct1"] == 01234567);
CHECK(tbl["oct2"] == 0755);
CHECK(tbl["bin1"] == 0b11010110);
}
);
# binary with prefix `0b`
bin1 = 0b11010110
)"sv,
[](table&& tbl)
{
CHECK(tbl["hex1"] == 0xDEADBEEF);
CHECK(tbl["hex2"] == 0xDEADBEEF);
CHECK(tbl["hex3"] == 0xDEADBEEF);
CHECK(tbl["oct1"] == 01234567);
CHECK(tbl["oct2"] == 0755);
CHECK(tbl["bin1"] == 0b11010110);
});
// "leading + is not allowed"
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);
// "leading zeros are allowed (after the prefix)"
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
hex1 = 0x000DEADBEEF
hex2 = 0x00000deadbeef
hex3 = 0x0dead_beef
oct1 = 0o0001234567
oct2 = 0o000755
bin1 = 0b0000011010110
)"sv,
[](table&& tbl)
{
CHECK(tbl["hex1"] == 0xDEADBEEF);
CHECK(tbl["hex2"] == 0xDEADBEEF);
CHECK(tbl["hex3"] == 0xDEADBEEF);
CHECK(tbl["oct1"] == 01234567);
CHECK(tbl["oct2"] == 0755);
CHECK(tbl["bin1"] == 0b11010110);
}
);
parsing_should_succeed(FILE_LINE_ARGS,
R"(
hex1 = 0x000DEADBEEF
hex2 = 0x00000deadbeef
hex3 = 0x0dead_beef
oct1 = 0o0001234567
oct2 = 0o000755
bin1 = 0b0000011010110
)"sv,
[](table&& tbl)
{
CHECK(tbl["hex1"] == 0xDEADBEEF);
CHECK(tbl["hex2"] == 0xDEADBEEF);
CHECK(tbl["hex3"] == 0xDEADBEEF);
CHECK(tbl["oct1"] == 01234567);
CHECK(tbl["oct2"] == 0755);
CHECK(tbl["bin1"] == 0b11010110);
});
// "***Non-negative*** integer values may also be expressed in hexadecimal, octal, or binary"
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)."
// (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, "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 = 0o1000000000000000000000"sv);
parsing_should_fail(FILE_LINE_ARGS, "val = 0b1000000000000000000000000000000000000000000000000000000000000000"sv);
// 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, "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, "0x00FF"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, "0o7_7_7"sv, 0777);
parse_expected_value(FILE_LINE_ARGS, "0o007"sv, 0007);
parse_expected_value(FILE_LINE_ARGS, "0b10000"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, "0b111111"sv, 0b111111);
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, "0xFF"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, "0o777"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, "0b10000"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, "0b111111"sv, 0b111111);
}

View File

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

View File

@ -7,9 +7,8 @@
TEST_CASE("parsing - strings")
{
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
str1 = """
@ -21,17 +20,16 @@ str2 = """
Roses are red
Violets are blue"""
)"sv,
[](table&& tbl)
{
CHECK(tbl["str"] == "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."sv);
CHECK(tbl["str1"] == "Roses are red\nViolets are blue"sv);
CHECK(tbl["str2"] == "\nRoses are red\nViolets are blue"sv);
}
);
[](table&& tbl)
{
CHECK(tbl["str"]
== "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."sv);
CHECK(tbl["str1"] == "Roses are red\nViolets are blue"sv);
CHECK(tbl["str2"] == "\nRoses are red\nViolets are blue"sv);
});
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# The following strings are byte-for-byte equivalent:
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."
str7 = """"This," she said, "is just a pointless statement.""""
)"sv,
[](table&& tbl)
{
static constexpr auto quick_brown_fox = "The quick brown fox jumps over the lazy dog."sv;
CHECK(tbl["str1"] == quick_brown_fox);
CHECK(tbl["str2"] == quick_brown_fox);
CHECK(tbl["str3"] == quick_brown_fox);
CHECK(tbl["str4"] == R"(Here are two quotation marks: "". Simple enough.)"sv);
CHECK(tbl["str5"] == R"(Here are three 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);
}
);
[](table&& tbl)
{
static constexpr auto quick_brown_fox = "The quick brown fox jumps over the lazy dog."sv;
CHECK(tbl["str1"] == quick_brown_fox);
CHECK(tbl["str2"] == quick_brown_fox);
CHECK(tbl["str3"] == quick_brown_fox);
CHECK(tbl["str4"] == R"(Here are two quotation marks: "". Simple enough.)"sv);
CHECK(tbl["str5"] == R"(Here are three 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);
});
parsing_should_fail(FILE_LINE_ARGS, R"(str5 = """Here are three quotation marks: """.""")"sv);
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# What you see is what you get.
winpath = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
@ -94,30 +90,28 @@ trimmed in raw strings.
is preserved.
'''
)"sv,
[](table&& tbl)
{
CHECK(tbl["winpath"] == R"(C:\Users\nodejs\templates)"sv);
CHECK(tbl["winpath2"] == R"(\\ServerX\admin$\system32\)"sv);
CHECK(tbl["quoted"] == R"(Tom "Dubs" Preston-Werner)"sv);
CHECK(tbl["regex"] == R"(<\i\c*\s*>)"sv);
CHECK(tbl["regex2"] == R"(I [dw]on't need \d{2} apples)"sv);
CHECK(tbl["lines"] == R"(The first newline is
[](table&& tbl)
{
CHECK(tbl["winpath"] == R"(C:\Users\nodejs\templates)"sv);
CHECK(tbl["winpath2"] == R"(\\ServerX\admin$\system32\)"sv);
CHECK(tbl["quoted"] == R"(Tom "Dubs" Preston-Werner)"sv);
CHECK(tbl["regex"] == R"(<\i\c*\s*>)"sv);
CHECK(tbl["regex2"] == R"(I [dw]on't need \d{2} apples)"sv);
CHECK(tbl["lines"] == R"(The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
)"sv);
CHECK(tbl["lines2"] == R"(
CHECK(tbl["lines2"] == R"(
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
)"sv);
}
);
});
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
quot15 = '''Here are fifteen quotation marks: """""""""""""""'''
# apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID
@ -126,77 +120,63 @@ apos15 = "Here are fifteen apostrophes: '''''''''''''''"
# 'That's still pointless', she said.
str = ''''That's still pointless', she said.'''
)"sv,
[](table&& tbl)
{
CHECK(tbl["quot15"] == R"(Here are fifteen quotation marks: """"""""""""""")"sv);
CHECK(tbl["apos15"] == R"(Here are fifteen apostrophes: ''''''''''''''')"sv);
CHECK(tbl["str"] == R"('That's still pointless', she said.)"sv);
}
);
[](table&& tbl)
{
CHECK(tbl["quot15"] == R"(Here are fifteen quotation marks: """"""""""""""")"sv);
CHECK(tbl["apos15"] == R"(Here are fifteen apostrophes: ''''''''''''''')"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);
// value tests
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);
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);
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);
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);
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);
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);
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);
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
parse_expected_value(
FILE_LINE_ARGS,
R"("Ýôú' λáƭè è áƒƭèř ƭλïƨ - #")"sv,
R"(Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #)"sv);
parse_expected_value(
FILE_LINE_ARGS,
R"(" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"")"sv,
R"( Âñδ ωλèñ "'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áôñϱ ωïƭλ # ")"sv);
parse_expected_value(
FILE_LINE_ARGS,
R"("Ýôú δôñ'ƭ ƭλïñƙ ƨôè úƨèř ωôñ'ƭ δô ƭλáƭ?")"sv,
R"(Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?)"sv);
#endif // UNICODE_LITERALS_OK
#if UNICODE_LITERALS_OK
parse_expected_value(FILE_LINE_ARGS, R"("Ýôú' λáƭè è áƒƭèř ƭλïƨ - #")"sv, R"(Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #)"sv);
parse_expected_value(FILE_LINE_ARGS,
R"(" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"")"sv,
R"( Âñδ ωλèñ "'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áôñϱ ωïƭλ # ")"sv);
parse_expected_value(FILE_LINE_ARGS,
R"("Ýôú δôñ'ƭ ƭλïñƙ ƨôè úƨèř ωôñ'ƭ δô ƭλáƭ?")"sv,
R"(Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?)"sv);
#endif // UNICODE_LITERALS_OK
parse_expected_value(
FILE_LINE_ARGS,
R"("\"\u03B1\u03B2\u03B3\"")"sv,
"\"\u03B1\u03B2\u03B3\""sv);
parse_expected_value(FILE_LINE_ARGS, R"("\"\u03B1\u03B2\u03B3\"")"sv, "\"\u03B1\u03B2\u03B3\""sv);
// toml/pull/709 (\xHH unicode scalars)
#if TOML_LANG_UNRELEASED
parse_expected_value(
FILE_LINE_ARGS,
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);
#else
parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv);
#endif
// toml/pull/709 (\xHH unicode scalars)
#if TOML_LANG_UNRELEASED
parse_expected_value(FILE_LINE_ARGS,
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);
#else
parsing_should_fail(FILE_LINE_ARGS, R"(str = "\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\x11\xFF\xEE")"sv);
#endif
// 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 = "\U123456")"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 = "\U123")"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 = "\U1234567")"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 = "\U1234")"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 = "\U1")"sv);
// 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 = "\u12")"sv);
parsing_should_fail(FILE_LINE_ARGS,R"(str = "\u1")"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 = "\u1")"sv);
// check 2-digit \x scalars with insufficient digits
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
// "Tables are defined by headers, with square brackets on a line by themselves."
parsing_should_succeed(
FILE_LINE_ARGS, "[table]"sv,
[](table&& tbl)
{
REQUIRE(tbl["table"].as_table());
CHECK(tbl["table"].as_table()->empty());
CHECK(tbl["table"].as_table()->size() == 0u);
}
);
parsing_should_succeed(FILE_LINE_ARGS,
"[table]"sv,
[](table&& tbl)
{
REQUIRE(tbl["table"].as_table());
CHECK(tbl["table"].as_table()->empty());
CHECK(tbl["table"].as_table()->size() == 0u);
});
parsing_should_fail(FILE_LINE_ARGS, "[]"sv);
// "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."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
[table-1]
key1 = "some string"
key2 = 123
@ -34,71 +32,65 @@ TEST_CASE("parsing - tables")
key1 = "another string"
key2 = 456
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["table-1"].as_table());
CHECK(tbl["table-1"].as_table()->size() == 2u);
CHECK(tbl["table-1"]["key1"] == "some string"sv);
CHECK(tbl["table-1"]["key2"] == 123);
[](table&& tbl)
{
REQUIRE(tbl["table-1"].as_table());
CHECK(tbl["table-1"].as_table()->size() == 2u);
CHECK(tbl["table-1"]["key1"] == "some string"sv);
CHECK(tbl["table-1"]["key2"] == 123);
REQUIRE(tbl["table-2"].as_table());
CHECK(tbl["table-2"].as_table()->size() == 2u);
CHECK(tbl["table-2"]["key1"] == "another string"sv);
CHECK(tbl["table-2"]["key2"] == 456);
}
);
REQUIRE(tbl["table-2"].as_table());
CHECK(tbl["table-2"].as_table()->size() == 2u);
CHECK(tbl["table-2"]["key1"] == "another string"sv);
CHECK(tbl["table-2"]["key2"] == 456);
});
// "Naming rules for tables are the same as for keys." (i.e. can be quoted)
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
[dog."tater.man"]
type.name = "pug"
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["dog"].as_table());
CHECK(tbl["dog"].as_table()->size() == 1u);
[](table&& tbl)
{
REQUIRE(tbl["dog"].as_table());
CHECK(tbl["dog"].as_table()->size() == 1u);
REQUIRE(tbl["dog"]["tater.man"].as_table());
CHECK(tbl["dog"]["tater.man"].as_table()->size() == 1u);
CHECK(tbl["dog"]["tater.man"]["type"]["name"] == "pug"sv);
}
);
REQUIRE(tbl["dog"]["tater.man"].as_table());
CHECK(tbl["dog"]["tater.man"].as_table()->size() == 1u);
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."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
[a.b.c] # this is best practice
[ d.e.f ] # same as [d.e.f]
[ g . h . i ] # same as [g.h.i]
[ j . "k" . 'l' ] # same as [j."k".'l']
)"sv,
[](table&& tbl)
{
CHECK(tbl["a"].as_table());
CHECK(tbl["a"]["b"].as_table());
CHECK(tbl["a"]["b"]["c"].as_table());
[](table&& tbl)
{
CHECK(tbl["a"].as_table());
CHECK(tbl["a"]["b"].as_table());
CHECK(tbl["a"]["b"]["c"].as_table());
CHECK(tbl["d"].as_table());
CHECK(tbl["d"]["e"].as_table());
CHECK(tbl["d"]["e"]["f"].as_table());
CHECK(tbl["d"].as_table());
CHECK(tbl["d"]["e"].as_table());
CHECK(tbl["d"]["e"]["f"].as_table());
CHECK(tbl["g"].as_table());
CHECK(tbl["g"]["h"].as_table());
CHECK(tbl["g"]["h"]["i"].as_table());
CHECK(tbl["g"].as_table());
CHECK(tbl["g"]["h"].as_table());
CHECK(tbl["g"]["h"]["i"].as_table());
CHECK(tbl["j"].as_table());
CHECK(tbl["j"]["k"].as_table());
CHECK(tbl["j"]["k"]["l"].as_table());
}
);
CHECK(tbl["j"].as_table());
CHECK(tbl["j"]["k"].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."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# [x] you
# [x.y] don't
# [x.y.z] need these
@ -106,14 +98,13 @@ TEST_CASE("parsing - tables")
[x] # defining a super-table afterwards is ok
)"sv,
[](table&& tbl)
{
CHECK(tbl["x"].as_table());
CHECK(tbl["x"]["y"].as_table());
CHECK(tbl["x"]["y"]["z"].as_table());
CHECK(tbl["x"]["y"]["z"]["w"].as_table());
}
);
[](table&& tbl)
{
CHECK(tbl["x"].as_table());
CHECK(tbl["x"]["y"].as_table());
CHECK(tbl["x"]["y"]["z"].as_table());
CHECK(tbl["x"]["y"]["z"]["w"].as_table());
});
// "Like keys, you cannot define a table more than once. Doing so is invalid."
parsing_should_fail(FILE_LINE_ARGS, R"(
@ -136,44 +127,39 @@ TEST_CASE("parsing - tables")
)"sv);
// "Defining tables out-of-order is discouraged."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# VALID BUT DISCOURAGED
[fruit.apple]
[animal]
[fruit.orange]
)"sv,
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["animal"].as_table());
CHECK(tbl["fruit"]["orange"].as_table());
}
);
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["animal"].as_table());
CHECK(tbl["fruit"]["orange"].as_table());
});
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# RECOMMENDED
[fruit.apple]
[fruit.orange]
[animal]
)"sv,
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["orange"].as_table());
CHECK(tbl["animal"].as_table());
}
);
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["orange"].as_table());
CHECK(tbl["animal"].as_table());
});
// "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)."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
# Top-level table begins.
name = "Fido"
breed = "pug"
@ -183,26 +169,24 @@ TEST_CASE("parsing - tables")
name = "Regina Dogman"
member_since = 1999-08-04
)"sv,
[](table&& tbl)
{
CHECK(tbl["name"].as_string());
CHECK(*tbl["name"].as_string() == "Fido"sv);
CHECK(tbl["breed"].as_string());
CHECK(*tbl["breed"].as_string() == "pug"sv);
[](table&& tbl)
{
CHECK(tbl["name"].as_string());
CHECK(*tbl["name"].as_string() == "Fido"sv);
CHECK(tbl["breed"].as_string());
CHECK(*tbl["breed"].as_string() == "pug"sv);
CHECK(tbl["owner"].as_table());
CHECK(*tbl["owner"]["name"].as_string() == "Regina Dogman"sv);
CHECK(tbl["owner"].as_table());
CHECK(*tbl["owner"]["name"].as_string() == "Regina Dogman"sv);
static constexpr auto member_since = toml::date{ 1999, 8, 4 };
CHECK(*tbl["owner"]["member_since"].as_date() == member_since);
}
);
static constexpr auto member_since = toml::date{ 1999, 8, 4 };
CHECK(*tbl["owner"]["member_since"].as_date() == member_since);
});
// "Dotted keys create and define a table for each key part before the last one,
// provided that such tables were not previously created."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
fruit.apple.color = "red"
# Defines a table named fruit
# Defines a table named fruit.apple
@ -211,18 +195,17 @@ TEST_CASE("parsing - tables")
# Defines a table named fruit.apple.taste
# fruit and fruit.apple were already created
)"sv,
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
CHECK(tbl["fruit"]["apple"]["taste"].as_table());
CHECK(tbl["fruit"]["apple"]["taste"]["sweet"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["taste"]["sweet"].as_boolean() == true);
}
);
CHECK(tbl["fruit"]["apple"]["taste"].as_table());
CHECK(tbl["fruit"]["apple"]["taste"]["sweet"].as_boolean());
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."
parsing_should_fail(FILE_LINE_ARGS, R"(
@ -257,9 +240,8 @@ TEST_CASE("parsing - tables")
)"sv);
// "The [table] form can, however, be used to define sub-tables within tables defined via dotted keys."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
[fruit]
apple.color = "red"
apple.taste.sweet = true
@ -267,18 +249,17 @@ TEST_CASE("parsing - tables")
[fruit.apple.texture] # you can add sub-tables
smooth = true
)"sv,
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
CHECK(tbl["fruit"]["apple"]["texture"].as_table());
CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true);
}
);
CHECK(tbl["fruit"]["apple"]["texture"].as_table());
CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true);
});
parsing_should_fail(FILE_LINE_ARGS, R"(
[fruit]
apple.color = "red"
@ -293,9 +274,8 @@ TEST_CASE("parsing - tables")
// same as above but the table order is reversed.
// see: https://github.com/toml-lang/toml/issues/769
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
[fruit.apple.texture]
smooth = true
@ -303,53 +283,50 @@ TEST_CASE("parsing - tables")
apple.color = "red"
apple.taste.sweet = true
)"sv,
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
[](table&& tbl)
{
CHECK(tbl["fruit"].as_table());
CHECK(tbl["fruit"]["apple"].as_table());
CHECK(tbl["fruit"]["apple"]["color"].as_string());
CHECK(*tbl["fruit"]["apple"]["color"].as_string() == "red"sv);
CHECK(tbl["fruit"]["apple"]["texture"].as_table());
CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true);
}
);
CHECK(tbl["fruit"]["apple"]["texture"].as_table());
CHECK(tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean());
CHECK(*tbl["fruit"]["apple"]["texture"]["smooth"].as_boolean() == true);
});
}
TEST_CASE("parsing - inline tables")
{
// these are the examples from https://toml.io/en/v1.0.0#inline-table
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
animal = { type.name = "pug" }
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["name"].as_table());
CHECK(tbl["name"].as_table()->size() == 2u);
CHECK(tbl["name"].as_table()->is_inline());
CHECK(tbl["name"]["first"] == "Tom"sv);
CHECK(tbl["name"]["last"] == "Preston-Werner"sv);
[](table&& tbl)
{
REQUIRE(tbl["name"].as_table());
CHECK(tbl["name"].as_table()->size() == 2u);
CHECK(tbl["name"].as_table()->is_inline());
CHECK(tbl["name"]["first"] == "Tom"sv);
CHECK(tbl["name"]["last"] == "Preston-Werner"sv);
REQUIRE(tbl["point"].as_table());
CHECK(tbl["point"].as_table()->size() == 2u);
CHECK(tbl["point"].as_table()->is_inline());
CHECK(tbl["point"]["x"] == 1);
CHECK(tbl["point"]["y"] == 2);
REQUIRE(tbl["point"].as_table());
CHECK(tbl["point"].as_table()->size() == 2u);
CHECK(tbl["point"].as_table()->is_inline());
CHECK(tbl["point"]["x"] == 1);
CHECK(tbl["point"]["y"] == 2);
REQUIRE(tbl["animal"].as_table());
CHECK(tbl["animal"].as_table()->size() == 1u);
CHECK(tbl["animal"].as_table()->is_inline());
REQUIRE(tbl["animal"]["type"].as_table());
CHECK(tbl["animal"]["type"].as_table()->size() == 1u);
CHECK(tbl["animal"]["type"]["name"] == "pug"sv);
}
);
REQUIRE(tbl["animal"].as_table());
CHECK(tbl["animal"].as_table()->size() == 1u);
CHECK(tbl["animal"].as_table()->is_inline());
REQUIRE(tbl["animal"]["type"].as_table());
CHECK(tbl["animal"]["type"].as_table()->size() == 1u);
CHECK(tbl["animal"]["type"]["name"] == "pug"sv);
});
// "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."
@ -367,176 +344,167 @@ TEST_CASE("parsing - inline tables")
)"sv);
// "newlines are allowed between the curly braces [if] they are valid within a value."
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
parsing_should_succeed(FILE_LINE_ARGS,
R"(
test = { val1 = "foo", val2 = [
1, 2,
3
], val3 = "bar" }
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["test"].as_table());
CHECK(tbl["test"].as_table()->size() == 3u);
CHECK(tbl["test"]["val1"] == "foo"sv);
REQUIRE(tbl["test"]["val2"].as<array>());
CHECK(tbl["test"]["val2"].as<array>()->size() == 3u);
CHECK(tbl["test"]["val2"][0] == 1);
CHECK(tbl["test"]["val2"][1] == 2);
CHECK(tbl["test"]["val2"][2] == 3);
CHECK(tbl["test"]["val3"] == "bar"sv);
}
);
[](table&& tbl)
{
REQUIRE(tbl["test"].as_table());
CHECK(tbl["test"].as_table()->size() == 3u);
CHECK(tbl["test"]["val1"] == "foo"sv);
REQUIRE(tbl["test"]["val2"].as<array>());
CHECK(tbl["test"]["val2"].as<array>()->size() == 3u);
CHECK(tbl["test"]["val2"][0] == 1);
CHECK(tbl["test"]["val2"][1] == 2);
CHECK(tbl["test"]["val2"][2] == 3);
CHECK(tbl["test"]["val3"] == "bar"sv);
});
// toml/issues/516 (newlines/trailing commas in inline tables)
#if TOML_LANG_UNRELEASED
// toml/issues/516 (newlines/trailing commas in inline tables)
#if TOML_LANG_UNRELEASED
{
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
name = {
first = "Tom",
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);
parsing_should_succeed(FILE_LINE_ARGS,
R"(
name = {
first = "Tom",
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);
});
}
#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);
// "No newlines are allowed between the curly braces unless they are valid within a value."
parsing_should_fail(FILE_LINE_ARGS, R"(
name = {
first = "Tom",
last = "Preston-Werner"
}
)"sv);
name = {
first = "Tom",
last = "Preston-Werner"
}
)"sv);
}
#endif
#endif
}
TEST_CASE("parsing - arrays-of-tables")
{
parsing_should_succeed(
FILE_LINE_ARGS,
R"(
points = [ { x = 1, y = 2, z = 3 },
{ x = 7, y = 8, z = 9 },
{ x = 2, y = 4, z = 8 } ]
parsing_should_succeed(FILE_LINE_ARGS,
R"(
points = [ { x = 1, y = 2, z = 3 },
{ x = 7, y = 8, z = 9 },
{ x = 2, y = 4, z = 8 } ]
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
[[products]]
[[products]]
name = "Nail"
sku = 284758393
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
color = "gray"
[[fruit]]
name = "apple"
[[fruit]]
name = "apple"
[fruit.physical] # subtable
color = "red"
shape = "round"
[fruit.physical] # subtable
color = "red"
shape = "round"
[[fruit.variety]] # nested array of tables
name = "red delicious"
[[fruit.variety]] # nested array of tables
name = "red delicious"
[[fruit.variety]]
name = "granny smith"
[[fruit.variety]]
name = "granny smith"
[[fruit]]
name = "banana"
[[fruit]]
name = "banana"
[[fruit.variety]]
name = "plantain"
[[fruit.variety]]
name = "plantain"
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["points"].as<array>());
CHECK(tbl["points"].as<array>()->size() == 3u);
CHECK(tbl["points"].as<array>()->is_homogeneous());
CHECK(tbl["points"].as<array>()->is_array_of_tables());
CHECK(tbl["points"][0]["x"] == 1);
CHECK(tbl["points"][0]["y"] == 2);
CHECK(tbl["points"][0]["z"] == 3);
CHECK(tbl["points"][1]["x"] == 7);
CHECK(tbl["points"][1]["y"] == 8);
CHECK(tbl["points"][1]["z"] == 9);
CHECK(tbl["points"][2]["x"] == 2);
CHECK(tbl["points"][2]["y"] == 4);
CHECK(tbl["points"][2]["z"] == 8);
)"sv,
[](table&& tbl)
{
REQUIRE(tbl["points"].as<array>());
CHECK(tbl["points"].as<array>()->size() == 3u);
CHECK(tbl["points"].as<array>()->is_homogeneous());
CHECK(tbl["points"].as<array>()->is_array_of_tables());
CHECK(tbl["points"][0]["x"] == 1);
CHECK(tbl["points"][0]["y"] == 2);
CHECK(tbl["points"][0]["z"] == 3);
CHECK(tbl["points"][1]["x"] == 7);
CHECK(tbl["points"][1]["y"] == 8);
CHECK(tbl["points"][1]["z"] == 9);
CHECK(tbl["points"][2]["x"] == 2);
CHECK(tbl["points"][2]["y"] == 4);
CHECK(tbl["points"][2]["z"] == 8);
REQUIRE(tbl["products"].as<array>());
CHECK(tbl["products"].as<array>()->size() == 3u);
CHECK(tbl["products"].as<array>()->is_homogeneous());
CHECK(tbl["products"].as<array>()->is_array_of_tables());
REQUIRE(tbl["products"].as<array>());
CHECK(tbl["products"].as<array>()->size() == 3u);
CHECK(tbl["products"].as<array>()->is_homogeneous());
CHECK(tbl["products"].as<array>()->is_array_of_tables());
REQUIRE(tbl["products"][0].as_table());
CHECK(tbl["products"][0].as_table()->size() == 2u);
CHECK(tbl["products"][0]["name"] == "Hammer"sv);
CHECK(tbl["products"][0]["sku"] == 738594937);
REQUIRE(tbl["products"][0].as_table());
CHECK(tbl["products"][0].as_table()->size() == 2u);
CHECK(tbl["products"][0]["name"] == "Hammer"sv);
CHECK(tbl["products"][0]["sku"] == 738594937);
REQUIRE(tbl["products"][1].as_table());
CHECK(tbl["products"][1].as_table()->size() == 0u);
REQUIRE(tbl["products"][1].as_table());
CHECK(tbl["products"][1].as_table()->size() == 0u);
REQUIRE(tbl["products"][2].as_table());
CHECK(tbl["products"][2].as_table()->size() == 3u);
CHECK(tbl["products"][2]["name"] == "Nail"sv);
CHECK(tbl["products"][2]["sku"] == 284758393);
CHECK(tbl["products"][2]["color"] == "gray"sv);
REQUIRE(tbl["products"][2].as_table());
CHECK(tbl["products"][2].as_table()->size() == 3u);
CHECK(tbl["products"][2]["name"] == "Nail"sv);
CHECK(tbl["products"][2]["sku"] == 284758393);
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>());
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"][0].as_table());
CHECK(tbl["fruit"][0].as_table()->size() == 3u);
CHECK(tbl["fruit"][0]["name"] == "apple"sv);
REQUIRE(tbl["fruit"][0].as_table());
CHECK(tbl["fruit"][0].as_table()->size() == 3u);
CHECK(tbl["fruit"][0]["name"] == "apple"sv);
REQUIRE(tbl["fruit"][0]["physical"].as_table());
CHECK(tbl["fruit"][0]["physical"].as_table()->size() == 2u);
CHECK(tbl["fruit"][0]["physical"]["color"] == "red"sv);
CHECK(tbl["fruit"][0]["physical"]["shape"] == "round"sv);
REQUIRE(tbl["fruit"][0]["physical"].as_table());
CHECK(tbl["fruit"][0]["physical"].as_table()->size() == 2u);
CHECK(tbl["fruit"][0]["physical"]["color"] == "red"sv);
CHECK(tbl["fruit"][0]["physical"]["shape"] == "round"sv);
REQUIRE(tbl["fruit"][0]["variety"].as<array>());
CHECK(tbl["fruit"][0]["variety"].as<array>()->size() == 2u);
CHECK(tbl["fruit"][0]["variety"].as<array>()->is_homogeneous());
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>());
CHECK(tbl["fruit"][0]["variety"].as<array>()->size() == 2u);
CHECK(tbl["fruit"][0]["variety"].as<array>()->is_homogeneous());
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());
CHECK(tbl["fruit"][1].as_table()->size() == 2u);
CHECK(tbl["fruit"][1]["name"] == "banana"sv);
REQUIRE(tbl["fruit"][1].as_table());
CHECK(tbl["fruit"][1].as_table()->size() == 2u);
CHECK(tbl["fruit"][1]["name"] == "banana"sv);
REQUIRE(tbl["fruit"][1]["variety"].as<array>());
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);
}
);
REQUIRE(tbl["fruit"][1]["variety"].as<array>());
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"(
# INVALID TOML DOC

View File

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

View File

@ -5,14 +5,14 @@
#include "tests.h"
bool parsing_should_succeed(
std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
pss_func&& func,
std::string_view source_path)
bool parsing_should_succeed(std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
pss_func&& func,
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&&
{
@ -29,7 +29,7 @@ bool parsing_should_succeed(
return std::move(tabl);
};
#if TOML_EXCEPTIONS
#if TOML_EXCEPTIONS
try
{
@ -52,15 +52,12 @@ bool parsing_should_succeed(
}
catch (const parse_error& err)
{
FORCE_FAIL(
"Parse error on line "sv << err.source().begin.line
<< ", column "sv << err.source().begin.column
<< ":\n"sv << err.description()
);
FORCE_FAIL("Parse error on line "sv << err.source().begin.line << ", column "sv << err.source().begin.column
<< ":\n"sv << err.description());
return false;
}
#else
#else
{
INFO("Parsing string directly"sv)
@ -74,11 +71,9 @@ bool parsing_should_succeed(
}
else
{
FORCE_FAIL(
"Parse error on line "sv << result.error().source().begin.line
<< ", column "sv << result.error().source().begin.column
<< ":\n"sv << result.error().description()
);
FORCE_FAIL("Parse error on line "sv << result.error().source().begin.line << ", column "sv
<< result.error().source().begin.column << ":\n"sv
<< result.error().description());
}
}
@ -96,29 +91,27 @@ bool parsing_should_succeed(
}
else
{
FORCE_FAIL(
"Parse error on line "sv << result.error().source().begin.line
<< ", column "sv << result.error().source().begin.column
<< ":\n"sv << result.error().description()
);
FORCE_FAIL("Parse error on line "sv << result.error().source().begin.line << ", column "sv
<< result.error().source().begin.column << ":\n"sv
<< result.error().description());
}
}
#endif
#endif
return true;
}
bool parsing_should_fail(
std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
source_index expected_failure_line,
source_index expected_failure_column)
bool parsing_should_fail(std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
source_index expected_failure_line,
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)
{
@ -130,17 +123,15 @@ bool parsing_should_fail(
{
if (ex_line != static_cast<source_index>(-1) && err.source().begin.line != ex_line)
{
FORCE_FAIL("Expected parse_error at line "sv << ex_line
<< ", actually occured at line "sv << err.source().begin.line
);
FORCE_FAIL("Expected parse_error at line "sv << ex_line << ", actually occured at line "sv
<< err.source().begin.line);
return false;
}
if (ex_col != static_cast<source_index>(-1) && err.source().begin.column != ex_col)
{
FORCE_FAIL("Expected parse_error at column "sv << ex_col
<< ", actually occured at column "sv << err.source().begin.column
);
FORCE_FAIL("Expected parse_error at column "sv << ex_col << ", actually occured at column "sv
<< err.source().begin.column);
return false;
}
@ -162,19 +153,21 @@ bool parsing_should_fail(
return false;
};
auto result = run_tests(expected_failure_line, expected_failure_column, [=]()
{
[[maybe_unused]] auto res = toml::parse(toml_str);
});
result = result && 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);
});
auto result = run_tests(expected_failure_line,
expected_failure_column,
[=]() { [[maybe_unused]] auto res = toml::parse(toml_str); });
result = result
&& 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);
});
return result;
#else
#else
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)
{
FORCE_FAIL("Expected parse_error at line "sv << ex_line
<< ", actually occured at line "sv << result.error().source().begin.line
);
FORCE_FAIL("Expected parse_error at line "sv << ex_line << ", actually occured at line "sv
<< result.error().source().begin.line);
}
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
<< ", actually occured at column "sv << result.error().source().begin.column
);
FORCE_FAIL("Expected parse_error at column "sv << ex_col << ", actually occured at column "sv
<< result.error().source().begin.column);
}
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); })
&& 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);
});
&& 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);
});
#endif
#endif
}
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<const node>>;
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<toml::node> const&);
template ReusableStringStream& ReusableStringStream::operator<<(toml::node_view<const toml::node> const&);
namespace Detail
{
template std::string stringify(const node_view<node>&);

View File

@ -7,82 +7,92 @@
#include "settings.h"
#if USE_TARTANLLAMA_OPTIONAL
#include "tloptional.h"
#include "lib_tloptional.h"
#endif
#if USE_SINGLE_HEADER
#include "../toml.hpp"
#include "../toml.hpp"
#else
#include "../include/toml++/toml.h"
#include "../include/toml++/toml.h"
#endif
#if defined(TOML_FP16) ^ SHOULD_HAVE_FP16
#error TOML_FP16 was not deduced correctly
#error TOML_FP16 was not deduced correctly
#endif
#if defined(TOML_FLOAT16) ^ SHOULD_HAVE_FLOAT16
#error TOML_FLOAT16 was not deduced correctly
#error TOML_FLOAT16 was not deduced correctly
#endif
#if defined(TOML_FLOAT128) ^ SHOULD_HAVE_FLOAT128
#error TOML_FLOAT128 was not deduced correctly
#error TOML_FLOAT128 was not deduced correctly
#endif
#if defined(TOML_INT128) ^ SHOULD_HAVE_INT128
#error TOML_INT128 was not deduced correctly
#error TOML_INT128 was not deduced correctly
#endif
#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
#if TOML_COMPILER_EXCEPTIONS != SHOULD_HAVE_EXCEPTIONS
#error TOML_COMPILER_EXCEPTIONS was not deduced correctly
#error TOML_COMPILER_EXCEPTIONS was not deduced correctly
#endif
#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
#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
#if TOML_ICC
#define UNICODE_LITERALS_OK 0
#define UNICODE_LITERALS_OK 0
#else
#define UNICODE_LITERALS_OK 1
#define UNICODE_LITERALS_OK 1
#endif
TOML_DISABLE_SPAM_WARNINGS;
TOML_DISABLE_ARITHMETIC_WARNINGS;
TOML_DISABLE_WARNINGS;
#include "catch2.h"
#include "lib_catch2.h"
#include <sstream>
namespace toml {}
namespace toml
{
}
using namespace Catch::literals;
using namespace toml;
TOML_ENABLE_WARNINGS;
#define FILE_LINE_ARGS std::string_view{ __FILE__ }, __LINE__
#define BOM_PREFIX "\xEF\xBB\xBF"
TOML_NODISCARD
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
#define FORCE_FAIL(...) FAIL(__VA_ARGS__)
#define FORCE_FAIL(...) FAIL(__VA_ARGS__)
#else
#define FORCE_FAIL(...) \
do \
{ \
FAIL(__VA_ARGS__); \
std::exit(-1); \
TOML_UNREACHABLE; \
} \
#define FORCE_FAIL(...) \
do \
{ \
FAIL(__VA_ARGS__); \
std::exit(-1); \
TOML_UNREACHABLE; \
} \
while (false)
#endif
#define CHECK_SYMMETRIC_RELOP(lhs, op, rhs, result) \
CHECK(((lhs) op (rhs)) == (result)); \
CHECK(((rhs) op (lhs)) == (result))
#define CHECK_SYMMETRIC_RELOP(lhs, op, rhs, result) \
CHECK(((lhs)op(rhs)) == (result)); \
CHECK(((rhs)op(lhs)) == (result))
#define CHECK_SYMMETRIC_EQUAL(lhs, rhs) \
CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, true); \
#define CHECK_SYMMETRIC_EQUAL(lhs, rhs) \
CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, true); \
CHECK_SYMMETRIC_RELOP(lhs, !=, rhs, false)
#define CHECK_SYMMETRIC_INEQUAL(lhs, rhs) \
CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, false); \
#define CHECK_SYMMETRIC_INEQUAL(lhs, rhs) \
CHECK_SYMMETRIC_RELOP(lhs, ==, rhs, false); \
CHECK_SYMMETRIC_RELOP(lhs, !=, rhs, true)
// 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>
class function_view<R(P...)> final
{
private:
using func_type = R(P...);
using eraser_func_type = R(void*, P&&...);
private:
using func_type = R(P...);
using eraser_func_type = R(void*, P&&...);
mutable void* ptr_ = {};
mutable eraser_func_type* eraser = {};
mutable void* ptr_ = {};
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>
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)...);
};
}
decltype(auto) operator()(P&&... xs) const
{
return eraser(ptr_, std::forward<P>(xs)...);
}
decltype(auto) operator()(P&&... xs) const
{
return eraser(ptr_, std::forward<P>(xs)...);
}
[[nodiscard]] operator bool() const noexcept { return !!ptr_; }
TOML_NODISCARD
operator bool() const noexcept
{
return !!ptr_;
}
};
using pss_func = function_view<void(toml::table&&)>;
bool parsing_should_succeed(
std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
pss_func&& func = {},
std::string_view source_path = {});
bool parsing_should_succeed(std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
pss_func&& func = {},
std::string_view source_path = {});
bool parsing_should_fail(
std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
source_index expected_failure_line = static_cast<source_index>(-1),
source_index expected_failure_column = static_cast<source_index>(-1));
bool parsing_should_fail(std::string_view test_file,
uint32_t test_line,
std::string_view toml_str,
source_index expected_failure_line = static_cast<source_index>(-1),
source_index expected_failure_column = static_cast<source_index>(-1));
template <typename T>
inline bool parse_expected_value(
std::string_view test_file,
uint32_t test_line,
std::string_view value_str,
const T& expected)
inline bool parse_expected_value(std::string_view test_file,
uint32_t test_line,
std::string_view value_str,
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;
static constexpr auto key = "val = "sv;
@ -159,7 +167,7 @@ inline bool parse_expected_value(
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{};
{
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>>;
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
const auto result = parsing_should_succeed(
@ -310,11 +319,10 @@ inline bool parse_expected_value(
// steal the val for round-trip tests
if (!stolen_value)
{
val_parsed = std::move(*nv.as<value_type>());
val_parsed = std::move(*nv.as<value_type>());
stolen_value = true;
}
}
);
});
if (!result)
return false;
@ -322,7 +330,8 @@ inline bool parse_expected_value(
// 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;
{
@ -333,25 +342,24 @@ inline bool parse_expected_value(
}
bool value_ok = true;
const auto parse_ok = parsing_should_succeed(
test_file,
test_line,
std::string_view{ str },
[&](table&& tbl)
{
REQUIRE(tbl.size() == 1);
auto nv = tbl["val"sv];
REQUIRE(nv);
REQUIRE(nv.as<value_type>());
REQUIRE(nv.node()->type() == impl::node_type_of<T>);
const auto parse_ok =
parsing_should_succeed(test_file,
test_line,
std::string_view{ str },
[&](table&& tbl)
{
REQUIRE(tbl.size() == 1);
auto nv = tbl["val"sv];
REQUIRE(nv);
REQUIRE(nv.as<value_type>());
REQUIRE(nv.node()->type() == impl::node_type_of<T>);
if (value_ok && nv.ref<value_type>() != expected)
{
value_ok = false;
FORCE_FAIL("Value was not the same after round-tripping"sv);
}
}
);
if (value_ok && nv.ref<value_type>() != expected)
{
value_ok = false;
FORCE_FAIL("Value was not the same after round-tripping"sv);
}
});
if (!parse_ok || value_ok)
return false;
@ -377,8 +385,8 @@ namespace Catch
{
extern template struct StringMaker<node_view<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<const node> const&);
extern template ReusableStringStream& ReusableStringStream::operator<<(node_view<node> const&);
extern template ReusableStringStream& ReusableStringStream::operator<<(node_view<const node> const&);
namespace Detail
{
extern template std::string stringify(const node_view<node>&);

View File

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

View File

@ -13,77 +13,64 @@ TEST_CASE("user feedback")
{
toml::table t1;
t1.insert_or_assign("bar1", toml::array{ 1, 2, 3 });
CHECK(t1 == toml::table{{
{ "bar1"sv, toml::array{ 1, 2, 3 } }
}});
CHECK(t1 == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } } } });
t1.insert_or_assign("foo1", *t1.get("bar1"));
CHECK(t1 == toml::table{{
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3 } }
}});
CHECK(t1 == toml::table{ { { "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?
// - yes -
// t1["foo1"] = t1["bar1"]; // does nothing, should this fail to compile?
// - yes -
//*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-
toml::array* array1 = t1["foo1"].node()->as_array();
array1->push_back(4);
CHECK(t1 == toml::table{{
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } }
}});
CHECK(t1 == toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } }, { "foo1"sv, toml::array{ 1, 2, 3, 4 } } } });
t1.insert_or_assign("foo3", t1["foo1"]);
CHECK(t1 == toml::table{{
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } }
}});
CHECK(t1
== toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
t1.insert_or_assign("foo2", *t1["foo1"].node());
CHECK(t1 == toml::table{{
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } }
}});
CHECK(t1
== toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
toml::array* array2 = t1["foo2"].node()->as_array();
array2->push_back("wrench");
CHECK(t1 == toml::table{{
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } }
}});
CHECK(t1
== toml::table{ { { "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
toml::table t2 = t1;
CHECK(t2 == t1);
CHECK(&t2 != &t1);
//t2.emplace("bar", toml::array{6, 7}); // fails to compile? not sure what I did wrong
// - it should be this: -
// t2.emplace("bar", toml::array{6, 7}); // fails to compile? not sure what I did wrong
// - it should be this: -
t2.emplace<toml::array>("bar", 6, 7);
CHECK(t2 == toml::table{{
{ "bar"sv, toml::array{ 6, 7 } },
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } }
}});
CHECK(t2
== toml::table{ { { "bar"sv, toml::array{ 6, 7 } },
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
t2.insert_or_assign("bar2", toml::array{ 6, 7 });
CHECK(t2 == toml::table{{
{ "bar"sv, toml::array{ 6, 7 } },
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "bar2"sv, toml::array{ 6, 7 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } }
}});
CHECK(t2
== toml::table{ { { "bar"sv, toml::array{ 6, 7 } },
{ "bar1"sv, toml::array{ 1, 2, 3 } },
{ "bar2"sv, toml::array{ 6, 7 } },
{ "foo1"sv, toml::array{ 1, 2, 3, 4 } },
{ "foo2"sv, toml::array{ 1, 2, 3, 4, "wrench" } },
{ "foo3"sv, toml::array{ 1, 2, 3, 4 } } } });
}
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
// - overlong numeric literals
// 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, "1= 0x6cA#+\xf1");
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\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\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"
);
parsing_should_fail(FILE_LINE_ARGS,
R"(t =[ 9, 2, 1,"r", 9999999999999999999999999999999999999999999999999999999999999995.0 ])"
);
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c' 'ml'\n\n%\x87");
parsing_should_fail(
FILE_LINE_ARGS,
R"(t =[ 9, 2, 1,"r", 9999999999999999999999999999999999999999999999999999999999999995.0 ])");
}
SECTION("github/issues/67") // https://github.com/marzer/tomlplusplus/issues/67
{
const auto data = R"(array=["v1", "v2", "v3"])"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table)
{
auto arr = table["array"].as_array();
for (auto it = arr->cbegin(); it != arr->cend();)
if (it->value_or(std::string_view{}) == "v2"sv)
it = arr->erase(it);
else
++it;
CHECK(arr->size() == 2);
});
parsing_should_succeed(FILE_LINE_ARGS,
data,
[](auto&& table)
{
auto arr = table["array"].as_array();
for (auto it = arr->cbegin(); it != arr->cend();)
if (it->value_or(std::string_view{}) == "v2"sv)
it = arr->erase(it);
else
++it;
CHECK(arr->size() == 2);
});
}
SECTION("github/issues/68") // https://github.com/marzer/tomlplusplus/issues/68
{
const auto data = R"(array=["v1", "v2", "v3"])"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table)
{
std::stringstream ss;
ss << table;
CHECK(ss.str() == "array = [ 'v1', 'v2', 'v3' ]"sv);
});
parsing_should_succeed(FILE_LINE_ARGS,
data,
[](auto&& table)
{
std::stringstream ss;
ss << table;
CHECK(ss.str() == "array = [ 'v1', 'v2', 'v3' ]"sv);
});
}
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
)"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table)
{
std::stringstream ss;
ss << table;
CHECK(ss.str() == R"(a = { key = 1 }
parsing_should_succeed(FILE_LINE_ARGS,
data,
[](auto&& table)
{
std::stringstream ss;
ss << table;
CHECK(ss.str() == R"(a = { key = 1 }
b = []
[[c]])"sv);
});
});
}
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
{
parsing_should_fail(FILE_LINE_ARGS, R"(
parsing_should_fail(FILE_LINE_ARGS,
R"(
[a.b.c.d]
u = 6
[a]
b.t = 8
[a.b] # should cause redefinition error here
u = 0
)", 6);
)",
6);
parsing_should_fail(FILE_LINE_ARGS, R"(
parsing_should_fail(FILE_LINE_ARGS,
R"(
[a]
b.t = 8
[a.b] # should cause redefinition error here
u = 0
)", 4);
)",
4);
}
}

View File

@ -9,47 +9,45 @@ TEST_CASE("using iterators")
constexpr auto data = R"(array=[1,"Foo",true]
string="Bar"
number=5)"sv;
parsing_should_succeed(FILE_LINE_ARGS, data, [](auto&& table)
{
const auto table_begin = table.begin();
const auto table_end = table.end();
auto count_table_lambda = [table_begin, table_end](node_type type) noexcept
parsing_should_succeed(
FILE_LINE_ARGS,
data,
[](auto&& table)
{
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(count_table_lambda(node_type::table) == 0);
CHECK(count_table_lambda(node_type::integer) == 1);
CHECK(count_table_lambda(node_type::string) == 1);
CHECK(std::next(table_begin, 3) == table_end);
CHECK(std::distance(table_begin, table_end) == 3);
CHECK(count_table_lambda(node_type::table) == 0);
CHECK(count_table_lambda(node_type::integer) == 1);
CHECK(count_table_lambda(node_type::string) == 1);
CHECK(std::next(table_begin, 3) == table_end);
const auto array_iter = std::find_if(table_begin, table_end, [](const auto& pair) noexcept
{
return pair.second.is_array();
const auto array_iter =
std::find_if(table_begin, table_end, [](const auto& pair) noexcept { 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" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\catch2.h" />
<ClInclude Include="..\leakproof.h" />
<ClInclude Include="..\lib_catch2.h" />
<ClInclude Include="..\lib_tloptional.h" />
<ClInclude Include="..\settings.h" />
<ClInclude Include="..\tests.h" />
<ClInclude Include="..\tloptional.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\cpp.hint" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

239
toml.hpp
View File

@ -546,13 +546,6 @@
#define TOML_UNREACHABLE TOML_ASSERT(false)
#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
#define TOML_HAS_ATTR(...) __has_cpp_attribute(__VA_ARGS__)
#else
@ -766,7 +759,9 @@
#define TOML_EXTERNAL_LINKAGE inline
#define TOML_INTERNAL_LINKAGE inline
#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
#define TOML_EXTERNAL_LINKAGE
@ -1024,15 +1019,6 @@ TOML_NAMESPACE_START
class parse_result;
#endif
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;
@ -4736,14 +4722,13 @@ TOML_NAMESPACE_START
TOML_API
array& operator=(array&& rhs) noexcept;
TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0_sz
|| !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
TOML_CONSTRAINED_TEMPLATE((sizeof...(ElemTypes) > 0 || !std::is_same_v<impl::remove_cvref_t<ElemType>, array>),
typename ElemType,
typename... ElemTypes)
TOML_NODISCARD_CTOR
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));
if constexpr (sizeof...(ElemTypes) > 0)
{
@ -4949,7 +4934,7 @@ TOML_NAMESPACE_START
const auto start_idx = static_cast<size_t>(pos.raw_ - elements.cbegin());
preinsertion_resize(start_idx, count);
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(static_cast<ElemType&&>(val)));
@ -5119,7 +5104,7 @@ TOML_NAMESPACE_START
if (lhs.size() != rhs.size())
return false;
if (rhs.size() == 0_sz)
if (rhs.size() == 0u)
return true;
size_t i{};
@ -5501,12 +5486,15 @@ TOML_NAMESPACE_START
}
TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype) const noexcept final;
TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype, node*& first_nonmatch) noexcept final;
TOML_NODISCARD
TOML_API
bool is_homogeneous(node_type ntype, const node*& first_nonmatch) const noexcept final;
template <typename ElemType = void>
@ -7528,7 +7516,7 @@ TOML_NAMESPACE_START
std::vector<std::string> key_path_;
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_API
@ -8057,26 +8045,26 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
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('-');
print_integer_leftpad_zeros(stream, val.month, 2_sz);
print_integer_leftpad_zeros(stream, val.month, 2u);
stream.put('-');
print_integer_leftpad_zeros(stream, val.day, 2_sz);
print_integer_leftpad_zeros(stream, val.day, 2u);
}
TOML_EXTERNAL_LINKAGE
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(':');
print_integer_leftpad_zeros(stream, val.minute, 2_sz);
print_integer_leftpad_zeros(stream, val.minute, 2u);
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)
{
stream.put('.');
auto ns = val.nanosecond;
size_t digits = 9_sz;
size_t digits = 9u;
while (ns % 10u == 0u)
{
ns /= 10u;
@ -8106,13 +8094,13 @@ TOML_IMPL_NAMESPACE_START
const auto hours = mins / 60;
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;
}
else
print_to_stream(stream, "00"sv);
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
@ -8476,14 +8464,14 @@ TOML_NAMESPACE_START
void array::preinsertion_resize(size_t idx, size_t count) noexcept
{
TOML_ASSERT(idx <= elements.size());
TOML_ASSERT(count >= 1_sz);
TOML_ASSERT(count >= 1u);
const auto old_size = elements.size();
const auto new_size = old_size + count;
const auto inserting_at_end = idx == old_size;
elements.resize(new_size);
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]);
}
}
@ -8547,7 +8535,7 @@ TOML_NAMESPACE_START
for (size_t i = 0, e = elements.size(); i < e; i++)
{
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;
}
@ -8577,14 +8565,14 @@ TOML_NAMESPACE_START
bool requires_flattening = false;
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();
if (!arr)
continue;
size_after_flattening--; // discount the array itself
const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 0_sz)
if (leaf_count > 0u)
{
requires_flattening = true;
size_after_flattening += leaf_count;
@ -8610,8 +8598,8 @@ TOML_NAMESPACE_START
std::unique_ptr<node> arr_storage = std::move(elements[i]);
const auto leaf_count = arr->total_leaf_count();
if (leaf_count > 1_sz)
preinsertion_resize(i + 1_sz, leaf_count - 1_sz);
if (leaf_count > 1u)
preinsertion_resize(i + 1u, leaf_count - 1u);
flatten_child(std::move(*arr), i); // increments i
}
@ -8814,7 +8802,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char>
class utf8_byte_stream<std::basic_string_view<Char>>
{
static_assert(sizeof(Char) == 1_sz);
static_assert(sizeof(Char) == 1);
private:
std::basic_string_view<Char> source_;
@ -8828,20 +8816,20 @@ TOML_ANON_NAMESPACE_START
// trim trailing nulls
const size_t initial_len = source_.length();
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'
{
actual_len = i + 1_sz;
actual_len = i + 1u;
break;
}
}
if (initial_len != actual_len)
source_ = source_.substr(0_sz, actual_len);
source_ = source_.substr(0u, actual_len);
// skip bom
if (actual_len >= 3_sz && memcmp(utf8_byte_order_mark.data(), source_.data(), 3_sz) == 0)
position_ += 3_sz;
if (actual_len >= 3u && memcmp(utf8_byte_order_mark.data(), source_.data(), 3u) == 0)
position_ += 3u;
}
TOML_NODISCARD
@ -8877,7 +8865,7 @@ TOML_ANON_NAMESPACE_START
template <typename Char>
class utf8_byte_stream<std::basic_istream<Char>>
{
static_assert(sizeof(Char) == 1_sz);
static_assert(sizeof(Char) == 1);
private:
std::basic_istream<Char>* source_;
@ -8893,7 +8881,7 @@ TOML_ANON_NAMESPACE_START
const auto initial_pos = source_->tellg();
Char 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;
source_->clear();
@ -8941,7 +8929,7 @@ TOML_ANON_NAMESPACE_START
TOML_NODISCARD
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
@ -9032,7 +9020,7 @@ TOML_ANON_NAMESPACE_START
{
TOML_ERROR_CHECK;
auto& prev = codepoints_[(cp_idx_ - 1_sz) % 2_sz];
auto& prev = codepoints_[(cp_idx_ - 1u) % 2u];
if (stream_.eof())
return nullptr;
@ -9096,7 +9084,7 @@ TOML_ANON_NAMESPACE_START
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);
if (decoder_.has_code_point())
{
@ -9725,7 +9713,7 @@ TOML_IMPL_NAMESPACE_START
TOML_NEVER_INLINE
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 (err)
return;
@ -9750,7 +9738,7 @@ TOML_IMPL_NAMESPACE_START
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();
assert_or_assume(count);
@ -9793,7 +9781,7 @@ TOML_IMPL_NAMESPACE_START
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();
@ -9802,7 +9790,7 @@ TOML_IMPL_NAMESPACE_START
{
if (pop_bytes >= recording_buffer.length())
recording_buffer.clear();
else if (pop_bytes == 1_sz)
else if (pop_bytes == 1u)
recording_buffer.pop_back();
else
recording_buffer.erase(recording_buffer.begin()
@ -10081,7 +10069,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line)
{
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
size_t consecutive_delimiters = 1;
do
{
advance_and_return_if_error({});
@ -10091,30 +10079,30 @@ TOML_IMPL_NAMESPACE_START
else
break;
}
while (lookaheads < 4_sz);
while (lookaheads < 4u);
switch (consecutive_delimiters)
{
// """ " (one quote somewhere in a ML string)
case 1_sz:
case 1:
str += '"';
skipping_whitespace = false;
continue;
// """ "" (two quotes somewhere in a ML string)
case 2_sz:
case 2:
str.append("\"\""sv);
skipping_whitespace = false;
continue;
// """ """ (the end of the string)
case 3_sz: return str;
case 3: return str;
// """ """" (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)
case 5_sz:
case 5:
str.append("\"\""sv);
advance_and_return_if_error({}); // skip the last '"'
return str;
@ -10210,7 +10198,7 @@ TOML_IMPL_NAMESPACE_START
if (multi_line)
{
size_t lookaheads = {};
size_t consecutive_delimiters = 1_sz;
size_t consecutive_delimiters = 1;
do
{
advance_and_return_if_error({});
@ -10220,24 +10208,24 @@ TOML_IMPL_NAMESPACE_START
else
break;
}
while (lookaheads < 4_sz);
while (lookaheads < 4u);
switch (consecutive_delimiters)
{
// ''' ' (one quote somewhere in a ML string)
case 1_sz: str += '\''; continue;
case 1: str += '\''; continue;
// ''' '' (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)
case 3_sz: return str;
case 3: return str;
// ''' '''' (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)
case 5_sz:
case 5:
str.append("''"sv);
advance_and_return_if_error({}); // skip the last '
return str;
@ -10320,7 +10308,7 @@ TOML_IMPL_NAMESPACE_START
{
// step back two characters so that the current
// character is the string delimiter
go_back(2_sz);
go_back(2u);
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);
// 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);
else
@ -10665,7 +10653,7 @@ TOML_IMPL_NAMESPACE_START
}
// 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_default("missing exponent"sv);
@ -10696,7 +10684,7 @@ TOML_IMPL_NAMESPACE_START
// calculate value
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;
uint32_t val{};
while (place)
@ -10810,7 +10798,7 @@ TOML_IMPL_NAMESPACE_START
}
// single digits can be converted trivially
if (length == 1_sz)
if (length == 1u)
{
if constexpr (base == 16)
return static_cast<int64_t>(hex_to_dec(chars[0]));
@ -10860,7 +10848,7 @@ TOML_IMPL_NAMESPACE_START
// "YYYY"
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);
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));
@ -10872,7 +10860,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto month = digits[1] + digits[0] * 10u;
if (month == 0u || month > 12u)
@ -10889,7 +10877,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto day = digits[1] + digits[0] * 10u;
if (day == 0u || day > max_days_in_month)
@ -10912,11 +10900,11 @@ TOML_IMPL_NAMESPACE_START
assert_or_assume(is_decimal_digit(*cp));
push_parse_scope("time"sv);
static constexpr auto max_digits = 9_sz;
static constexpr size_t max_digits = 9;
uint32_t digits[max_digits];
// "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);
const auto hour = digits[1] + digits[0] * 10u;
if (hour > 23u)
@ -10930,7 +10918,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto minute = digits[1] + digits[0] * 10u;
if (minute > 59u)
@ -10954,7 +10942,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto second = digits[1] + digits[0] * 10u;
if (second > 59u)
@ -10970,7 +10958,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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)
{
set_error_and_return_if_eof({});
@ -10987,7 +10975,7 @@ TOML_IMPL_NAMESPACE_START
uint32_t value = 0u;
uint32_t place = 1u;
for (auto i = digit_count; i-- > 0_sz;)
for (auto i = digit_count; i-- > 0u;)
{
value += digits[i] * place;
place *= 10u;
@ -11039,7 +11027,7 @@ TOML_IMPL_NAMESPACE_START
// "HH"
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);
const auto hour = digits[1] + digits[0] * 10;
if (hour > 23)
@ -11053,7 +11041,7 @@ TOML_IMPL_NAMESPACE_START
advance_and_return_if_error_or_eof({});
// "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);
const auto minute = digits[1] + digits[0] * 10;
if (minute > 59)
@ -11223,19 +11211,19 @@ TOML_IMPL_NAMESPACE_START
switch (static_cast<char32_t>(c | 32u))
{
case U'b':
if (char_count == 2_sz && has_any(begins_zero))
if (char_count == 2u && has_any(begins_zero))
add_trait(has_b);
break;
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_plus | has_minus) || has_any(begins_sign)))
add_trait(has_e);
break;
case U'o':
if (char_count == 2_sz && has_any(begins_zero))
if (char_count == 2u && has_any(begins_zero))
add_trait(has_o);
break;
@ -11245,8 +11233,8 @@ TOML_IMPL_NAMESPACE_START
break;
case U'x':
if ((char_count == 2_sz && has_any(begins_zero))
|| (char_count == 3_sz && has_any(begins_sign) && chars[1] == U'0'))
if ((char_count == 2u && has_any(begins_zero))
|| (char_count == 3u && has_any(begins_sign) && chars[1] == U'0'))
add_trait(has_x);
break;
@ -11278,7 +11266,7 @@ TOML_IMPL_NAMESPACE_START
return_if_error({});
// 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' ')
{
const auto pre_advance_count = advance_count;
@ -11291,7 +11279,7 @@ TOML_IMPL_NAMESPACE_START
go_back(advance_count - pre_advance_count);
advance_count = pre_advance_count;
traits = pre_scan_traits;
char_count = 10_sz;
char_count = 10u;
};
advance_and_return_if_error({});
@ -11309,19 +11297,19 @@ TOML_IMPL_NAMESPACE_START
scan();
return_if_error({});
if (char_count == 12_sz)
if (char_count == 12u)
backpedal();
}
}
// set the reader back to where we started
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';
// if after scanning ahead we still only have one value character,
// the only valid value type is an integer.
if (char_count == 1_sz)
if (char_count == 1u)
{
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
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
// 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))
{
// 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) };
advance(); // skip the sign
@ -11670,7 +11658,7 @@ TOML_IMPL_NAMESPACE_START
// get the key
start_recording();
auto key = parse_key();
stop_recording(1_sz);
stop_recording(1u);
// skip past any whitespace that followed the key
consume_leading_whitespace();
@ -11736,7 +11724,7 @@ TOML_IMPL_NAMESPACE_START
// get the actual key
start_recording();
key = parse_key();
stop_recording(1_sz);
stop_recording(1u);
return_if_error({});
// 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.
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]);
if (!child)
@ -11893,13 +11881,13 @@ TOML_IMPL_NAMESPACE_START
auto kvp = parse_key_value_pair();
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,
// 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]);
if (!child)
@ -12279,7 +12267,7 @@ TOML_ANON_NAMESPACE_START
// open file with a custom-sized stack buffer
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.open(file_path_str, std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
if (!file.is_open())
@ -12657,7 +12645,7 @@ TOML_NAMESPACE_START
if (requires_quotes)
{
std::string s;
s.reserve(str.length() + 2_sz);
s.reserve(str.length() + 2u);
s += '"';
for (auto c : str)
{
@ -12687,11 +12675,11 @@ TOML_NAMESPACE_START
{
auto& n = *reinterpret_cast<const table*>(&node);
if (n.empty())
return 2_sz; // "{}"
size_t weight = 3_sz; // "{ }"
return 2u; // "{}"
size_t weight = 3u; // "{ }"
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)
break;
}
@ -12702,11 +12690,11 @@ TOML_NAMESPACE_START
{
auto& n = *reinterpret_cast<const array*>(&node);
if (n.empty())
return 2_sz; // "[]"
size_t weight = 3_sz; // "[ ]"
return 2u; // "[]"
size_t weight = 3u; // "[ ]"
for (auto& elem : n)
{
weight += count_inline_columns(elem) + 2_sz; // + ", "
weight += count_inline_columns(elem) + 2u; // + ", "
if (weight >= line_wrap_cols)
break;
}
@ -12716,7 +12704,7 @@ TOML_NAMESPACE_START
case node_type::string:
{
auto& n = *reinterpret_cast<const value<std::string>*>(&node);
return n.get().length() + 2_sz; // + ""
return n.get().length() + 2u; // + ""
}
case node_type::integer:
@ -12724,14 +12712,14 @@ TOML_NAMESPACE_START
auto& n = *reinterpret_cast<const value<int64_t>*>(&node);
auto v = n.get();
if (!v)
return 1_sz;
return 1u;
size_t weight = {};
if (v < 0)
{
weight += 1;
weight += 1u;
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:
@ -12739,21 +12727,21 @@ TOML_NAMESPACE_START
auto& n = *reinterpret_cast<const value<double>*>(&node);
auto v = n.get();
if (v == 0.0)
return 3_sz; // "0.0"
size_t weight = 2_sz; // ".0"
return 3u; // "0.0"
size_t weight = 2u; // ".0"
if (v < 0.0)
{
weight += 1;
weight += 1u;
v *= -1.0;
}
return weight + static_cast<size_t>(log10(v)) + 1_sz;
return weight + static_cast<size_t>(log10(v)) + 1u;
break;
}
case node_type::boolean: return 5_sz;
case node_type::boolean: return 5u;
case node_type::date: [[fallthrough]];
case node_type::time: return 10_sz;
case node_type::date_time: return 30_sz;
case node_type::time: return 10u;
case node_type::date_time: return 30u;
case node_type::none: TOML_UNREACHABLE;
default: TOML_UNREACHABLE;
}
@ -12879,7 +12867,7 @@ TOML_NAMESPACE_START
for (size_t i = 0; i < arr.size(); i++)
{
if (i > 0_sz)
if (i > 0u)
{
impl::print_to_stream(base::stream(), ',');
if (!multiline)
@ -12921,7 +12909,7 @@ TOML_NAMESPACE_START
static constexpr auto is_non_inline_array_of_tables = [](auto&& nde) noexcept
{
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
@ -12984,7 +12972,7 @@ TOML_NAMESPACE_START
}
}
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;
key_path_.push_back(make_key_segment(k));
@ -13121,7 +13109,7 @@ TOML_NAMESPACE_START
base::increase_indent();
for (size_t i = 0; i < arr.size(); i++)
{
if (i > 0_sz)
if (i > 0u)
impl::print_to_stream(base::stream(), ',');
base::print_newline(true);
base::print_indent();
@ -13186,7 +13174,6 @@ TOML_POP_WARNINGS;
#undef TOML_COMPILER_EXCEPTIONS
#undef TOML_CONCAT
#undef TOML_CONCAT_1
#undef TOML_CONSTEVAL
#undef TOML_CONSTRAINED_TEMPLATE
#undef TOML_CPP
#undef TOML_DISABLE_ARITHMETIC_WARNINGS

View File

@ -10,6 +10,7 @@ REM ----------------------------------------------------------------------------
CALL :RunClangFormatOnDirectories ^
include\toml++ ^
include\toml++\impl ^
tests ^
examples
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)
# preamble
write('// 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('// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.')
write('// SPDX-License-Identifier: MIT')
write('//-----')
write('// this file was generated by generate_conformance_tests.py - do not modify it directly')
write('')
write('#include "tests.h"')
write('using namespace toml::impl;')
write('')
write(r'// This file is a part of toml++ and is subject to the the terms of the MIT license.')
write(r'// Copyright (c) Mark Gillard <mark.gillard@outlook.com.au>')
write(r'// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.')
write(r'// SPDX-License-Identifier: MIT')
write(r'//-----')
write(r'// this file was generated by generate_conformance_tests.py - do not modify it directly')
write(r'// clang-format off')
write(r'')
write(r'#include "tests.h"')
write(r'using namespace toml::impl;')
write(r'')
# test data
write('TOML_DISABLE_WARNINGS; // unused variable spam')

View File

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