diff --git a/examples/error_printer.cpp b/examples/error_printer.cpp index 94c9943..a73d6f0 100644 --- a/examples/error_printer.cpp +++ b/examples/error_printer.cpp @@ -105,8 +105,6 @@ namespace int main() { - examples::init(); - for (auto str : invalid_parses) { if (str.empty()) diff --git a/examples/examples.h b/examples/examples.h index 716a2d5..5e30f79 100644 --- a/examples/examples.h +++ b/examples/examples.h @@ -28,17 +28,9 @@ #include #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(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 diff --git a/examples/simple_parser.cpp b/examples/simple_parser.cpp index 7c7453a..927e29f 100644 --- a/examples/simple_parser.cpp +++ b/examples/simple_parser.cpp @@ -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 { diff --git a/examples/toml_generator.cpp b/examples/toml_generator.cpp index 41a3c23..36b44e3 100644 --- a/examples/toml_generator.cpp +++ b/examples/toml_generator.cpp @@ -93,8 +93,6 @@ namespace int main(int argc, char** argv) { - examples::init(); - int node_budget{}; for (int i = 1; i < argc; i++) { diff --git a/examples/toml_to_json_transcoder.cpp b/examples/toml_to_json_transcoder.cpp index 8b95a90..2ed8f0e 100644 --- a/examples/toml_to_json_transcoder.cpp +++ b/examples/toml_to_json_transcoder.cpp @@ -14,8 +14,6 @@ using namespace std::string_view_literals; int main(int argc, char** argv) { - examples::init(); - toml::table table; try { diff --git a/include/toml++/impl/date_time.h b/include/toml++/impl/date_time.h index 828afcd..49347a3 100644 --- a/include/toml++/impl/date_time.h +++ b/include/toml++/impl/date_time.h @@ -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), typename Y, typename M, typename D) + TOML_NODISCARD_CTOR + constexpr date(Y y, M m, D d) noexcept // + : year{ static_cast(y) }, + month{ static_cast(m) }, + day{ static_cast(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), + 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(h) }, + minute{ static_cast(m) }, + second{ static_cast(s) }, + nanosecond{ static_cast(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), typename H, typename M) TOML_NODISCARD_CTOR - constexpr time_offset(int8_t h, int8_t m) noexcept // - : minutes{ static_cast(h * 60 + m) } + constexpr time_offset(H h, M m) noexcept // + : minutes{ static_cast(static_cast>(h) + * impl::common_signed_type{ 60 } + + static_cast>(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 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. /// diff --git a/include/toml++/impl/default_formatter.h b/include/toml++/impl/default_formatter.h index bf592cd..e8561bb 100644 --- a/include/toml++/impl/default_formatter.h +++ b/include/toml++/impl/default_formatter.h @@ -43,15 +43,11 @@ TOML_NAMESPACE_START /// \cond using base = impl::formatter; - std::vector key_path_; + std::vector 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 diff --git a/include/toml++/impl/default_formatter.inl b/include/toml++/impl/default_formatter.inl index 5911c17..6026b60 100644 --- a/include/toml++/impl/default_formatter.inl +++ b/include/toml++/impl/default_formatter.inl @@ -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(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(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++) { diff --git a/include/toml++/impl/formatter.h b/include/toml++/impl/formatter.h index f6ac823..209acf6 100644 --- a/include/toml++/impl/formatter.h +++ b/include/toml++/impl/formatter.h @@ -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&); @@ -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; diff --git a/include/toml++/impl/formatter.inl b/include/toml++/impl/formatter.inl index 558c95e..37b4b79 100644 --- a/include/toml++/impl/formatter.inl +++ b/include/toml++/impl/formatter.inl @@ -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(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& 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& 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; } diff --git a/include/toml++/impl/forward_declarations.h b/include/toml++/impl/forward_declarations.h index 5f21d57..da87160 100644 --- a/include/toml++/impl/forward_declarations.h +++ b/include/toml++/impl/forward_declarations.h @@ -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 using remove_cvref = std::remove_cv_t>; + template + using common_signed_type = std::common_type_t...>; + template inline constexpr bool is_one_of = (false || ... || std::is_same_v); + template + inline constexpr bool all_integral = (std::is_integral_v && ...); + template inline constexpr bool is_cvref = std::is_reference_v || std::is_const_v || std::is_volatile_v; diff --git a/include/toml++/impl/json_formatter.h b/include/toml++/impl/json_formatter.h index 4b5f76b..7ca8b3a 100644 --- a/include/toml++/impl/json_formatter.h +++ b/include/toml++/impl/json_formatter.h @@ -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 diff --git a/include/toml++/impl/json_formatter.inl b/include/toml++/impl/json_formatter.inl index 08067a3..a4375a6 100644 --- a/include/toml++/impl/json_formatter.inl +++ b/include/toml++/impl/json_formatter.inl @@ -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(); diff --git a/include/toml++/impl/parser.inl b/include/toml++/impl/parser.inl index 1845cd8..dccd5b3 100644 --- a/include/toml++/impl/parser.inl +++ b/include/toml++/impl/parser.inl @@ -494,8 +494,7 @@ TOML_ANON_NAMESPACE_END; TOML_ANON_NAMESPACE_START { template - 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(year), static_cast(month), static_cast(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(minute)); - auto time = toml::time{ - static_cast(hour), - static_cast(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(second)); - time.second = static_cast(second); + time.second = static_cast(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(minute)); - offset.minutes = static_cast((hour * 60 + minute) * sign); + offset.minutes = static_cast((hour * 60 + minute) * sign); } if (!is_eof() && !is_value_terminator(*cp)) diff --git a/include/toml++/impl/utf8.h b/include/toml++/impl/utf8.h index e394e09..4ac1264 100644 --- a/include/toml++/impl/utf8.h +++ b/include/toml++/impl/utf8.h @@ -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 }; diff --git a/tests/formatters.cpp b/tests/formatters.cpp new file mode 100644 index 0000000..930d10f --- /dev/null +++ b/tests/formatters.cpp @@ -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 +// See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT + +#include "tests.h" + +namespace +{ + template + 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(p.value)] << '\''; + else if (p.value == U'\x7F') + return os << "'\\u007F'"sv; + else if (p.value < 127u) + return os << '\'' << static_cast(static_cast(p.value)) << '\''; + else + return os << static_cast(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 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(str_a[i])); + b(static_cast(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(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::infinity() }, + { "neg_inf"sv, -std::numeric_limits::infinity() }, + { "pos_nan"sv, +std::numeric_limits::quiet_NaN() }, + { "neg_nan"sv, -std::numeric_limits::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") + {} +} diff --git a/tests/meson.build b/tests/meson.build index fff1197..d8a00ce 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -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', diff --git a/tests/vs/test_debug_x64.vcxproj b/tests/vs/test_debug_x64.vcxproj index f592f26..0cbf597 100644 --- a/tests/vs/test_debug_x64.vcxproj +++ b/tests/vs/test_debug_x64.vcxproj @@ -10,6 +10,7 @@ 16.0 {202DCF23-B4E4-5FB9-AFA8-CC9A718067FF} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x64_cpplatest.vcxproj b/tests/vs/test_debug_x64_cpplatest.vcxproj index c02bc77..3921c8c 100644 --- a/tests/vs/test_debug_x64_cpplatest.vcxproj +++ b/tests/vs/test_debug_x64_cpplatest.vcxproj @@ -10,6 +10,7 @@ 16.0 {B0B1EA1E-611A-59B6-939F-0A891C71BBF0} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x64_cpplatest_noexcept.vcxproj b/tests/vs/test_debug_x64_cpplatest_noexcept.vcxproj index fb432ed..550872f 100644 --- a/tests/vs/test_debug_x64_cpplatest_noexcept.vcxproj +++ b/tests/vs/test_debug_x64_cpplatest_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {2D040A50-F533-5977-AF7F-B25C29112025} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x64_cpplatest_noexcept_unrel.vcxproj b/tests/vs/test_debug_x64_cpplatest_noexcept_unrel.vcxproj index cac69d7..2b9f990 100644 --- a/tests/vs/test_debug_x64_cpplatest_noexcept_unrel.vcxproj +++ b/tests/vs/test_debug_x64_cpplatest_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {50988C9F-99C8-59C2-BCAA-AA1F0848472E} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x64_cpplatest_unrel.vcxproj b/tests/vs/test_debug_x64_cpplatest_unrel.vcxproj index 15de07c..5af5454 100644 --- a/tests/vs/test_debug_x64_cpplatest_unrel.vcxproj +++ b/tests/vs/test_debug_x64_cpplatest_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {39175FCA-1342-507B-90F3-E8DCFB4C48D0} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x64_noexcept.vcxproj b/tests/vs/test_debug_x64_noexcept.vcxproj index c96f047..5fe2862 100644 --- a/tests/vs/test_debug_x64_noexcept.vcxproj +++ b/tests/vs/test_debug_x64_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {70F7C29B-3468-5C09-8D47-B649CEBAB09E} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x64_noexcept_unrel.vcxproj b/tests/vs/test_debug_x64_noexcept_unrel.vcxproj index 3fa91e5..0bae49e 100644 --- a/tests/vs/test_debug_x64_noexcept_unrel.vcxproj +++ b/tests/vs/test_debug_x64_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {62191BB3-97A9-552E-93BF-BFDF4D9905DD} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x64_unrel.vcxproj b/tests/vs/test_debug_x64_unrel.vcxproj index ae20e49..ed1015d 100644 --- a/tests/vs/test_debug_x64_unrel.vcxproj +++ b/tests/vs/test_debug_x64_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {9A3431E3-4727-5FED-9C18-CCD300C2760E} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86.vcxproj b/tests/vs/test_debug_x86.vcxproj index 046d878..2ce605a 100644 --- a/tests/vs/test_debug_x86.vcxproj +++ b/tests/vs/test_debug_x86.vcxproj @@ -10,6 +10,7 @@ 16.0 {CFBAF3E0-2F81-5178-964C-F419CD2F296D} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86_cpplatest.vcxproj b/tests/vs/test_debug_x86_cpplatest.vcxproj index 7ac8255..8021b8e 100644 --- a/tests/vs/test_debug_x86_cpplatest.vcxproj +++ b/tests/vs/test_debug_x86_cpplatest.vcxproj @@ -10,6 +10,7 @@ 16.0 {AD9A5FC3-6B12-5B6F-86C0-AB2FBB8C7766} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86_cpplatest_noexcept.vcxproj b/tests/vs/test_debug_x86_cpplatest_noexcept.vcxproj index 9fc7870..e3b845a 100644 --- a/tests/vs/test_debug_x86_cpplatest_noexcept.vcxproj +++ b/tests/vs/test_debug_x86_cpplatest_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {DC05B52F-D0ED-5F40-A5EC-92C4C1D77F98} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86_cpplatest_noexcept_unrel.vcxproj b/tests/vs/test_debug_x86_cpplatest_noexcept_unrel.vcxproj index 79e5569..c6ff393 100644 --- a/tests/vs/test_debug_x86_cpplatest_noexcept_unrel.vcxproj +++ b/tests/vs/test_debug_x86_cpplatest_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {41DC0274-FFA8-5D94-AF8D-5677E3141095} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86_cpplatest_unrel.vcxproj b/tests/vs/test_debug_x86_cpplatest_unrel.vcxproj index 5b1ea82..1c57769 100644 --- a/tests/vs/test_debug_x86_cpplatest_unrel.vcxproj +++ b/tests/vs/test_debug_x86_cpplatest_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {C8B46DC3-994F-5A7C-98ED-3388BCE5D647} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86_noexcept.vcxproj b/tests/vs/test_debug_x86_noexcept.vcxproj index 3117a1c..1a0a1c2 100644 --- a/tests/vs/test_debug_x86_noexcept.vcxproj +++ b/tests/vs/test_debug_x86_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {F7375F00-0345-5F67-89C0-2B18412B40FB} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86_noexcept_unrel.vcxproj b/tests/vs/test_debug_x86_noexcept_unrel.vcxproj index 65aacb3..a8ddd10 100644 --- a/tests/vs/test_debug_x86_noexcept_unrel.vcxproj +++ b/tests/vs/test_debug_x86_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {92AAC430-36B0-51E4-8E39-F3C579EDB331} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_debug_x86_unrel.vcxproj b/tests/vs/test_debug_x86_unrel.vcxproj index fc856e8..60c6429 100644 --- a/tests/vs/test_debug_x86_unrel.vcxproj +++ b/tests/vs/test_debug_x86_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {B1EAF133-1019-510F-A083-FC04774FF12E} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64.vcxproj b/tests/vs/test_release_x64.vcxproj index cb521d6..d9a36e7 100644 --- a/tests/vs/test_release_x64.vcxproj +++ b/tests/vs/test_release_x64.vcxproj @@ -10,6 +10,7 @@ 16.0 {F70977E7-E735-5D5C-9043-CA792F1B9392} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64_cpplatest.vcxproj b/tests/vs/test_release_x64_cpplatest.vcxproj index 868cd1f..80f0b9c 100644 --- a/tests/vs/test_release_x64_cpplatest.vcxproj +++ b/tests/vs/test_release_x64_cpplatest.vcxproj @@ -10,6 +10,7 @@ 16.0 {413BDA52-0A9D-56B8-9AF3-A65019F42831} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64_cpplatest_noexcept.vcxproj b/tests/vs/test_release_x64_cpplatest_noexcept.vcxproj index cd4ad36..58d455c 100644 --- a/tests/vs/test_release_x64_cpplatest_noexcept.vcxproj +++ b/tests/vs/test_release_x64_cpplatest_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {6F6D8031-4BA9-5F07-BE1F-190A2FC3CC9C} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64_cpplatest_noexcept_unrel.vcxproj b/tests/vs/test_release_x64_cpplatest_noexcept_unrel.vcxproj index 915836d..70110e7 100644 --- a/tests/vs/test_release_x64_cpplatest_noexcept_unrel.vcxproj +++ b/tests/vs/test_release_x64_cpplatest_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {18ADA45A-11DD-5649-8492-F726E6A82803} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64_cpplatest_unrel.vcxproj b/tests/vs/test_release_x64_cpplatest_unrel.vcxproj index cf37729..e2ba9bd 100644 --- a/tests/vs/test_release_x64_cpplatest_unrel.vcxproj +++ b/tests/vs/test_release_x64_cpplatest_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {74813AFD-DB22-52FA-9108-0BADD4B0E161} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64_noexcept.vcxproj b/tests/vs/test_release_x64_noexcept.vcxproj index 9ae7b9e..88554e7 100644 --- a/tests/vs/test_release_x64_noexcept.vcxproj +++ b/tests/vs/test_release_x64_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {B1B28D93-892C-59BF-9C6F-D813EC6438A0} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64_noexcept_unrel.vcxproj b/tests/vs/test_release_x64_noexcept_unrel.vcxproj index 98d115a..919d0fb 100644 --- a/tests/vs/test_release_x64_noexcept_unrel.vcxproj +++ b/tests/vs/test_release_x64_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {6C3EA8CD-33CC-5775-ACC4-631FF5FE1E2C} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x64_unrel.vcxproj b/tests/vs/test_release_x64_unrel.vcxproj index 9e56959..026e5b2 100644 --- a/tests/vs/test_release_x64_unrel.vcxproj +++ b/tests/vs/test_release_x64_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {B3779AEA-40D6-5F3C-BC86-98E4E577E09D} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86.vcxproj b/tests/vs/test_release_x86.vcxproj index ed38b3e..2d42b8b 100644 --- a/tests/vs/test_release_x86.vcxproj +++ b/tests/vs/test_release_x86.vcxproj @@ -10,6 +10,7 @@ 16.0 {2D7D2E84-8861-529C-9C05-A1EE1FB84084} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86_cpplatest.vcxproj b/tests/vs/test_release_x86_cpplatest.vcxproj index d6980d1..3b6acd0 100644 --- a/tests/vs/test_release_x86_cpplatest.vcxproj +++ b/tests/vs/test_release_x86_cpplatest.vcxproj @@ -10,6 +10,7 @@ 16.0 {B98D8D10-4B7B-5AA8-84B5-87FE6AA80C10} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86_cpplatest_noexcept.vcxproj b/tests/vs/test_release_x86_cpplatest_noexcept.vcxproj index e7f8542..eedf951 100644 --- a/tests/vs/test_release_x86_cpplatest_noexcept.vcxproj +++ b/tests/vs/test_release_x86_cpplatest_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {C9D50E23-65F2-5C1E-BE44-7327A9FFC637} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86_cpplatest_noexcept_unrel.vcxproj b/tests/vs/test_release_x86_cpplatest_noexcept_unrel.vcxproj index 4e2f7fa..c383082 100644 --- a/tests/vs/test_release_x86_cpplatest_noexcept_unrel.vcxproj +++ b/tests/vs/test_release_x86_cpplatest_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {082D6FBD-F01E-504B-9905-25937CCE7F9A} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86_cpplatest_unrel.vcxproj b/tests/vs/test_release_x86_cpplatest_unrel.vcxproj index 6ad4736..dd38ef8 100644 --- a/tests/vs/test_release_x86_cpplatest_unrel.vcxproj +++ b/tests/vs/test_release_x86_cpplatest_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {AD2F4862-1DC2-550B-AFEF-FF3D4D477323} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86_noexcept.vcxproj b/tests/vs/test_release_x86_noexcept.vcxproj index cd6629c..cf86694 100644 --- a/tests/vs/test_release_x86_noexcept.vcxproj +++ b/tests/vs/test_release_x86_noexcept.vcxproj @@ -10,6 +10,7 @@ 16.0 {0D4D9D25-3F93-5C37-866E-F8B0AC23F851} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86_noexcept_unrel.vcxproj b/tests/vs/test_release_x86_noexcept_unrel.vcxproj index edfe9ef..1fa5b28 100644 --- a/tests/vs/test_release_x86_noexcept_unrel.vcxproj +++ b/tests/vs/test_release_x86_noexcept_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {151E9E68-E325-5B08-8722-257F2B083BAD} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/tests/vs/test_release_x86_unrel.vcxproj b/tests/vs/test_release_x86_unrel.vcxproj index c6a1e99..7c5f266 100644 --- a/tests/vs/test_release_x86_unrel.vcxproj +++ b/tests/vs/test_release_x86_unrel.vcxproj @@ -10,6 +10,7 @@ 16.0 {B3077FF1-FC90-5C14-A69F-3524F62167B1} 10.0 + x64 @@ -76,6 +77,7 @@ + NotUsing diff --git a/toml.hpp b/toml.hpp index c3f7be0..78f3d3d 100644 --- a/toml.hpp +++ b/toml.hpp @@ -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 using remove_cvref = std::remove_cv_t>; + template + using common_signed_type = std::common_type_t...>; + template inline constexpr bool is_one_of = (false || ... || std::is_same_v); + template + inline constexpr bool all_integral = (std::is_integral_v && ...); + template inline constexpr bool is_cvref = std::is_reference_v || std::is_const_v || std::is_volatile_v; @@ -1993,6 +2000,17 @@ TOML_NAMESPACE_START uint8_t day; + TOML_NODISCARD_CTOR + date() noexcept = default; + + TOML_CONSTRAINED_TEMPLATE((impl::all_integral), typename Y, typename M, typename D) + TOML_NODISCARD_CTOR + constexpr date(Y y, M m, D d) noexcept // + : year{ static_cast(y) }, + month{ static_cast(m) }, + day{ static_cast(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), + 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(h) }, + minute{ static_cast(m) }, + second{ static_cast(s) }, + nanosecond{ static_cast(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), typename H, typename M) TOML_NODISCARD_CTOR - constexpr time_offset(int8_t h, int8_t m) noexcept // - : minutes{ static_cast(h * 60 + m) } + constexpr time_offset(H h, M m) noexcept // + : minutes{ static_cast(static_cast>(h) + * impl::common_signed_type{ 60 } + + static_cast>(m)) } {} TOML_NODISCARD @@ -2180,11 +2215,7 @@ TOML_NAMESPACE_START optional 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&); @@ -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 key_path_; + std::vector 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 - 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(year), static_cast(month), static_cast(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(minute)); - auto time = toml::time{ - static_cast(hour), - static_cast(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(second)); - time.second = static_cast(second); + time.second = static_cast(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(minute)); - offset.minutes = static_cast((hour * 60 + minute) * sign); + offset.minutes = static_cast((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(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& 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& 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(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(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(); diff --git a/tools/generate_windows_test_targets.py b/tools/generate_windows_test_targets.py index 82d0e11..cacac1f 100644 --- a/tools/generate_windows_test_targets.py +++ b/tools/generate_windows_test_targets.py @@ -53,6 +53,7 @@ def main(): 16.0 {{{uuid}}} 10.0 + x64 @@ -119,6 +120,7 @@ def main(): + NotUsing