fixed inf and nan being formatted incorrectly by the json_formatter

also:
- added `formatter_flags::quote_infinities_and_nans`
- made constructors for dates/times accept any integral types
- lots of internal work on formatter base (laying groundwork for more customization)
This commit is contained in:
Mark Gillard 2021-10-29 23:59:53 +03:00
parent 97132cb27c
commit f2fe57d21f
51 changed files with 695 additions and 378 deletions

View File

@ -105,8 +105,6 @@ namespace
int main()
{
examples::init();
for (auto str : invalid_parses)
{
if (str.empty())

View File

@ -28,17 +28,9 @@
#include <windows.h>
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif
namespace examples
namespace
{
inline void init() noexcept
static const auto initialize_environment_automagically = []() noexcept
{
#ifdef _WIN32
SetConsoleOutputCP(65001); // CP_UTF8
@ -48,5 +40,15 @@ namespace examples
std::cout << std::boolalpha;
srand(static_cast<unsigned int>(time(nullptr)));
}
return true;
}();
}
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif

View File

@ -14,8 +14,6 @@ using namespace std::string_view_literals;
int main(int argc, char** argv)
{
examples::init();
const auto path = argc > 1 ? std::string_view{ argv[1] } : "example.toml"sv;
try
{

View File

@ -93,8 +93,6 @@ namespace
int main(int argc, char** argv)
{
examples::init();
int node_budget{};
for (int i = 1; i < argc; i++)
{

View File

@ -14,8 +14,6 @@ using namespace std::string_view_literals;
int main(int argc, char** argv)
{
examples::init();
toml::table table;
try
{

View File

@ -22,6 +22,19 @@ TOML_NAMESPACE_START
/// \brief The day component, from 1 - 31.
uint8_t day;
/// \brief Default constructor. Does not initialize the members.
TOML_NODISCARD_CTOR
date() noexcept = default;
/// \brief Constructs a date from individual date component values.
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<Y, M, D>), typename Y, typename M, typename D)
TOML_NODISCARD_CTOR
constexpr date(Y y, M m, D d) noexcept //
: year{ static_cast<uint16_t>(y) },
month{ static_cast<uint8_t>(m) },
day{ static_cast<uint8_t>(d) }
{}
/// \brief Equality operator.
TOML_NODISCARD
friend constexpr bool operator==(const date& lhs, const date& rhs) noexcept
@ -105,6 +118,24 @@ TOML_NAMESPACE_START
/// \brief The fractional nanoseconds component, from 0 - 999999999.
uint32_t nanosecond;
/// \brief Default constructor. Does not initialize the members.
TOML_NODISCARD_CTOR
time() noexcept = default;
/// \brief Constructs a time from individual time component values.
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M, S, NS>),
typename H,
typename M,
typename S = uint8_t,
typename NS = uint32_t)
TOML_NODISCARD_CTOR
constexpr time(H h, M m, S s = S{}, NS ns = NS{}) noexcept //
: hour{ static_cast<uint8_t>(h) },
minute{ static_cast<uint8_t>(m) },
second{ static_cast<uint8_t>(s) },
nanosecond{ static_cast<uint32_t>(ns) }
{}
/// \brief Equality operator.
TOML_NODISCARD
friend constexpr bool operator==(const time& lhs, const time& rhs) noexcept
@ -181,13 +212,11 @@ TOML_NAMESPACE_START
/// \brief Offset from UTC+0, in minutes.
int16_t minutes;
/// \brief Default-constructs a zero time-offset.
/// \brief Default constructor. Does not initialize the members.
TOML_NODISCARD_CTOR
constexpr time_offset() noexcept //
: minutes{}
{}
time_offset() noexcept = default;
/// \brief Constructs a timezone offset from separate hour and minute totals.
/// \brief Constructs a timezone offset from individual hour and minute totals.
///
/// \detail \cpp
/// std::cout << toml::time_offset{ 2, 30 } << "\n";
@ -204,11 +233,17 @@ TOML_NAMESPACE_START
/// Z
/// \eout
///
/// \tparam H An integral type.
/// \tparam M An integral type.
///
/// \param h The total hours.
/// \param m The total minutes.
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M>), typename H, typename M)
TOML_NODISCARD_CTOR
constexpr time_offset(int8_t h, int8_t m) noexcept //
: minutes{ static_cast<int16_t>(h * 60 + m) }
constexpr time_offset(H h, M m) noexcept //
: minutes{ static_cast<int16_t>(static_cast<impl::common_signed_type<H, M>>(h)
* impl::common_signed_type<H, M>{ 60 }
+ static_cast<impl::common_signed_type<H, M>>(m)) }
{}
/// \brief Equality operator.
@ -292,13 +327,9 @@ TOML_NAMESPACE_START
/// \remarks The date_time is said to be 'local' if the offset is empty.
optional<toml::time_offset> offset;
/// \brief Default-constructs a zero date-time.
/// \brief Default constructor. Does not initialize the members.
TOML_NODISCARD_CTOR
constexpr date_time() noexcept //
: date{},
time{},
offset{} // TINAE - icc bugfix
{}
date_time() noexcept = default;
/// \brief Constructs a local date-time.
///

View File

@ -43,15 +43,11 @@ TOML_NAMESPACE_START
/// \cond
using base = impl::formatter;
std::vector<std::string> key_path_;
std::vector<std::string_view> key_path_;
bool pending_table_separator_ = false;
static constexpr size_t line_wrap_cols = 120;
TOML_NODISCARD
TOML_API
static std::string make_key_segment(const std::string&) noexcept;
TOML_NODISCARD
TOML_API
static size_t count_inline_columns(const node&) noexcept;
@ -64,7 +60,7 @@ TOML_NAMESPACE_START
void print_pending_table_separator();
TOML_API
void print_key_segment(const std::string&);
void print_key_segment(std::string_view);
TOML_API
void print_key_path();
@ -81,8 +77,9 @@ TOML_NAMESPACE_START
TOML_API
void print();
static constexpr format_flags mandatory_flags = format_flags::none;
static constexpr format_flags ignored_flags = format_flags::none;
static constexpr impl::formatter_constants constants = { "inf"sv, "-inf"sv, "nan"sv };
static constexpr format_flags mandatory_flags = format_flags::none;
static constexpr format_flags ignored_flags = format_flags::none;
/// \endcond
@ -99,7 +96,7 @@ TOML_NAMESPACE_START
/// \param flags Format option flags.
TOML_NODISCARD_CTOR
explicit default_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
: base{ source, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ &source, nullptr, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
@ -128,7 +125,7 @@ TOML_NAMESPACE_START
/// \param flags Format option flags.
TOML_NODISCARD_CTOR
explicit default_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
: base{ result, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ nullptr, &result, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#endif

View File

@ -22,50 +22,6 @@ TOML_DISABLE_ARITHMETIC_WARNINGS;
TOML_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
std::string default_formatter::make_key_segment(const std::string& str) noexcept
{
if (str.empty())
return "''"s;
else
{
bool requires_quotes = false;
{
impl::utf8_decoder decoder;
for (size_t i = 0; i < str.length() && !requires_quotes; i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
requires_quotes = true;
else if (decoder.has_code_point())
requires_quotes = !impl::is_bare_key_character(decoder.codepoint);
}
}
if (requires_quotes)
{
std::string s;
s.reserve(str.length() + 2u);
s += '"';
for (auto c : str)
{
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
s.append(impl::low_character_escape_table[c]);
else if TOML_UNLIKELY(c == '\x7F')
s.append("\\u007F"sv);
else if TOML_UNLIKELY(c == '"')
s.append("\\\""sv);
else
s += c;
}
s += '"';
return s;
}
else
return str;
}
}
TOML_EXTERNAL_LINKAGE
size_t default_formatter::count_inline_columns(const node& node) noexcept
{
@ -167,35 +123,9 @@ TOML_NAMESPACE_START
}
TOML_EXTERNAL_LINKAGE
void default_formatter::print_key_segment(const std::string& str)
void default_formatter::print_key_segment(std::string_view str)
{
if (str.empty())
impl::print_to_stream(base::stream(), "''"sv);
else
{
bool requires_quotes = false;
{
impl::utf8_decoder decoder;
for (size_t i = 0; i < str.length() && !requires_quotes; i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
requires_quotes = true;
else if (decoder.has_code_point())
requires_quotes = !impl::is_bare_key_character(decoder.codepoint);
}
}
if (requires_quotes)
{
impl::print_to_stream(base::stream(), '"');
impl::print_to_stream_with_escapes(base::stream(), str);
impl::print_to_stream(base::stream(), '"');
}
else
impl::print_to_stream(base::stream(), str);
}
base::clear_naked_newline();
base::print_string(str, false, true);
}
TOML_EXTERNAL_LINKAGE
@ -205,7 +135,7 @@ TOML_NAMESPACE_START
{
if (std::addressof(segment) > key_path_.data())
impl::print_to_stream(base::stream(), '.');
impl::print_to_stream(base::stream(), segment);
print_key_segment(segment);
}
base::clear_naked_newline();
}
@ -376,7 +306,7 @@ TOML_NAMESPACE_START
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));
key_path_.push_back(std::string_view{ k });
if (!skip_self)
{
@ -406,7 +336,7 @@ TOML_NAMESPACE_START
if (base::indent_sub_tables())
base::increase_indent();
key_path_.push_back(make_key_segment(k));
key_path_.push_back(std::string_view{ k });
for (size_t i = 0; i < arr.size(); i++)
{

View File

@ -11,26 +11,36 @@
TOML_IMPL_NAMESPACE_START
{
struct formatter_constants
{
std::string_view pos_inf;
std::string_view neg_inf;
std::string_view nan;
};
struct formatter_config
{
format_flags flags;
std::string_view indent;
};
class formatter
{
private:
const toml::node* source_;
std::ostream* stream_ = {};
format_flags flags_; //
int indent_; // these are set in attach()
bool naked_newline_; //
std::string_view indent_string_;
size_t indent_columns_;
const node* source_;
#if TOML_PARSER && !TOML_EXCEPTIONS
const parse_result* result_ = {};
const parse_result* result_;
#endif
TOML_API
void set_indent_string(std::string_view str) noexcept;
const formatter_constants* constants_;
formatter_config config_;
size_t indent_columns_;
std::ostream* stream_; //
int indent_; // these are set in attach()
bool naked_newline_; //
protected:
TOML_PURE_INLINE_GETTER
const toml::node& source() const noexcept
const node& source() const noexcept
{
return *source_;
}
@ -71,37 +81,43 @@ TOML_IMPL_NAMESPACE_START
TOML_PURE_INLINE_GETTER
bool indent_array_elements() const noexcept
{
return !!(flags_ & format_flags::indent_array_elements);
return !!(config_.flags & format_flags::indent_array_elements);
}
TOML_PURE_INLINE_GETTER
bool indent_sub_tables() const noexcept
{
return !!(flags_ & format_flags::indent_sub_tables);
return !!(config_.flags & format_flags::indent_sub_tables);
}
TOML_PURE_INLINE_GETTER
bool quote_dates_and_times() const noexcept
{
return !!(flags_ & format_flags::quote_dates_and_times);
return !!(config_.flags & format_flags::quote_dates_and_times);
}
TOML_PURE_INLINE_GETTER
bool quote_infinities_and_nans() const noexcept
{
return !!(config_.flags & format_flags::quote_infinities_and_nans);
}
TOML_PURE_INLINE_GETTER
bool literal_strings_allowed() const noexcept
{
return !!(flags_ & format_flags::allow_literal_strings);
return !!(config_.flags & format_flags::allow_literal_strings);
}
TOML_PURE_INLINE_GETTER
bool multi_line_strings_allowed() const noexcept
{
return !!(flags_ & format_flags::allow_multi_line_strings);
return !!(config_.flags & format_flags::allow_multi_line_strings);
}
TOML_PURE_INLINE_GETTER
bool value_format_flags_allowed() const noexcept
{
return !!(flags_ & format_flags::allow_value_format_flags);
return !!(config_.flags & format_flags::allow_value_format_flags);
}
TOML_PURE_INLINE_GETTER
@ -128,7 +144,7 @@ TOML_IMPL_NAMESPACE_START
void print_indent();
TOML_API
void print_quoted_string(std::string_view str, bool allow_multi_line = true);
void print_string(std::string_view str, bool allow_multi_line = true, bool allow_bare = false);
TOML_API
void print(const value<std::string>&);
@ -158,21 +174,9 @@ TOML_IMPL_NAMESPACE_START
TOML_API
bool dump_failed_parse_result();
TOML_NODISCARD_CTOR
formatter(const toml::node& source, format_flags flags, std::string_view indent) noexcept //
: source_{ &source },
flags_{ flags }
{
set_indent_string(indent);
}
#if TOML_PARSER && !TOML_EXCEPTIONS
TOML_NODISCARD_CTOR
TOML_API
formatter(const parse_result& result, format_flags flags, std::string_view indent) noexcept;
#endif
formatter(const node*, const parse_result*, const formatter_constants&, const formatter_config&) noexcept;
};
}
TOML_IMPL_NAMESPACE_END;

View File

@ -22,25 +22,24 @@
TOML_IMPL_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
formatter::formatter(const node* source_node,
const parse_result* source_pr,
const formatter_constants& constants,
const formatter_config& config) noexcept //
#if TOML_PARSER && !TOML_EXCEPTIONS
TOML_EXTERNAL_LINKAGE
formatter::formatter(const parse_result& result, format_flags flags, std::string_view indent) noexcept //
: source_{ result ? &result.table() : nullptr },
flags_{ flags },
result_{ &result }
{
set_indent_string(indent);
}
: source_{ source_pr && *source_pr ? &source_pr->table() : source_node },
result_{ source_pr },
#else
: source_{ source_pr ? source_pr : source_node },
#endif
TOML_EXTERNAL_LINKAGE
void formatter::set_indent_string(std::string_view str) noexcept
constants_{ &constants },
config_{ config }
{
indent_string_ = str.data() ? str : " "sv;
TOML_ASSERT(source_ != nullptr);
indent_columns_ = {};
for (auto c : indent_string_)
for (auto c : config_.indent)
indent_columns_ += c == '\t' ? 4u : 1u;
}
@ -73,13 +72,13 @@ TOML_IMPL_NAMESPACE_START
{
for (int i = 0; i < indent_; i++)
{
print_to_stream(*stream_, indent_string_);
print_to_stream(*stream_, config_.indent);
naked_newline_ = false;
}
}
TOML_EXTERNAL_LINKAGE
void formatter::print_quoted_string(std::string_view str, bool allow_multi_line)
void formatter::print_string(std::string_view str, bool allow_multi_line, bool allow_bare)
{
auto literals = literal_strings_allowed();
if (str.empty())
@ -90,13 +89,13 @@ TOML_IMPL_NAMESPACE_START
}
auto multi_line = allow_multi_line && multi_line_strings_allowed();
if (multi_line || literals)
if (multi_line || literals || allow_bare)
{
utf8_decoder decoder;
bool has_line_breaks = false;
bool has_control_chars = false;
bool has_single_quotes = false;
for (size_t i = 0; i < str.length() && !(has_line_breaks && has_control_chars && has_single_quotes); i++)
for (size_t i = 0; i < str.length(); i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
@ -104,6 +103,7 @@ TOML_IMPL_NAMESPACE_START
has_line_breaks = false;
has_control_chars = true; // force ""
has_single_quotes = true;
allow_bare = false;
break;
}
else if (decoder.has_code_point())
@ -114,13 +114,20 @@ TOML_IMPL_NAMESPACE_START
has_control_chars = true;
else if (decoder.codepoint == U'\'')
has_single_quotes = true;
if (allow_bare)
allow_bare = is_bare_key_character(decoder.codepoint);
}
if (has_line_breaks && has_control_chars && has_single_quotes && !allow_bare)
break;
}
multi_line = multi_line && has_line_breaks;
literals = literals && !has_control_chars && !(!multi_line && has_single_quotes);
}
if (literals)
if (allow_bare)
print_to_stream(*stream_, str);
else if (literals)
print_to_stream_bookended(*stream_, str, multi_line ? "'''"sv : "'"sv);
else
{
@ -135,7 +142,7 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
void formatter::print(const value<std::string>& val)
{
print_quoted_string(val.get());
print_string(val.get());
}
TOML_EXTERNAL_LINKAGE
@ -166,7 +173,24 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
void formatter::print(const value<double>& val)
{
print_to_stream(*stream_, *val);
const std::string_view* inf_nan = nullptr;
switch (fpclassify(*val))
{
case fp_class::neg_inf: inf_nan = &constants_->neg_inf; break;
case fp_class::pos_inf: inf_nan = &constants_->pos_inf; break;
case fp_class::nan: inf_nan = &constants_->nan; break;
case fp_class::ok: print_to_stream(*stream_, *val); break;
default: TOML_UNREACHABLE;
}
if (inf_nan)
{
if (quote_infinities_and_nans())
print_to_stream_bookended(*stream_, *inf_nan, '"');
else
print_to_stream(*stream_, *inf_nan);
}
naked_newline_ = false;
}

View File

@ -298,22 +298,25 @@ TOML_NAMESPACE_START // abi namespace
none,
/// \brief Dates and times will be emitted as quoted strings.
quote_dates_and_times = 1,
quote_dates_and_times = 1ull,
/// \brief Infinities and NaNs will be emitted as quoted strings.
quote_infinities_and_nans = (1ull << 1),
/// \brief Strings will be emitted as single-quoted literal strings where possible.
allow_literal_strings = 2,
allow_literal_strings = (1ull << 2),
/// \brief Strings containing newlines will be emitted as triple-quoted 'multi-line' strings where possible.
allow_multi_line_strings = 4,
allow_multi_line_strings = (1ull << 3),
/// \brief Values with special format flags will be formatted accordingly.
allow_value_format_flags = 8,
allow_value_format_flags = (1ull << 4),
/// \brief Apply indentation to tables nested within other tables/arrays.
indent_sub_tables = 16,
indent_sub_tables = (1ull << 5),
/// \brief Apply indentation to array elements when the array is forced to wrap over multiple lines.
indent_array_elements = 32,
indent_array_elements = (1ull << 6),
/// \brief Combination mask of all indentation-enabling flags.
indentation = indent_sub_tables | indent_array_elements,
@ -358,9 +361,15 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
using remove_cvref = std::remove_cv_t<std::remove_reference_t<T>>;
template <typename... T>
using common_signed_type = std::common_type_t<std::make_signed_t<T>...>;
template <typename T, typename... U>
inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>);
template <typename... T>
inline constexpr bool all_integral = (std::is_integral_v<T> && ...);
template <typename T>
inline constexpr bool is_cvref = std::is_reference_v<T> || std::is_const_v<T> || std::is_volatile_v<T>;

