diff options
Diffstat (limited to 'vendor/toml++/impl/toml_formatter.inl')
| -rw-r--r-- | vendor/toml++/impl/toml_formatter.inl | 731 |
1 files changed, 346 insertions, 385 deletions
diff --git a/vendor/toml++/impl/toml_formatter.inl b/vendor/toml++/impl/toml_formatter.inl index e764448..02c6d0b 100644 --- a/vendor/toml++/impl/toml_formatter.inl +++ b/vendor/toml++/impl/toml_formatter.inl @@ -1,405 +1,366 @@ -//# 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 +// # This file is a part of toml++ and is subject to the the terms of the MIT license. +// # Copyright (c) Mark Gillard <mark.gillard@outlook.com.au> +// # See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT #pragma once #include "preprocessor.hpp" -//# {{ +// # {{ #if !TOML_IMPLEMENTATION #error This is an implementation-only header. #endif -//# }} +// # }} #if TOML_ENABLE_FORMATTERS -#include "toml_formatter.hpp" +#include "array.hpp" +#include "header_start.hpp" #include "print_to_stream.hpp" -#include "value.hpp" #include "table.hpp" -#include "array.hpp" +#include "toml_formatter.hpp" #include "unicode.hpp" -#include "header_start.hpp" +#include "value.hpp" TOML_DISABLE_ARITHMETIC_WARNINGS; -TOML_ANON_NAMESPACE_START -{ - TOML_INTERNAL_LINKAGE - size_t toml_formatter_count_inline_columns(const node& node, size_t line_wrap_cols) noexcept - { - switch (node.type()) - { - case node_type::table: - { - auto& tbl = *reinterpret_cast<const table*>(&node); - if (tbl.empty()) - return 2u; // "{}" - size_t weight = 3u; // "{ }" - for (auto&& [k, v] : tbl) - { - weight += k.length() + toml_formatter_count_inline_columns(v, line_wrap_cols) + 2u; // + ", " - if (weight >= line_wrap_cols) - break; - } - return weight; - } - - case node_type::array: - { - auto& arr = *reinterpret_cast<const array*>(&node); - if (arr.empty()) - return 2u; // "[]" - size_t weight = 3u; // "[ ]" - for (auto& elem : arr) - { - weight += toml_formatter_count_inline_columns(elem, line_wrap_cols) + 2u; // + ", " - if (weight >= line_wrap_cols) - break; - } - return weight; - } - - case node_type::string: - { - // todo: proper utf8 decoding? - // todo: tab awareness? - auto& str = (*reinterpret_cast<const value<std::string>*>(&node)).get(); - return str.length() + 2u; // + "" - } - - case node_type::integer: - { - auto val = (*reinterpret_cast<const value<int64_t>*>(&node)).get(); - if (!val) - return 1u; - size_t weight = {}; - if (val < 0) - { - weight += 1u; - val *= -1; - } - return weight + static_cast<size_t>(log10(static_cast<double>(val))) + 1u; - } - - case node_type::floating_point: - { - auto val = (*reinterpret_cast<const value<double>*>(&node)).get(); - if (val == 0.0) - return 3u; // "0.0" - size_t weight = 2u; // ".0" - if (val < 0.0) - { - weight += 1u; - val *= -1.0; - } - return weight + static_cast<size_t>(log10(val)) + 1u; - break; - } - - case node_type::boolean: return 5u; - case node_type::date: [[fallthrough]]; - case node_type::time: return 10u; - case node_type::date_time: return 30u; - case node_type::none: TOML_UNREACHABLE; - default: TOML_UNREACHABLE; - } - - TOML_UNREACHABLE; - } - - TOML_INTERNAL_LINKAGE - bool toml_formatter_forces_multiline(const node& node, size_t line_wrap_cols, size_t starting_column_bias) noexcept - { - return (toml_formatter_count_inline_columns(node, line_wrap_cols) + starting_column_bias) >= line_wrap_cols; - } +TOML_ANON_NAMESPACE_START { + TOML_INTERNAL_LINKAGE + size_t toml_formatter_count_inline_columns(const node& node, size_t line_wrap_cols) noexcept { + switch (node.type()) { + case node_type::table: { + auto& tbl = *reinterpret_cast<const table*>(&node); + if (tbl.empty()) return 2u; // "{}" + size_t weight = 3u; // "{ }" + for (auto&& [k, v] : tbl) { + weight += + k.length() + toml_formatter_count_inline_columns(v, line_wrap_cols) + 2u; // + ", " + if (weight >= line_wrap_cols) break; + } + return weight; + } + + case node_type::array: { + auto& arr = *reinterpret_cast<const array*>(&node); + if (arr.empty()) return 2u; // "[]" + size_t weight = 3u; // "[ ]" + for (auto& elem : arr) { + weight += toml_formatter_count_inline_columns(elem, line_wrap_cols) + 2u; // + ", " + if (weight >= line_wrap_cols) break; + } + return weight; + } + + case node_type::string: { + // todo: proper utf8 decoding? + // todo: tab awareness? + auto& str = (*reinterpret_cast<const value<std::string>*>(&node)).get(); + return str.length() + 2u; // + "" + } + + case node_type::integer: { + auto val = (*reinterpret_cast<const value<int64_t>*>(&node)).get(); + if (!val) return 1u; + size_t weight = {}; + if (val < 0) { + weight += 1u; + val *= -1; + } + return weight + static_cast<size_t>(log10(static_cast<double>(val))) + 1u; + } + + case node_type::floating_point: { + auto val = (*reinterpret_cast<const value<double>*>(&node)).get(); + if (val == 0.0) return 3u; // "0.0" + size_t weight = 2u; // ".0" + if (val < 0.0) { + weight += 1u; + val *= -1.0; + } + return weight + static_cast<size_t>(log10(val)) + 1u; + break; + } + + case node_type::boolean: + return 5u; + case node_type::date: + [[fallthrough]]; + case node_type::time: + return 10u; + case node_type::date_time: + return 30u; + case node_type::none: + TOML_UNREACHABLE; + default: + TOML_UNREACHABLE; + } + + TOML_UNREACHABLE; + } + + TOML_INTERNAL_LINKAGE + bool toml_formatter_forces_multiline(const node& node, size_t line_wrap_cols, + size_t starting_column_bias) noexcept { + return (toml_formatter_count_inline_columns(node, line_wrap_cols) + starting_column_bias) >= + line_wrap_cols; + } } TOML_ANON_NAMESPACE_END; -TOML_NAMESPACE_START -{ - TOML_EXTERNAL_LINKAGE - void toml_formatter::print_pending_table_separator() - { - if (pending_table_separator_) - { - print_newline(true); - print_newline(true); - pending_table_separator_ = false; - } - } - - TOML_EXTERNAL_LINKAGE - void toml_formatter::print(const key& k) - { - print_string(k.str(), false, true, false); - } - - TOML_EXTERNAL_LINKAGE - void toml_formatter::print_inline(const table& tbl) - { - if (tbl.empty()) - { - print_unformatted("{}"sv); - return; - } - - print_unformatted("{ "sv); - - bool first = false; - for (auto&& [k, v] : tbl) - { - if (first) - print_unformatted(", "sv); - first = true; - - print(k); - if (terse_kvps()) - print_unformatted("="sv); - else - print_unformatted(" = "sv); - - const auto type = v.type(); - TOML_ASSUME(type != node_type::none); - switch (type) - { - case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break; - case node_type::array: print(*reinterpret_cast<const array*>(&v)); break; - default: print_value(v, type); - } - } - - print_unformatted(" }"sv); - } - - TOML_EXTERNAL_LINKAGE - void toml_formatter::print(const array& arr) - { - if (arr.empty()) - { - print_unformatted("[]"sv); - return; - } - - const auto original_indent = indent(); - const auto multiline = TOML_ANON_NAMESPACE::toml_formatter_forces_multiline( - arr, - 120u, - indent_columns() * static_cast<size_t>(original_indent < 0 ? 0 : original_indent)); - - print_unformatted("["sv); - - if (multiline) - { - if (original_indent < 0) - indent(0); - if (indent_array_elements()) - increase_indent(); - } - else - print_unformatted(' '); - - for (size_t i = 0; i < arr.size(); i++) - { - if (i > 0u) - { - print_unformatted(','); - if (!multiline) - print_unformatted(' '); - } - - if (multiline) - { - print_newline(true); - print_indent(); - } - - auto& v = arr[i]; - const auto type = v.type(); - TOML_ASSUME(type != node_type::none); - switch (type) - { - case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break; - case node_type::array: print(*reinterpret_cast<const array*>(&v)); break; - default: print_value(v, type); - } - } - if (multiline) - { - indent(original_indent); - print_newline(true); - print_indent(); - } - else - print_unformatted(' '); - - print_unformatted("]"sv); - } - - TOML_EXTERNAL_LINKAGE - void toml_formatter::print(const table& tbl) - { - static constexpr auto is_non_inline_array_of_tables = [](const node& n) noexcept - { - const auto arr = n.as_array(); - if (!arr || !arr->is_array_of_tables()) - return false; - - return !reinterpret_cast<const table*>(&(*arr)[0])->is_inline(); - }; - - // values, arrays, and inline tables/table arrays - for (auto&& [k, v] : tbl) - { - const auto type = v.type(); - if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline()) - || (type == node_type::array && is_non_inline_array_of_tables(v))) - continue; - - pending_table_separator_ = true; - print_newline(); - print_indent(); - print(k); - if (terse_kvps()) - print_unformatted("="sv); - else - print_unformatted(" = "sv); - TOML_ASSUME(type != node_type::none); - switch (type) - { - case node_type::table: print_inline(*reinterpret_cast<const table*>(&v)); break; - case node_type::array: print(*reinterpret_cast<const array*>(&v)); break; - default: print_value(v, type); - } - } - - const auto print_key_path = [&]() - { - size_t i{}; - for (const auto k : key_path_) - { - if (i++) - print_unformatted('.'); - print(*k); - } - }; - - // non-inline tables - for (auto&& [k, v] : tbl) - { - const auto type = v.type(); - if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline()) - continue; - auto& child_tbl = *reinterpret_cast<const table*>(&v); - - // we can skip indenting and emitting the headers for tables that only contain other tables - // (so we don't over-nest) - size_t child_value_count{}; // includes inline tables and non-table arrays - size_t child_table_count{}; - size_t child_table_array_count{}; - for (auto&& [child_k, child_v] : child_tbl) - { - TOML_UNUSED(child_k); - const auto child_type = child_v.type(); - TOML_ASSUME(child_type != node_type::none); - switch (child_type) - { - case node_type::table: - if (reinterpret_cast<const table*>(&child_v)->is_inline()) - child_value_count++; - else - child_table_count++; - break; - - case node_type::array: - if (is_non_inline_array_of_tables(child_v)) - child_table_array_count++; - else - child_value_count++; - break; - - default: child_value_count++; - } - } - bool skip_self = false; - if (child_value_count == 0u && (child_table_count > 0u || child_table_array_count > 0u)) - skip_self = true; - - key_path_.push_back(&k); - - if (!skip_self) - { - print_pending_table_separator(); - if (indent_sub_tables()) - increase_indent(); - print_indent(); - print_unformatted("["sv); - print_key_path(); - print_unformatted("]"sv); - pending_table_separator_ = true; - } - - print(child_tbl); - - key_path_.pop_back(); - if (!skip_self && indent_sub_tables()) - decrease_indent(); - } - - // table arrays - for (auto&& [k, v] : tbl) - { - if (!is_non_inline_array_of_tables(v)) - continue; - auto& arr = *reinterpret_cast<const array*>(&v); - - if (indent_sub_tables()) - increase_indent(); - key_path_.push_back(&k); - - for (size_t i = 0; i < arr.size(); i++) - { - print_pending_table_separator(); - print_indent(); - print_unformatted("[["sv); - print_key_path(); - print_unformatted("]]"sv); - pending_table_separator_ = true; - print(*reinterpret_cast<const table*>(&arr[i])); - } - - key_path_.pop_back(); - if (indent_sub_tables()) - decrease_indent(); - } - } - - TOML_EXTERNAL_LINKAGE - void toml_formatter::print() - { - if (dump_failed_parse_result()) - return; - - switch (auto source_type = source().type()) - { - case node_type::table: - { - auto& tbl = *reinterpret_cast<const table*>(&source()); - if (tbl.is_inline()) - print_inline(tbl); - else - { - decrease_indent(); // so root kvps and tables have the same indent - print(tbl); - } - break; - } - - case node_type::array: print(*reinterpret_cast<const array*>(&source())); break; - - default: print_value(source(), source_type); - } - } +TOML_NAMESPACE_START { + TOML_EXTERNAL_LINKAGE + void toml_formatter::print_pending_table_separator() { + if (pending_table_separator_) { + print_newline(true); + print_newline(true); + pending_table_separator_ = false; + } + } + + TOML_EXTERNAL_LINKAGE + void toml_formatter::print(const key& k) { + print_string(k.str(), false, true, false); + } + + TOML_EXTERNAL_LINKAGE + void toml_formatter::print_inline(const table& tbl) { + if (tbl.empty()) { + print_unformatted("{}"sv); + return; + } + + print_unformatted("{ "sv); + + bool first = false; + for (auto&& [k, v] : tbl) { + if (first) print_unformatted(", "sv); + first = true; + + print(k); + if (terse_kvps()) + print_unformatted("="sv); + else + print_unformatted(" = "sv); + + const auto type = v.type(); + TOML_ASSUME(type != node_type::none); + switch (type) { + case node_type::table: + print_inline(*reinterpret_cast<const table*>(&v)); + break; + case node_type::array: + print(*reinterpret_cast<const array*>(&v)); + break; + default: + print_value(v, type); + } + } + + print_unformatted(" }"sv); + } + + TOML_EXTERNAL_LINKAGE + void toml_formatter::print(const array& arr) { + if (arr.empty()) { + print_unformatted("[]"sv); + return; + } + + const auto original_indent = indent(); + const auto multiline = TOML_ANON_NAMESPACE::toml_formatter_forces_multiline( + arr, 120u, + indent_columns() * static_cast<size_t>(original_indent < 0 ? 0 : original_indent)); + + print_unformatted("["sv); + + if (multiline) { + if (original_indent < 0) indent(0); + if (indent_array_elements()) increase_indent(); + } else + print_unformatted(' '); + + for (size_t i = 0; i < arr.size(); i++) { + if (i > 0u) { + print_unformatted(','); + if (!multiline) print_unformatted(' '); + } + + if (multiline) { + print_newline(true); + print_indent(); + } + + auto& v = arr[i]; + const auto type = v.type(); + TOML_ASSUME(type != node_type::none); + switch (type) { + case node_type::table: + print_inline(*reinterpret_cast<const table*>(&v)); + break; + case node_type::array: + print(*reinterpret_cast<const array*>(&v)); + break; + default: + print_value(v, type); + } + } + if (multiline) { + indent(original_indent); + print_newline(true); + print_indent(); + } else + print_unformatted(' '); + + print_unformatted("]"sv); + } + + TOML_EXTERNAL_LINKAGE + void toml_formatter::print(const table& tbl) { + static constexpr auto is_non_inline_array_of_tables = [](const node& n) noexcept { + const auto arr = n.as_array(); + if (!arr || !arr->is_array_of_tables()) return false; + + return !reinterpret_cast<const table*>(&(*arr)[0])->is_inline(); + }; + + // values, arrays, and inline tables/table arrays + for (auto&& [k, v] : tbl) { + const auto type = v.type(); + if ((type == node_type::table && !reinterpret_cast<const table*>(&v)->is_inline()) || + (type == node_type::array && is_non_inline_array_of_tables(v))) + continue; + + pending_table_separator_ = true; + print_newline(); + print_indent(); + print(k); + if (terse_kvps()) + print_unformatted("="sv); + else + print_unformatted(" = "sv); + TOML_ASSUME(type != node_type::none); + switch (type) { + case node_type::table: + print_inline(*reinterpret_cast<const table*>(&v)); + break; + case node_type::array: + print(*reinterpret_cast<const array*>(&v)); + break; + default: + print_value(v, type); + } + } + + const auto print_key_path = [&]() { + size_t i{}; + for (const auto k : key_path_) { + if (i++) print_unformatted('.'); + print(*k); + } + }; + + // non-inline tables + for (auto&& [k, v] : tbl) { + const auto type = v.type(); + if (type != node_type::table || reinterpret_cast<const table*>(&v)->is_inline()) continue; + auto& child_tbl = *reinterpret_cast<const table*>(&v); + + // we can skip indenting and emitting the headers for tables that only contain other tables + // (so we don't over-nest) + size_t child_value_count{}; // includes inline tables and non-table arrays + size_t child_table_count{}; + size_t child_table_array_count{}; + for (auto&& [child_k, child_v] : child_tbl) { + TOML_UNUSED(child_k); + const auto child_type = child_v.type(); + TOML_ASSUME(child_type != node_type::none); + switch (child_type) { + case node_type::table: + if (reinterpret_cast<const table*>(&child_v)->is_inline()) + child_value_count++; + else + child_table_count++; + break; + + case node_type::array: + if (is_non_inline_array_of_tables(child_v)) + child_table_array_count++; + else + child_value_count++; + break; + + default: + child_value_count++; + } + } + bool skip_self = false; + if (child_value_count == 0u && (child_table_count > 0u || child_table_array_count > 0u)) + skip_self = true; + + key_path_.push_back(&k); + + if (!skip_self) { + print_pending_table_separator(); + if (indent_sub_tables()) increase_indent(); + print_indent(); + print_unformatted("["sv); + print_key_path(); + print_unformatted("]"sv); + pending_table_separator_ = true; + } + + print(child_tbl); + + key_path_.pop_back(); + if (!skip_self && indent_sub_tables()) decrease_indent(); + } + + // table arrays + for (auto&& [k, v] : tbl) { + if (!is_non_inline_array_of_tables(v)) continue; + auto& arr = *reinterpret_cast<const array*>(&v); + + if (indent_sub_tables()) increase_indent(); + key_path_.push_back(&k); + + for (size_t i = 0; i < arr.size(); i++) { + print_pending_table_separator(); + print_indent(); + print_unformatted("[["sv); + print_key_path(); + print_unformatted("]]"sv); + pending_table_separator_ = true; + print(*reinterpret_cast<const table*>(&arr[i])); + } + + key_path_.pop_back(); + if (indent_sub_tables()) decrease_indent(); + } + } + + TOML_EXTERNAL_LINKAGE + void toml_formatter::print() { + if (dump_failed_parse_result()) return; + + switch (auto source_type = source().type()) { + case node_type::table: { + auto& tbl = *reinterpret_cast<const table*>(&source()); + if (tbl.is_inline()) + print_inline(tbl); + else { + decrease_indent(); // so root kvps and tables have the same indent + print(tbl); + } + break; + } + + case node_type::array: + print(*reinterpret_cast<const array*>(&source())); + break; + + default: + print_value(source(), source_type); + } + } } TOML_NAMESPACE_END; #include "header_end.hpp" -#endif // TOML_ENABLE_FORMATTERS +#endif // TOML_ENABLE_FORMATTERS |
