9#if !TOML_IMPLEMENTATION
10#error This is an implementation-only header.
13#if TOML_ENABLE_FORMATTERS
26 size_t toml_formatter_count_inline_columns(
const node& node,
size_t line_wrap_cols)
noexcept {
27 switch (node.type()) {
28 case node_type::table: {
29 auto& tbl = *
reinterpret_cast<const table*
>(&node);
30 if (tbl.empty())
return 2u;
32 for (
auto&& [k, v] : tbl) {
34 k.length() + toml_formatter_count_inline_columns(v, line_wrap_cols) + 2u;
35 if (weight >= line_wrap_cols)
break;
40 case node_type::array: {
41 auto& arr = *
reinterpret_cast<const array*
>(&node);
42 if (arr.empty())
return 2u;
44 for (
auto& elem : arr) {
45 weight += toml_formatter_count_inline_columns(elem, line_wrap_cols) + 2u;
46 if (weight >= line_wrap_cols)
break;
51 case node_type::string: {
54 auto& str = (*
reinterpret_cast<const value<std::string>*
>(&node)).
get();
55 return str.length() + 2u;
58 case node_type::integer: {
59 auto val = (*
reinterpret_cast<const value<int64_t>*
>(&node)).get();
66 return weight +
static_cast<size_t>(log10(
static_cast<double>(val))) + 1u;
69 case node_type::floating_point: {
70 auto val = (*
reinterpret_cast<const value<double>*
>(&node)).get();
71 if (val == 0.0)
return 3u;
77 return weight +
static_cast<size_t>(log10(val)) + 1u;
81 case node_type::boolean:
87 case node_type::date_time:
99 bool toml_formatter_forces_multiline(
const node& node,
size_t line_wrap_cols,
100 size_t starting_column_bias)
noexcept {
101 return (toml_formatter_count_inline_columns(node, line_wrap_cols) + starting_column_bias) >=
109 void toml_formatter::print_pending_table_separator() {
110 if (pending_table_separator_) {
113 pending_table_separator_ =
false;
118 void toml_formatter::print(
const key& k) {
119 print_string(k.str(),
false,
true,
false);
123 void toml_formatter::print_inline(
const table& tbl) {
125 print_unformatted(
"{}"sv);
129 print_unformatted(
"{ "sv);
132 for (
auto&& [k, v] : tbl) {
133 if (first) print_unformatted(
", "sv);
138 print_unformatted(
"="sv);
140 print_unformatted(
" = "sv);
142 const auto type = v.type();
145 case node_type::table:
146 print_inline(*
reinterpret_cast<const table*
>(&v));
148 case node_type::array:
149 print(*
reinterpret_cast<const array*
>(&v));
152 print_value(v, type);
156 print_unformatted(
" }"sv);
160 void toml_formatter::print(
const array& arr) {
162 print_unformatted(
"[]"sv);
166 const auto original_indent = indent();
167 const auto multiline = TOML_ANON_NAMESPACE::toml_formatter_forces_multiline(
169 indent_columns() *
static_cast<size_t>(original_indent < 0 ? 0 : original_indent));
171 print_unformatted(
"["sv);
174 if (original_indent < 0) indent(0);
177 print_unformatted(
' ');
179 for (
size_t i = 0; i < arr.
size(); i++) {
181 print_unformatted(
',');
182 if (!multiline) print_unformatted(
' ');
191 const auto type = v.
type();
194 case node_type::table:
195 print_inline(*
reinterpret_cast<const table*
>(&v));
197 case node_type::array:
198 print(*
reinterpret_cast<const array*
>(&v));
201 print_value(v, type);
205 indent(original_indent);
209 print_unformatted(
' ');
211 print_unformatted(
"]"sv);
215 void toml_formatter::print(
const table& tbl) {
216 static constexpr auto is_non_inline_array_of_tables = [](
const node& n)
noexcept {
220 return !
reinterpret_cast<const table*
>(&(*arr)[0])->is_inline();
224 for (
auto&& [k, v] : tbl) {
225 const auto type = v.
type();
226 if ((type == node_type::table && !
reinterpret_cast<const table*
>(&v)->is_inline()) ||
227 (type == node_type::array && is_non_inline_array_of_tables(v)))
230 pending_table_separator_ =
true;
235 print_unformatted(
"="sv);
237 print_unformatted(
" = "sv);
240 case node_type::table:
241 print_inline(*
reinterpret_cast<const table*
>(&v));
243 case node_type::array:
244 print(*
reinterpret_cast<const array*
>(&v));
247 print_value(v, type);
251 const auto print_key_path = [&]() {
253 for (
const auto k : key_path_) {
254 if (i++) print_unformatted(
'.');
260 for (
auto&& [k, v] : tbl) {
261 const auto type = v.type();
262 if (type != node_type::table ||
reinterpret_cast<const table*
>(&v)->
is_inline())
continue;
263 auto& child_tbl = *
reinterpret_cast<const table*
>(&v);
267 size_t child_value_count{};
268 size_t child_table_count{};
269 size_t child_table_array_count{};
270 for (
auto&& [child_k, child_v] : child_tbl) {
272 const auto child_type = child_v.type();
274 switch (child_type) {
275 case node_type::table:
276 if (
reinterpret_cast<const table*
>(&child_v)->is_inline())
282 case node_type::array:
283 if (is_non_inline_array_of_tables(child_v))
284 child_table_array_count++;
293 bool skip_self =
false;
294 if (child_value_count == 0u && (child_table_count > 0u || child_table_array_count > 0u))
297 key_path_.push_back(&k);
300 print_pending_table_separator();
303 print_unformatted(
"["sv);
305 print_unformatted(
"]"sv);
306 pending_table_separator_ =
true;
311 key_path_.pop_back();
316 for (
auto&& [k, v] : tbl) {
317 if (!is_non_inline_array_of_tables(v))
continue;
318 auto& arr = *
reinterpret_cast<const array*
>(&v);
323 for (
size_t i = 0; i < arr.
size(); i++) {
324 print_pending_table_separator();
326 print_unformatted(
"[["sv);
328 print_unformatted(
"]]"sv);
329 pending_table_separator_ =
true;
330 print(*
reinterpret_cast<const table*
>(&arr[i]));
333 key_path_.pop_back();
339 void toml_formatter::print() {
340 if (dump_failed_parse_result())
return;
342 switch (
auto source_type = source().type()) {
343 case node_type::table: {
344 auto& tbl = *
reinterpret_cast<const table*
>(&source());
354 case node_type::array:
355 print(*
reinterpret_cast<const array*
>(&source()));
359 print_value(source(), source_type);
A TOML array.
Definition array.hpp:285
TOML_PURE_INLINE_GETTER node * get(size_t index) noexcept
Gets a pointer to the element at a specific index.
Definition array.hpp:685
TOML_PURE_GETTER bool is_array_of_tables() const noexcept final
Returns true if the array contains only tables.
Definition array.hpp:459
TOML_CONST_INLINE_GETTER node_type type() const noexcept final
Returns #toml::node_type::array.
Definition array.hpp:412
TOML_NODISCARD bool empty() const noexcept
Returns true if the array is empty.
Definition array.hpp:1129
TOML_CONST_INLINE_GETTER array * as_array() noexcept final
Returns a pointer to the array.
Definition array.hpp:541
TOML_NODISCARD size_t size() const noexcept
Returns the number of elements in the array.
Definition array.hpp:1136
void push_back(ElemType &&val, value_flags flags=preserve_source_value_flags)
Appends a new element to the end of the array.
Definition array.hpp:1633
A TOML table.
Definition table.hpp:220
TOML_PURE_INLINE_GETTER bool empty() const noexcept
Returns true if the table is empty.
Definition table.hpp:1112
TOML_CONST_INLINE_GETTER node_type type() const noexcept final
Returns #toml::node_type::table.
Definition table.hpp:292
TOML_PURE_INLINE_GETTER bool is_inline() const noexcept
Returns true if this table is an inline table.
Definition table.hpp:548
enum TOML_CLOSED_FLAGS_ENUM indent_sub_tables
Apply indentation to tables nested within other tables/arrays.
Definition forward_declarations.hpp:330
enum TOML_CLOSED_FLAGS_ENUM indent_array_elements
Apply indentation to array elements when the array is forced to wrap over multiple lines.
Definition forward_declarations.hpp:333
#define TOML_ANON_NAMESPACE_END
Definition preprocessor.hpp:1337
#define TOML_UNUSED(...)
Definition preprocessor.hpp:603
#define TOML_INTERNAL_LINKAGE
Definition preprocessor.hpp:1340
#define TOML_EXTERNAL_LINKAGE
Definition preprocessor.hpp:1339
#define TOML_UNREACHABLE
Definition preprocessor.hpp:515
#define TOML_NAMESPACE_END
Definition preprocessor.hpp:1320
#define TOML_ASSUME(expr)
Definition preprocessor.hpp:506