View File

@ -55,7 +55,8 @@ TOML_NAMESPACE_START
TOML_API
void print();
static constexpr format_flags mandatory_flags = format_flags::quote_dates_and_times;
static constexpr impl::formatter_constants constants = { "Infinity"sv, "-Infinity"sv, "NaN"sv };
static constexpr format_flags mandatory_flags = format_flags::quote_dates_and_times;
static constexpr format_flags ignored_flags =
format_flags::allow_literal_strings | format_flags::allow_multi_line_strings;
@ -63,7 +64,8 @@ TOML_NAMESPACE_START
public:
/// \brief The default flags for a json_formatter.
static constexpr format_flags default_flags = format_flags::quote_dates_and_times //
static constexpr format_flags default_flags = format_flags::quote_dates_and_times //
| format_flags::quote_infinities_and_nans //
| format_flags::indentation;
/// \brief Constructs a JSON formatter and binds it to a TOML object.
@ -72,7 +74,7 @@ TOML_NAMESPACE_START
/// \param flags Format option flags.
TOML_NODISCARD_CTOR
explicit json_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
: base{ source, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ &source, nullptr, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
@ -103,7 +105,7 @@ TOML_NAMESPACE_START
/// \param flags Format option flags.
TOML_NODISCARD_CTOR
explicit json_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
: base{ result, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ nullptr, &result, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#endif

View File

@ -33,12 +33,12 @@ TOML_NAMESPACE_START
for (auto&& [k, v] : tbl)
{
if (first)
impl::print_to_stream(base::stream(), ", "sv);
impl::print_to_stream(base::stream(), ',');
first = true;
base::print_newline(true);
base::print_indent();
base::print_quoted_string(k, false);
base::print_string(k, false);
impl::print_to_stream(base::stream(), " : "sv);
const auto type = v.type();

View File

@ -494,8 +494,7 @@ TOML_ANON_NAMESPACE_END;
TOML_ANON_NAMESPACE_START
{
template <typename... T>
TOML_NODISCARD
TOML_ATTR(const)
TOML_CONST_GETTER
TOML_INTERNAL_LINKAGE
constexpr bool is_match(char32_t codepoint, T... vals) noexcept
{
@ -544,22 +543,21 @@ TOML_ANON_NAMESPACE_START
static constexpr auto prefix = "x"sv;
};
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(node_type val) noexcept
{
return impl::node_type_friendly_names[impl::unwrap_enum(val)];
}
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(const std::string& str) noexcept
{
return std::string_view{ str };
}
TOML_NODISCARD
TOML_ATTR(const)
TOML_CONST_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(bool val) noexcept
{
@ -568,7 +566,7 @@ TOML_ANON_NAMESPACE_START
return val ? "true"sv : "false"sv;
}
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(const utf8_codepoint& cp) noexcept
{
@ -580,7 +578,7 @@ TOML_ANON_NAMESPACE_START
return cp.as_view();
}
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(const utf8_codepoint* cp) noexcept
{
@ -2134,7 +2132,7 @@ TOML_IMPL_NAMESPACE_START
if (!part_of_datetime && !is_eof() && !is_value_terminator(*cp))
set_error_and_return_default("expected value-terminator, saw '"sv, to_sv(*cp), "'"sv);
return { static_cast<uint16_t>(year), static_cast<uint8_t>(month), static_cast<uint8_t>(day) };
return { year, month, day };
}
TOML_NODISCARD
@ -2169,10 +2167,7 @@ TOML_IMPL_NAMESPACE_START
if (minute > 59u)
set_error_and_return_default("expected minute between 0 and 59 (inclusive), saw "sv,
static_cast<uint64_t>(minute));
auto time = toml::time{
static_cast<uint8_t>(hour),
static_cast<uint8_t>(minute),
};
auto time = toml::time{ hour, minute };
// ':'
if constexpr (TOML_LANG_UNRELEASED) // toml/issues/671 (allow omission of seconds)
@ -2193,7 +2188,7 @@ TOML_IMPL_NAMESPACE_START
if (second > 59u)
set_error_and_return_default("expected second between 0 and 59 (inclusive), saw "sv,
static_cast<uint64_t>(second));
time.second = static_cast<uint8_t>(second);
time.second = static_cast<decltype(time.second)>(second);
// '.' (early-exiting is allowed; fractional is optional)
if (is_eof() || is_value_terminator(*cp) || (part_of_datetime && is_match(*cp, U'+', U'-', U'Z', U'z')))
@ -2257,7 +2252,7 @@ TOML_IMPL_NAMESPACE_START
return { date, time };
// zero offset ('Z' or 'z')
time_offset offset;
time_offset offset{};
if (is_match(*cp, U'Z', U'z'))
advance_and_return_if_error({});
@ -2292,7 +2287,7 @@ TOML_IMPL_NAMESPACE_START
if (minute > 59)
set_error_and_return_default("expected minute between 0 and 59 (inclusive), saw "sv,
static_cast<int64_t>(minute));
offset.minutes = static_cast<int16_t>((hour * 60 + minute) * sign);
offset.minutes = static_cast<decltype(offset.minutes)>((hour * 60 + minute) * sign);
}
if (!is_eof() && !is_value_terminator(*cp))

View File

@ -908,7 +908,7 @@ TOML_IMPL_NAMESPACE_START
return state == uint_least32_t{};
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
constexpr bool needs_more_input() const noexcept
{
return state > uint_least32_t{} && state != uint_least32_t{ 12u };

281
tests/formatters.cpp Normal file
View File

@ -0,0 +1,281 @@
// 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
#include "tests.h"
namespace
{
template <typename Formatter, typename T>
static auto format_to_string(const T& obj,
format_flags flags = Formatter::default_flags,
format_flags exclude_flags = format_flags::none)
{
std::stringstream ss;
ss << "*****\n" << Formatter{ obj, flags & ~(exclude_flags) } << "\n*****";
return ss.str();
}
struct char32_printer
{
char32_t value;
friend std::ostream& operator<<(std::ostream& os, const char32_printer& p)
{
if (p.value <= U'\x1F')
return os << '\'' << impl::low_character_escape_table[static_cast<size_t>(p.value)] << '\'';
else if (p.value == U'\x7F')
return os << "'\\u007F'"sv;
else if (p.value < 127u)
return os << '\'' << static_cast<char>(static_cast<uint8_t>(p.value)) << '\'';
else
return os << static_cast<uint_least32_t>(p.value);
}
};
struct string_difference
{
source_position position;
size_t index;
char32_t a, b;
friend std::ostream& operator<<(std::ostream& os, const string_difference& diff)
{
if (diff.a && diff.b && diff.a != diff.b)
os << char32_printer{ diff.a } << " vs "sv << char32_printer{ diff.b } << " at "sv;
return os << diff.position << ", index "sv << diff.index;
}
};
static optional<string_difference> find_first_difference(std::string_view str_a, std::string_view str_b) noexcept
{
string_difference diff{ { 1u, 1u } };
impl::utf8_decoder a, b;
for (size_t i = 0, e = std::min(str_a.length(), str_b.length()); i < e; i++, diff.index++)
{
a(static_cast<uint8_t>(str_a[i]));
b(static_cast<uint8_t>(str_b[i]));
if (a.has_code_point() != b.has_code_point() || a.error() != b.error())
return diff;
if (a.error())
{
a.reset();
b.reset();
continue;
}
if (!a.has_code_point())
continue;
if (a.codepoint != b.codepoint)
{
diff.a = a.codepoint;
diff.b = b.codepoint;
return diff;
}
if (impl::is_line_break(a.codepoint))
{
diff.position.line++;
diff.position.column = 1u;
}
else
diff.position.column++;
}
if (str_a.length() != str_b.length())
return diff;
return {};
}
}
#define CHECK_FORMATTER(formatter, data, expected) \
do \
{ \
const auto str = format_to_string<formatter>(data); \
const auto diff = find_first_difference(str, expected); \
if (diff) \
FORCE_FAIL("string mismatch: "sv << *diff); \
} \
while (false)
TEST_CASE("formatters")
{
const auto data = toml::table{
{ "integers"sv,
toml::table{ { "zero"sv, 0 },
{ "one"sv, 1 },
{ "dec"sv, 10 },
{ "bin"sv, 10, toml::value_flags::format_as_binary },
{ "oct"sv, 10, toml::value_flags::format_as_octal },
{ "hex"sv, 10, toml::value_flags::format_as_hexadecimal } } },
{ "floats"sv,
toml::table{ { "pos_zero"sv, +0.0 },
{ "neg_zero"sv, -0.0 },
{ "one"sv, 1.0 },
{ "pos_inf"sv, +std::numeric_limits<double>::infinity() },
{ "neg_inf"sv, -std::numeric_limits<double>::infinity() },
{ "pos_nan"sv, +std::numeric_limits<double>::quiet_NaN() },
{ "neg_nan"sv, -std::numeric_limits<double>::quiet_NaN() }
} },
{ "dates and times"sv,
toml::table{
{ "dates"sv, toml::table{ { "zero"sv, toml::date{} } } },
{ "times"sv, toml::table{ { "zero"sv, toml::time{} } } },
{ "date-times"sv,
toml::table{
{ "local"sv, toml::table{ { "zero"sv, toml::date_time{} } } },
{ "offset"sv, toml::table{ { "zero"sv, toml::date_time{ {}, {}, toml::time_offset{} } } } } } } } },
{ "bools"sv,
toml::table{ { "true"sv, true }, //
{ "false"sv, false } } },
{
"strings"sv,
toml::array{ R"()"sv,
R"(string)"sv,
R"(string with a single quote in it: ')"sv,
R"(string with a double quote in it: ")"sv,
"string with a tab: \t"sv,
R"(a long string to force the array over multiple lines)"sv },
},
{ "a"sv,
toml::table{ { "val", true },
{ "b"sv, toml::table{ { "val", true }, { "c"sv, toml::table{ { "val", true } } } } } } }
};
SECTION("default_formatter")
{
static constexpr auto expected = R"(*****
strings = [
'',
'string',
"string with a single quote in it: '",
'string with a double quote in it: "',
'string with a tab: ',
'a long string to force the array over multiple lines'
]
[a]
val = true
[a.b]
val = true
[a.b.c]
val = true
[bools]
false = false
true = true
['dates and times'.date-times.local]
zero = 0000-00-00T00:00:00
['dates and times'.date-times.offset]
zero = 0000-00-00T00:00:00Z
['dates and times'.dates]
zero = 0000-00-00
['dates and times'.times]
zero = 00:00:00
[floats]
neg_inf = -inf
neg_nan = nan
neg_zero = -0.0
one = 1.0
pos_inf = inf
pos_nan = nan
pos_zero = 0.0
[integers]
bin = 0b1010
dec = 10
hex = 0xA
oct = 0o12
one = 1
zero = 0
*****)"sv;
CHECK_FORMATTER(default_formatter, data, expected);
}
SECTION("json_formatter")
{
static constexpr auto expected = R"(*****
{
"a" : {
"b" : {
"c" : {
"val" : true
},
"val" : true
},
"val" : true
},
"bools" : {
"false" : false,
"true" : true
},
"dates and times" : {
"date-times" : {
"local" : {
"zero" : "0000-00-00T00:00:00"
},
"offset" : {
"zero" : "0000-00-00T00:00:00Z"
}
},
"dates" : {
"zero" : "0000-00-00"
},
"times" : {
"zero" : "00:00:00"
}
},
"floats" : {
"neg_inf" : "-Infinity",
"neg_nan" : "NaN",
"neg_zero" : -0.0,
"one" : 1.0,
"pos_inf" : "Infinity",
"pos_nan" : "NaN",
"pos_zero" : 0.0
},
"integers" : {
"bin" : 10,
"dec" : 10,
"hex" : 10,
"oct" : 10,
"one" : 1,
"zero" : 0
},
"strings" : [
"",
"string",
"string with a single quote in it: '",
"string with a double quote in it: \"",
"string with a tab: \t",
"a long string to force the array over multiple lines"
]
}
*****)"sv;
CHECK_FORMATTER(json_formatter, data, expected);
}
SECTION("yaml_formatter")
{}
}

View File

@ -3,6 +3,7 @@ test_sources = [
'conformance_burntsushi_valid.cpp',
'conformance_iarna_invalid.cpp',
'conformance_iarna_valid.cpp',
'formatters.cpp',
'impl_toml.cpp',
'tests.cpp',
'parsing_floats.cpp',

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{202DCF23-B4E4-5FB9-AFA8-CC9A718067FF}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B0B1EA1E-611A-59B6-939F-0A891C71BBF0}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{2D040A50-F533-5977-AF7F-B25C29112025}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{50988C9F-99C8-59C2-BCAA-AA1F0848472E}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{39175FCA-1342-507B-90F3-E8DCFB4C48D0}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{70F7C29B-3468-5C09-8D47-B649CEBAB09E}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{62191BB3-97A9-552E-93BF-BFDF4D9905DD}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{9A3431E3-4727-5FED-9C18-CCD300C2760E}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{CFBAF3E0-2F81-5178-964C-F419CD2F296D}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{AD9A5FC3-6B12-5B6F-86C0-AB2FBB8C7766}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{DC05B52F-D0ED-5F40-A5EC-92C4C1D77F98}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{41DC0274-FFA8-5D94-AF8D-5677E3141095}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{C8B46DC3-994F-5A7C-98ED-3388BCE5D647}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{F7375F00-0345-5F67-89C0-2B18412B40FB}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{92AAC430-36B0-51E4-8E39-F3C579EDB331}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B1EAF133-1019-510F-A083-FC04774FF12E}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{F70977E7-E735-5D5C-9043-CA792F1B9392}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{413BDA52-0A9D-56B8-9AF3-A65019F42831}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{6F6D8031-4BA9-5F07-BE1F-190A2FC3CC9C}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{18ADA45A-11DD-5649-8492-F726E6A82803}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{74813AFD-DB22-52FA-9108-0BADD4B0E161}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B1B28D93-892C-59BF-9C6F-D813EC6438A0}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{6C3EA8CD-33CC-5775-ACC4-631FF5FE1E2C}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B3779AEA-40D6-5F3C-BC86-98E4E577E09D}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{2D7D2E84-8861-529C-9C05-A1EE1FB84084}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B98D8D10-4B7B-5AA8-84B5-87FE6AA80C10}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{C9D50E23-65F2-5C1E-BE44-7327A9FFC637}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{082D6FBD-F01E-504B-9905-25937CCE7F9A}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{AD2F4862-1DC2-550B-AFEF-FF3D4D477323}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{0D4D9D25-3F93-5C37-866E-F8B0AC23F851}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{151E9E68-E325-5B08-8722-257F2B083BAD}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

