diff --git a/.clang-format b/.clang-format index 5ce2c28..ed1b66c 100644 --- a/.clang-format +++ b/.clang-format @@ -156,12 +156,16 @@ StatementMacros: - TOML_ALWAYS_INLINE - TOML_API - TOML_ATTR + - TOML_CONST_GETTER + - TOML_CONST_INLINE_GETTER - TOML_EXTERNAL_LINKAGE - TOML_INTERNAL_LINKAGE - TOML_MEMBER_ATTR - TOML_NEVER_INLINE - TOML_NODISCARD - TOML_NODISCARD_CTOR + - TOML_PURE_GETTER + - TOML_PURE_INLINE_GETTER - TOML_RETURNS_BY_THROWING TabWidth: 4 TypenameMacros: diff --git a/cpp.hint b/cpp.hint index 0a481ff..b35bf38 100644 --- a/cpp.hint +++ b/cpp.hint @@ -1,24 +1,28 @@ -#define TOML_API -#define TOML_ATTR(...) -#define TOML_ALWAYS_INLINE inline -#define TOML_NEVER_INLINE -#define TOML_TRIVIAL_ABI -#define TOML_ABSTRACT_BASE -#define TOML_EMPTY_BASES -#define TOML_CONSTRAINED_TEMPLATE(cond, ...) template <__VA_ARGS__> -#define TOML_LIKELY(...) (__VA_ARGS__) -#define TOML_UNLIKELY(...) (__VA_ARGS__) -#define TOML_NODISCARD -#define TOML_NODISCARD_CTOR -#define TOML_RETURNS_BY_THROWING -#define TOML_EXTERN_NOEXCEPT(...) -#define TOML_EXTERNAL_LINKAGE -#define TOML_INTERNAL_LINKAGE static -#define TOML_ANON_NAMESPACE_START namespace -#define TOML_ANON_NAMESPACE_END static_assert(true) #define TOML_ABI_NAMESPACE_BOOL(...) static_assert(true) #define TOML_ABI_NAMESPACE_END static_assert(true) -#define TOML_NAMESPACE_START namespace toml -#define TOML_NAMESPACE_END static_assert(true) -#define TOML_IMPL_NAMESPACE_START namespace toml::impl +#define TOML_ABSTRACT_BASE +#define TOML_ALWAYS_INLINE inline +#define TOML_ANON_NAMESPACE_END static_assert(true) +#define TOML_ANON_NAMESPACE_START namespace +#define TOML_API +#define TOML_ATTR(...) +#define TOML_CONST_GETTER +#define TOML_CONST_INLINE_GETTER inline +#define TOML_CONSTRAINED_TEMPLATE(cond, ...) template <__VA_ARGS__> +#define TOML_EMPTY_BASES +#define TOML_EXTERN_NOEXCEPT(...) +#define TOML_EXTERNAL_LINKAGE #define TOML_IMPL_NAMESPACE_END static_assert(true) +#define TOML_IMPL_NAMESPACE_START namespace toml::impl +#define TOML_INTERNAL_LINKAGE static +#define TOML_LIKELY(...) (__VA_ARGS__) +#define TOML_NAMESPACE_END static_assert(true) +#define TOML_NAMESPACE_START namespace toml +#define TOML_NEVER_INLINE +#define TOML_NODISCARD +#define TOML_NODISCARD_CTOR +#define TOML_PURE_GETTER +#define TOML_PURE_INLINE_GETTER inline +#define TOML_RETURNS_BY_THROWING +#define TOML_TRIVIAL_ABI +#define TOML_UNLIKELY(...) (__VA_ARGS__) diff --git a/include/toml++/impl/default_formatter.h b/include/toml++/impl/default_formatter.h index 392b295..b9dedde 100644 --- a/include/toml++/impl/default_formatter.h +++ b/include/toml++/impl/default_formatter.h @@ -81,13 +81,17 @@ 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; + /// \endcond public: /// \brief The default flags for a default_formatter. - static constexpr format_flags default_flags = format_flags::allow_literal_strings - | format_flags::allow_multi_line_strings - | format_flags::allow_value_format_flags; + static constexpr format_flags default_flags = format_flags::allow_literal_strings // + | format_flags::allow_multi_line_strings // + | format_flags::allow_value_format_flags // + | format_flags::indentation; /// \brief Constructs a default formatter and binds it to a TOML object. /// @@ -95,7 +99,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 } + : base{ source, (flags | mandatory_flags) & ~ignored_flags } {} #if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS) @@ -124,7 +128,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 } + : base{ result, (flags | mandatory_flags) & ~ignored_flags } {} #endif diff --git a/include/toml++/impl/default_formatter.inl b/include/toml++/impl/default_formatter.inl index 46c1038..a201c61 100644 --- a/include/toml++/impl/default_formatter.inl +++ b/include/toml++/impl/default_formatter.inl @@ -260,7 +260,8 @@ TOML_NAMESPACE_START { if (original_indent < 0) base::indent(0); - base::increase_indent(); + if (base::indent_array_elements()) + base::increase_indent(); } else impl::print_to_stream(base::stream(), ' '); @@ -380,7 +381,8 @@ TOML_NAMESPACE_START if (!skip_self) { print_pending_table_separator(); - base::increase_indent(); + if (base::indent_sub_tables()) + base::increase_indent(); base::print_indent(); impl::print_to_stream(base::stream(), "["sv); print_key_path(); @@ -391,7 +393,7 @@ TOML_NAMESPACE_START print(child_tbl); key_path_.pop_back(); - if (!skip_self) + if (!skip_self && base::indent_sub_tables()) base::decrease_indent(); } @@ -402,7 +404,8 @@ TOML_NAMESPACE_START continue; auto& arr = *reinterpret_cast(&v); - base::increase_indent(); + if (base::indent_sub_tables()) + base::increase_indent(); key_path_.push_back(make_key_segment(k)); for (size_t i = 0; i < arr.size(); i++) @@ -417,7 +420,8 @@ TOML_NAMESPACE_START } key_path_.pop_back(); - base::decrease_indent(); + if (base::indent_sub_tables()) + base::decrease_indent(); } } diff --git a/include/toml++/impl/formatter.h b/include/toml++/impl/formatter.h index 774bbda..d753934 100644 --- a/include/toml++/impl/formatter.h +++ b/include/toml++/impl/formatter.h @@ -16,32 +16,30 @@ TOML_IMPL_NAMESPACE_START private: const toml::node* source_; std::ostream* stream_ = {}; - format_flags flags_; - int indent_; - bool naked_newline_; + format_flags flags_; // + int indent_; // these are set in attach() + bool naked_newline_; // #if TOML_PARSER && !TOML_EXCEPTIONS const parse_result* result_ = {}; #endif protected: - TOML_NODISCARD - TOML_ALWAYS_INLINE + static constexpr size_t indent_columns = 4; + static constexpr std::string_view indent_string = " "sv; + + TOML_PURE_INLINE_GETTER const toml::node& source() const noexcept { return *source_; } - TOML_NODISCARD - TOML_ALWAYS_INLINE + TOML_PURE_INLINE_GETTER std::ostream& stream() const noexcept { return *stream_; } - static constexpr size_t indent_columns = 4; - static constexpr std::string_view indent_string = " "sv; - - TOML_NODISCARD + TOML_PURE_INLINE_GETTER int indent() const noexcept { return indent_; @@ -62,31 +60,43 @@ TOML_IMPL_NAMESPACE_START indent_--; } - TOML_NODISCARD + TOML_PURE_INLINE_GETTER + bool indent_array_elements() const noexcept + { + return !!(flags_ & format_flags::indent_array_elements); + } + + TOML_PURE_INLINE_GETTER + bool indent_sub_tables() const noexcept + { + return !!(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); } - TOML_NODISCARD + TOML_PURE_INLINE_GETTER bool literal_strings_allowed() const noexcept { return !!(flags_ & format_flags::allow_literal_strings); } - TOML_NODISCARD + TOML_PURE_INLINE_GETTER bool multi_line_strings_allowed() const noexcept { return !!(flags_ & format_flags::allow_multi_line_strings); } - TOML_NODISCARD + TOML_PURE_INLINE_GETTER bool value_format_flags_allowed() const noexcept { return !!(flags_ & format_flags::allow_value_format_flags); } - TOML_NODISCARD + TOML_PURE_INLINE_GETTER bool naked_newline() const noexcept { return naked_newline_; diff --git a/include/toml++/impl/formatter.inl b/include/toml++/impl/formatter.inl index 76b3734..94f88c5 100644 --- a/include/toml++/impl/formatter.inl +++ b/include/toml++/impl/formatter.inl @@ -213,18 +213,29 @@ TOML_IMPL_NAMESPACE_START } } - TOML_EXTERNAL_LINKAGE - bool formatter::dump_failed_parse_result() noexcept(!TOML_PARSER || TOML_EXCEPTIONS) - { #if TOML_PARSER && !TOML_EXCEPTIONS + + TOML_EXTERNAL_LINKAGE + bool formatter::dump_failed_parse_result() noexcept(false) + { if (result_ && !(*result_)) { stream() << result_->error(); return true; } -#endif return false; } + +#else + + TOML_EXTERNAL_LINKAGE + TOML_ATTR(const) + bool formatter::dump_failed_parse_result() noexcept(true) + { + return false; + } + +#endif } TOML_IMPL_NAMESPACE_END; diff --git a/include/toml++/impl/forward_declarations.h b/include/toml++/impl/forward_declarations.h index eae6adc..319eade 100644 --- a/include/toml++/impl/forward_declarations.h +++ b/include/toml++/impl/forward_declarations.h @@ -267,7 +267,7 @@ TOML_NAMESPACE_START // abi namespace } /// \brief Metadata associated with TOML values. - enum class value_flags : uint8_t + enum class value_flags : uint16_t { /// \brief None. none, @@ -284,7 +284,10 @@ TOML_NAMESPACE_START // abi namespace TOML_MAKE_FLAGS(value_flags); /// \brief Format flags for modifying how TOML data is printed to streams. - enum class format_flags : uint8_t + /// + /// \note Formatters may disregard/override any of these flags according to the requirements of their + /// output target (e.g. #toml::json_formatter JSON always apply quotes to dates and times). + enum class format_flags : uint64_t { /// \brief None. none, @@ -300,6 +303,15 @@ TOML_NAMESPACE_START // abi namespace /// \brief Values with special format flags will be formatted accordingly. allow_value_format_flags = 8, + + /// \brief Apply indentation to tables nested within other tables/arrays. + indent_sub_tables = 16, + + /// \brief Apply indentation to array elements when the array is forced to wrap over multiple lines. + indent_array_elements = 32, + + /// \brief Combination mask of all indentation-enabling flags. + indentation = indent_sub_tables | indent_array_elements, }; TOML_MAKE_FLAGS(format_flags); diff --git a/include/toml++/impl/json_formatter.h b/include/toml++/impl/json_formatter.h index aad9cb9..aedf8ba 100644 --- a/include/toml++/impl/json_formatter.h +++ b/include/toml++/impl/json_formatter.h @@ -55,11 +55,16 @@ TOML_NAMESPACE_START TOML_API void print(); + 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; + /// \endcond 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::indentation; /// \brief Constructs a JSON formatter and binds it to a TOML object. /// @@ -67,7 +72,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 } + : base{ source, (flags | mandatory_flags) & ~ignored_flags } {} #if defined(DOXYGEN) || (TOML_PARSER && !TOML_EXCEPTIONS) @@ -98,7 +103,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 } + : base{ result, (flags | mandatory_flags) & ~ignored_flags } {} #endif diff --git a/include/toml++/impl/json_formatter.inl b/include/toml++/impl/json_formatter.inl index d9f50c2..08067a3 100644 --- a/include/toml++/impl/json_formatter.inl +++ b/include/toml++/impl/json_formatter.inl @@ -27,7 +27,8 @@ TOML_NAMESPACE_START else { impl::print_to_stream(base::stream(), '{'); - base::increase_indent(); + if (base::indent_sub_tables()) + base::increase_indent(); bool first = false; for (auto&& [k, v] : tbl) { @@ -49,7 +50,8 @@ TOML_NAMESPACE_START default: base::print_value(v, type); } } - base::decrease_indent(); + if (base::indent_sub_tables()) + base::decrease_indent(); base::print_newline(true); base::print_indent(); impl::print_to_stream(base::stream(), '}'); @@ -65,7 +67,8 @@ TOML_NAMESPACE_START else { impl::print_to_stream(base::stream(), '['); - base::increase_indent(); + if (base::indent_array_elements()) + base::increase_indent(); for (size_t i = 0; i < arr.size(); i++) { if (i > 0u) @@ -83,7 +86,8 @@ TOML_NAMESPACE_START default: base::print_value(v, type); } } - base::decrease_indent(); + if (base::indent_array_elements()) + base::decrease_indent(); base::print_newline(true); base::print_indent(); impl::print_to_stream(base::stream(), ']'); diff --git a/include/toml++/impl/node.h b/include/toml++/impl/node.h index f6f3bb0..92c9c08 100644 --- a/include/toml++/impl/node.h +++ b/include/toml++/impl/node.h @@ -27,8 +27,7 @@ TOML_NAMESPACE_START decltype(auto) get_value_exact() const noexcept(impl::value_retrieval_is_nothrow); template - TOML_NODISCARD - TOML_ATTR(pure) + TOML_PURE_GETTER static decltype(auto) do_ref(N&& n) noexcept { using type = impl::unwrap_node; @@ -59,27 +58,21 @@ TOML_NAMESPACE_START node& operator=(node&&) noexcept; template - TOML_NODISCARD - TOML_ALWAYS_INLINE - TOML_ATTR(pure) + TOML_PURE_INLINE_GETTER impl::wrap_node& ref_cast() & noexcept { return *reinterpret_cast*>(this); } template - TOML_NODISCARD - TOML_ALWAYS_INLINE - TOML_ATTR(pure) + TOML_PURE_INLINE_GETTER impl::wrap_node&& ref_cast() && noexcept { return std::move(*reinterpret_cast*>(this)); } template - TOML_NODISCARD - TOML_ALWAYS_INLINE - TOML_ATTR(pure) + TOML_PURE_INLINE_GETTER const impl::wrap_node& ref_cast() const& noexcept { return *reinterpret_cast*>(this); @@ -102,84 +95,84 @@ TOML_NAMESPACE_START virtual node_type type() const noexcept = 0; /// \brief Returns true if this node is a table. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_table() const noexcept { return false; } /// \brief Returns true if this node is an array. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_array() const noexcept { return false; } /// \brief Returns true if this node is a value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_value() const noexcept { return false; } /// \brief Returns true if this node is a string value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_string() const noexcept { return false; } /// \brief Returns true if this node is an integer value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_integer() const noexcept { return false; } /// \brief Returns true if this node is an floating-point value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_floating_point() const noexcept { return false; } /// \brief Returns true if this node is an integer or floating-point value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_number() const noexcept { return false; } /// \brief Returns true if this node is a boolean value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_boolean() const noexcept { return false; } /// \brief Returns true if this node is a local date value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_date() const noexcept { return false; } /// \brief Returns true if this node is a local time value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_time() const noexcept { return false; } /// \brief Returns true if this node is a date-time value. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_date_time() const noexcept { return false; } /// \brief Returns true if this node is an array containing only tables. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual bool is_array_of_tables() const noexcept { return false; @@ -191,8 +184,7 @@ TOML_NAMESPACE_START /// /// \returns Returns true if this node is an instance of the specified type. template - TOML_NODISCARD - TOML_ATTR(pure) + TOML_PURE_INLINE_GETTER bool is() const noexcept { using type = impl::unwrap_node; @@ -315,8 +307,7 @@ TOML_NAMESPACE_START /// /// \remarks Always returns `false` for empty tables and arrays. template - TOML_NODISCARD - TOML_ATTR(pure) + TOML_PURE_GETTER bool is_homogeneous() const noexcept { using type = impl::unwrap_node; @@ -334,117 +325,117 @@ TOML_NAMESPACE_START /// @{ /// \brief Returns a pointer to the node as a toml::table, if it is one. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual table* as_table() noexcept { return nullptr; } /// \brief Returns a pointer to the node as a toml::array, if it is one. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual array* as_array() noexcept { return nullptr; } /// \brief Returns a pointer to the node as a toml::value, if it is one. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual toml::value* as_string() noexcept { return nullptr; } /// \brief Returns a pointer to the node as a toml::value, if it is one. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual toml::value* as_integer() noexcept { return nullptr; } /// \brief Returns a pointer to the node as a toml::value, if it is one. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual toml::value* as_floating_point() noexcept { return nullptr; } /// \brief Returns a pointer to the node as a toml::value, if it is one. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual toml::value* as_boolean() noexcept { return nullptr; } /// \brief Returns a pointer to the node as a toml::value, if it is one. - TOML_NODISCARD + TOML_PURE_INLINE_GETTER virtual toml::value* as_date() noexcept { return nullptr; } /// \brief Returns a pointer to the node as a toml::value