View File

@ -10,6 +10,7 @@
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B3077FF1-FC90-5C14-A69F-3524F62167B1}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -76,6 +77,7 @@
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>

339
toml.hpp
View File

@ -1186,12 +1186,13 @@ TOML_NAMESPACE_START // abi namespace
enum class format_flags : uint64_t
{
none,
quote_dates_and_times = 1,
allow_literal_strings = 2,
allow_multi_line_strings = 4,
allow_value_format_flags = 8,
indent_sub_tables = 16,
indent_array_elements = 32,
quote_dates_and_times = 1ull,
quote_infinities_and_nans = (1ull << 1),
allow_literal_strings = (1ull << 2),
allow_multi_line_strings = (1ull << 3),
allow_value_format_flags = (1ull << 4),
indent_sub_tables = (1ull << 5),
indent_array_elements = (1ull << 6),
indentation = indent_sub_tables | indent_array_elements,
};
TOML_MAKE_FLAGS(format_flags);
@ -1215,9 +1216,15 @@ TOML_IMPL_NAMESPACE_START
template <typename T>
using remove_cvref = std::remove_cv_t<std::remove_reference_t<T>>;
template <typename... T>
using common_signed_type = std::common_type_t<std::make_signed_t<T>...>;
template <typename T, typename... U>
inline constexpr bool is_one_of = (false || ... || std::is_same_v<T, U>);
template <typename... T>
inline constexpr bool all_integral = (std::is_integral_v<T> && ...);
template <typename T>
inline constexpr bool is_cvref = std::is_reference_v<T> || std::is_const_v<T> || std::is_volatile_v<T>;
@ -1993,6 +2000,17 @@ TOML_NAMESPACE_START
uint8_t day;
TOML_NODISCARD_CTOR
date() noexcept = default;
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<Y, M, D>), typename Y, typename M, typename D)
TOML_NODISCARD_CTOR
constexpr date(Y y, M m, D d) noexcept //
: year{ static_cast<uint16_t>(y) },
month{ static_cast<uint8_t>(m) },
day{ static_cast<uint8_t>(d) }
{}
TOML_NODISCARD
friend constexpr bool operator==(const date& lhs, const date& rhs) noexcept
{
@ -2057,6 +2075,22 @@ TOML_NAMESPACE_START
uint32_t nanosecond;
TOML_NODISCARD_CTOR
time() noexcept = default;
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M, S, NS>),
typename H,
typename M,
typename S = uint8_t,
typename NS = uint32_t)
TOML_NODISCARD_CTOR
constexpr time(H h, M m, S s = S{}, NS ns = NS{}) noexcept //
: hour{ static_cast<uint8_t>(h) },
minute{ static_cast<uint8_t>(m) },
second{ static_cast<uint8_t>(s) },
nanosecond{ static_cast<uint32_t>(ns) }
{}
TOML_NODISCARD
friend constexpr bool operator==(const time& lhs, const time& rhs) noexcept
{
@ -2117,13 +2151,14 @@ TOML_NAMESPACE_START
int16_t minutes;
TOML_NODISCARD_CTOR
constexpr time_offset() noexcept //
: minutes{}
{}
time_offset() noexcept = default;
TOML_CONSTRAINED_TEMPLATE((impl::all_integral<H, M>), typename H, typename M)
TOML_NODISCARD_CTOR
constexpr time_offset(int8_t h, int8_t m) noexcept //
: minutes{ static_cast<int16_t>(h * 60 + m) }
constexpr time_offset(H h, M m) noexcept //
: minutes{ static_cast<int16_t>(static_cast<impl::common_signed_type<H, M>>(h)
* impl::common_signed_type<H, M>{ 60 }
+ static_cast<impl::common_signed_type<H, M>>(m)) }
{}
TOML_NODISCARD
@ -2180,11 +2215,7 @@ TOML_NAMESPACE_START
optional<toml::time_offset> offset;
TOML_NODISCARD_CTOR
constexpr date_time() noexcept //
: date{},
time{},
offset{} // TINAE - icc bugfix
{}
date_time() noexcept = default;
TOML_NODISCARD_CTOR
constexpr date_time(const toml::date& d, const toml::time& t) noexcept //
@ -6866,7 +6897,7 @@ TOML_IMPL_NAMESPACE_START
return state == uint_least32_t{};
}
TOML_NODISCARD
TOML_PURE_INLINE_GETTER
constexpr bool needs_more_input() const noexcept
{
return state > uint_least32_t{} && state != uint_least32_t{ 12u };
@ -7389,26 +7420,36 @@ TOML_PUSH_WARNINGS;
TOML_IMPL_NAMESPACE_START
{
struct formatter_constants
{
std::string_view pos_inf;
std::string_view neg_inf;
std::string_view nan;
};
struct formatter_config
{
format_flags flags;
std::string_view indent;
};
class formatter
{
private:
const toml::node* source_;
std::ostream* stream_ = {};
format_flags flags_; //
int indent_; // these are set in attach()
bool naked_newline_; //
std::string_view indent_string_;
size_t indent_columns_;
const node* source_;
#if TOML_PARSER && !TOML_EXCEPTIONS
const parse_result* result_ = {};
const parse_result* result_;
#endif
TOML_API
void set_indent_string(std::string_view str) noexcept;
const formatter_constants* constants_;
formatter_config config_;
size_t indent_columns_;
std::ostream* stream_; //
int indent_; // these are set in attach()
bool naked_newline_; //
protected:
TOML_PURE_INLINE_GETTER
const toml::node& source() const noexcept
const node& source() const noexcept
{
return *source_;
}
@ -7449,37 +7490,43 @@ TOML_IMPL_NAMESPACE_START
TOML_PURE_INLINE_GETTER
bool indent_array_elements() const noexcept
{
return !!(flags_ & format_flags::indent_array_elements);
return !!(config_.flags & format_flags::indent_array_elements);
}
TOML_PURE_INLINE_GETTER
bool indent_sub_tables() const noexcept
{
return !!(flags_ & format_flags::indent_sub_tables);
return !!(config_.flags & format_flags::indent_sub_tables);
}
TOML_PURE_INLINE_GETTER
bool quote_dates_and_times() const noexcept
{
return !!(flags_ & format_flags::quote_dates_and_times);
return !!(config_.flags & format_flags::quote_dates_and_times);
}
TOML_PURE_INLINE_GETTER
bool quote_infinities_and_nans() const noexcept
{
return !!(config_.flags & format_flags::quote_infinities_and_nans);
}
TOML_PURE_INLINE_GETTER
bool literal_strings_allowed() const noexcept
{
return !!(flags_ & format_flags::allow_literal_strings);
return !!(config_.flags & format_flags::allow_literal_strings);
}
TOML_PURE_INLINE_GETTER
bool multi_line_strings_allowed() const noexcept
{
return !!(flags_ & format_flags::allow_multi_line_strings);
return !!(config_.flags & format_flags::allow_multi_line_strings);
}
TOML_PURE_INLINE_GETTER
bool value_format_flags_allowed() const noexcept
{
return !!(flags_ & format_flags::allow_value_format_flags);
return !!(config_.flags & format_flags::allow_value_format_flags);
}
TOML_PURE_INLINE_GETTER
@ -7506,7 +7553,7 @@ TOML_IMPL_NAMESPACE_START
void print_indent();
TOML_API
void print_quoted_string(std::string_view str, bool allow_multi_line = true);
void print_string(std::string_view str, bool allow_multi_line = true, bool allow_bare = false);
TOML_API
void print(const value<std::string>&);
@ -7536,21 +7583,9 @@ TOML_IMPL_NAMESPACE_START
TOML_API
bool dump_failed_parse_result();
TOML_NODISCARD_CTOR
formatter(const toml::node& source, format_flags flags, std::string_view indent) noexcept //
: source_{ &source },
flags_{ flags }
{
set_indent_string(indent);
}
#if TOML_PARSER && !TOML_EXCEPTIONS
TOML_NODISCARD_CTOR
TOML_API
formatter(const parse_result& result, format_flags flags, std::string_view indent) noexcept;
#endif
formatter(const node*, const parse_result*, const formatter_constants&, const formatter_config&) noexcept;
};
}
TOML_IMPL_NAMESPACE_END;
@ -7568,15 +7603,11 @@ TOML_NAMESPACE_START
private:
using base = impl::formatter;
std::vector<std::string> key_path_;
std::vector<std::string_view> key_path_;
bool pending_table_separator_ = false;
static constexpr size_t line_wrap_cols = 120;
TOML_NODISCARD
TOML_API
static std::string make_key_segment(const std::string&) noexcept;
TOML_NODISCARD
TOML_API
static size_t count_inline_columns(const node&) noexcept;
@ -7589,7 +7620,7 @@ TOML_NAMESPACE_START
void print_pending_table_separator();
TOML_API
void print_key_segment(const std::string&);
void print_key_segment(std::string_view);
TOML_API
void print_key_path();
@ -7606,8 +7637,9 @@ TOML_NAMESPACE_START
TOML_API
void print();
static constexpr format_flags mandatory_flags = format_flags::none;
static constexpr format_flags ignored_flags = format_flags::none;
static constexpr impl::formatter_constants constants = { "inf"sv, "-inf"sv, "nan"sv };
static constexpr format_flags mandatory_flags = format_flags::none;
static constexpr format_flags ignored_flags = format_flags::none;
public:
@ -7618,14 +7650,14 @@ TOML_NAMESPACE_START
TOML_NODISCARD_CTOR
explicit default_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
: base{ source, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ &source, nullptr, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
TOML_NODISCARD_CTOR
explicit default_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
: base{ result, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ nullptr, &result, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#endif
@ -7670,25 +7702,27 @@ TOML_NAMESPACE_START
TOML_API
void print();
static constexpr format_flags mandatory_flags = format_flags::quote_dates_and_times;
static constexpr impl::formatter_constants constants = { "Infinity"sv, "-Infinity"sv, "NaN"sv };
static constexpr format_flags mandatory_flags = format_flags::quote_dates_and_times;
static constexpr format_flags ignored_flags =
format_flags::allow_literal_strings | format_flags::allow_multi_line_strings;
public:
static constexpr format_flags default_flags = format_flags::quote_dates_and_times //
static constexpr format_flags default_flags = format_flags::quote_dates_and_times //
| format_flags::quote_infinities_and_nans //
| format_flags::indentation;
TOML_NODISCARD_CTOR
explicit json_formatter(const toml::node& source, format_flags flags = default_flags) noexcept
: base{ source, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ &source, nullptr, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS)
TOML_NODISCARD_CTOR
explicit json_formatter(const toml::parse_result& result, format_flags flags = default_flags) noexcept
: base{ result, (flags | mandatory_flags) & ~ignored_flags, " "sv }
: base{ nullptr, &result, constants, { (flags | mandatory_flags) & ~ignored_flags, " "sv } }
{}
#endif
@ -9304,8 +9338,7 @@ TOML_ANON_NAMESPACE_END;
TOML_ANON_NAMESPACE_START
{
template <typename... T>
TOML_NODISCARD
TOML_ATTR(const)
TOML_CONST_GETTER
TOML_INTERNAL_LINKAGE
constexpr bool is_match(char32_t codepoint, T... vals) noexcept
{
@ -9354,22 +9387,21 @@ TOML_ANON_NAMESPACE_START
static constexpr auto prefix = "x"sv;
};
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(node_type val) noexcept
{
return impl::node_type_friendly_names[impl::unwrap_enum(val)];
}
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(const std::string& str) noexcept
{
return std::string_view{ str };
}
TOML_NODISCARD
TOML_ATTR(const)
TOML_CONST_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(bool val) noexcept
{
@ -9378,7 +9410,7 @@ TOML_ANON_NAMESPACE_START
return val ? "true"sv : "false"sv;
}
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(const utf8_codepoint& cp) noexcept
{
@ -9390,7 +9422,7 @@ TOML_ANON_NAMESPACE_START
return cp.as_view();
}
TOML_NODISCARD
TOML_PURE_GETTER
TOML_INTERNAL_LINKAGE
std::string_view to_sv(const utf8_codepoint* cp) noexcept
{
@ -10944,7 +10976,7 @@ TOML_IMPL_NAMESPACE_START
if (!part_of_datetime && !is_eof() && !is_value_terminator(*cp))
set_error_and_return_default("expected value-terminator, saw '"sv, to_sv(*cp), "'"sv);
return { static_cast<uint16_t>(year), static_cast<uint8_t>(month), static_cast<uint8_t>(day) };
return { year, month, day };
}
TOML_NODISCARD
@ -10979,10 +11011,7 @@ TOML_IMPL_NAMESPACE_START
if (minute > 59u)
set_error_and_return_default("expected minute between 0 and 59 (inclusive), saw "sv,
static_cast<uint64_t>(minute));
auto time = toml::time{
static_cast<uint8_t>(hour),
static_cast<uint8_t>(minute),
};
auto time = toml::time{ hour, minute };
// ':'
if constexpr (TOML_LANG_UNRELEASED) // toml/issues/671 (allow omission of seconds)
@ -11003,7 +11032,7 @@ TOML_IMPL_NAMESPACE_START
if (second > 59u)
set_error_and_return_default("expected second between 0 and 59 (inclusive), saw "sv,
static_cast<uint64_t>(second));
time.second = static_cast<uint8_t>(second);
time.second = static_cast<decltype(time.second)>(second);
// '.' (early-exiting is allowed; fractional is optional)
if (is_eof() || is_value_terminator(*cp) || (part_of_datetime && is_match(*cp, U'+', U'-', U'Z', U'z')))
@ -11067,7 +11096,7 @@ TOML_IMPL_NAMESPACE_START
return { date, time };
// zero offset ('Z' or 'z')
time_offset offset;
time_offset offset{};
if (is_match(*cp, U'Z', U'z'))
advance_and_return_if_error({});
@ -11102,7 +11131,7 @@ TOML_IMPL_NAMESPACE_START
if (minute > 59)
set_error_and_return_default("expected minute between 0 and 59 (inclusive), saw "sv,
static_cast<int64_t>(minute));
offset.minutes = static_cast<int16_t>((hour * 60 + minute) * sign);
offset.minutes = static_cast<decltype(offset.minutes)>((hour * 60 + minute) * sign);
}
if (!is_eof() && !is_value_terminator(*cp))
@ -12458,25 +12487,24 @@ TOML_PUSH_WARNINGS;
TOML_IMPL_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
formatter::formatter(const node* source_node,
const parse_result* source_pr,
const formatter_constants& constants,
const formatter_config& config) noexcept //
#if TOML_PARSER && !TOML_EXCEPTIONS
TOML_EXTERNAL_LINKAGE
formatter::formatter(const parse_result& result, format_flags flags, std::string_view indent) noexcept //
: source_{ result ? &result.table() : nullptr },
flags_{ flags },
result_{ &result }
{
set_indent_string(indent);
}
: source_{ source_pr && *source_pr ? &source_pr->table() : source_node },
result_{ source_pr },
#else
: source_{ source_pr ? source_pr : source_node },
#endif
TOML_EXTERNAL_LINKAGE
void formatter::set_indent_string(std::string_view str) noexcept
constants_{ &constants },
config_{ config }
{
indent_string_ = str.data() ? str : " "sv;
TOML_ASSERT(source_ != nullptr);
indent_columns_ = {};
for (auto c : indent_string_)
for (auto c : config_.indent)
indent_columns_ += c == '\t' ? 4u : 1u;
}
@ -12509,13 +12537,13 @@ TOML_IMPL_NAMESPACE_START
{
for (int i = 0; i < indent_; i++)
{
print_to_stream(*stream_, indent_string_);
print_to_stream(*stream_, config_.indent);
naked_newline_ = false;
}
}
TOML_EXTERNAL_LINKAGE
void formatter::print_quoted_string(std::string_view str, bool allow_multi_line)
void formatter::print_string(std::string_view str, bool allow_multi_line, bool allow_bare)
{
auto literals = literal_strings_allowed();
if (str.empty())
@ -12526,13 +12554,13 @@ TOML_IMPL_NAMESPACE_START
}
auto multi_line = allow_multi_line && multi_line_strings_allowed();
if (multi_line || literals)
if (multi_line || literals || allow_bare)
{
utf8_decoder decoder;
bool has_line_breaks = false;
bool has_control_chars = false;
bool has_single_quotes = false;
for (size_t i = 0; i < str.length() && !(has_line_breaks && has_control_chars && has_single_quotes); i++)
for (size_t i = 0; i < str.length(); i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
@ -12540,6 +12568,7 @@ TOML_IMPL_NAMESPACE_START
has_line_breaks = false;
has_control_chars = true; // force ""
has_single_quotes = true;
allow_bare = false;
break;
}
else if (decoder.has_code_point())
@ -12550,13 +12579,20 @@ TOML_IMPL_NAMESPACE_START
has_control_chars = true;
else if (decoder.codepoint == U'\'')
has_single_quotes = true;
if (allow_bare)
allow_bare = is_bare_key_character(decoder.codepoint);
}
if (has_line_breaks && has_control_chars && has_single_quotes && !allow_bare)
break;
}
multi_line = multi_line && has_line_breaks;
literals = literals && !has_control_chars && !(!multi_line && has_single_quotes);
}
if (literals)
if (allow_bare)
print_to_stream(*stream_, str);
else if (literals)
print_to_stream_bookended(*stream_, str, multi_line ? "'''"sv : "'"sv);
else
{
@ -12571,7 +12607,7 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
void formatter::print(const value<std::string>& val)
{
print_quoted_string(val.get());
print_string(val.get());
}
TOML_EXTERNAL_LINKAGE
@ -12602,7 +12638,24 @@ TOML_IMPL_NAMESPACE_START
TOML_EXTERNAL_LINKAGE
void formatter::print(const value<double>& val)
{
print_to_stream(*stream_, *val);
const std::string_view* inf_nan = nullptr;
switch (fpclassify(*val))
{
case fp_class::neg_inf: inf_nan = &constants_->neg_inf; break;
case fp_class::pos_inf: inf_nan = &constants_->pos_inf; break;
case fp_class::nan: inf_nan = &constants_->nan; break;
case fp_class::ok: print_to_stream(*stream_, *val); break;
default: TOML_UNREACHABLE;
}
if (inf_nan)
{
if (quote_infinities_and_nans())
print_to_stream_bookended(*stream_, *inf_nan, '"');
else
print_to_stream(*stream_, *inf_nan);
}
naked_newline_ = false;
}
@ -12695,50 +12748,6 @@ TOML_DISABLE_ARITHMETIC_WARNINGS;
TOML_NAMESPACE_START
{
TOML_EXTERNAL_LINKAGE
std::string default_formatter::make_key_segment(const std::string& str) noexcept
{
if (str.empty())
return "''"s;
else
{
bool requires_quotes = false;
{
impl::utf8_decoder decoder;
for (size_t i = 0; i < str.length() && !requires_quotes; i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
requires_quotes = true;
else if (decoder.has_code_point())
requires_quotes = !impl::is_bare_key_character(decoder.codepoint);
}
}
if (requires_quotes)
{
std::string s;
s.reserve(str.length() + 2u);
s += '"';
for (auto c : str)
{
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
s.append(impl::low_character_escape_table[c]);
else if TOML_UNLIKELY(c == '\x7F')
s.append("\\u007F"sv);
else if TOML_UNLIKELY(c == '"')
s.append("\\\""sv);
else
s += c;
}
s += '"';
return s;
}
else
return str;
}
}
TOML_EXTERNAL_LINKAGE
size_t default_formatter::count_inline_columns(const node& node) noexcept
{
@ -12840,35 +12849,9 @@ TOML_NAMESPACE_START
}
TOML_EXTERNAL_LINKAGE
void default_formatter::print_key_segment(const std::string& str)
void default_formatter::print_key_segment(std::string_view str)
{
if (str.empty())
impl::print_to_stream(base::stream(), "''"sv);
else
{
bool requires_quotes = false;
{
impl::utf8_decoder decoder;
for (size_t i = 0; i < str.length() && !requires_quotes; i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
requires_quotes = true;
else if (decoder.has_code_point())
requires_quotes = !impl::is_bare_key_character(decoder.codepoint);
}
}
if (requires_quotes)
{
impl::print_to_stream(base::stream(), '"');
impl::print_to_stream_with_escapes(base::stream(), str);
impl::print_to_stream(base::stream(), '"');
}
else
impl::print_to_stream(base::stream(), str);
}
base::clear_naked_newline();
base::print_string(str, false, true);
}
TOML_EXTERNAL_LINKAGE
@ -12878,7 +12861,7 @@ TOML_NAMESPACE_START
{
if (std::addressof(segment) > key_path_.data())
impl::print_to_stream(base::stream(), '.');
impl::print_to_stream(base::stream(), segment);
print_key_segment(segment);
}
base::clear_naked_newline();
}
@ -13049,7 +13032,7 @@ TOML_NAMESPACE_START
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));
key_path_.push_back(std::string_view{ k });
if (!skip_self)
{
@ -13079,7 +13062,7 @@ TOML_NAMESPACE_START
if (base::indent_sub_tables())
base::increase_indent();
key_path_.push_back(make_key_segment(k));
key_path_.push_back(std::string_view{ k });
for (size_t i = 0; i < arr.size(); i++)
{
@ -13149,12 +13132,12 @@ TOML_NAMESPACE_START
for (auto&& [k, v] : tbl)
{
if (first)
impl::print_to_stream(base::stream(), ", "sv);
impl::print_to_stream(base::stream(), ',');
first = true;
base::print_newline(true);
base::print_indent();
base::print_quoted_string(k, false);
base::print_string(k, false);
impl::print_to_stream(base::stream(), " : "sv);
const auto type = v.type();

View File

@ -53,6 +53,7 @@ def main():
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{{{uuid}}}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|{platform}'" Label="Configuration">
@ -119,6 +120,7 @@ def main():
<ClCompile Include="..\conformance_burntsushi_valid.cpp" />
<ClCompile Include="..\conformance_iarna_invalid.cpp" />
<ClCompile Include="..\conformance_iarna_valid.cpp" />
<ClCompile Include="..\formatters.cpp" />
<ClCompile Include="..\impl_toml.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>