tomlplusplus/include/toml++/toml_default_formatter.hpp
Mark Gillard fd07301bae improved support for __fp16, _Float16 and __float128
also:
- fixed a bunch of doxygen parsing issues
- added `#define` leak detection to the single-header script
- renamed `TOML_ALL_INLINE` to `TOML_HEADER_ONLY` (the old one still works too)
- simplified abi namespace definitions
2020-07-25 20:50:24 +03:00

276 lines
6.4 KiB
C++

//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 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 "toml_preprocessor.h"
#if !TOML_IMPLEMENTATION
#error This is an implementation-only header.
#endif
//# }}
#include "toml_default_formatter.h"
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
#include <cmath>
TOML_POP_WARNINGS
TOML_PUSH_WARNINGS
TOML_DISABLE_SWITCH_WARNINGS
TOML_DISABLE_ARITHMETIC_WARNINGS
TOML_DISABLE_PADDING_WARNINGS
TOML_DISABLE_MISC_WARNINGS
TOML_IMPL_NAMESPACE_START
{
inline constexpr size_t default_formatter_line_wrap = 120_sz;
TOML_API
TOML_EXTERNAL_LINKAGE
std::string default_formatter_make_key_segment(const std::string& str) noexcept
{
if (str.empty())
return "''"s;
else
{
bool requiresQuotes = false;
{
utf8_decoder decoder;
for (size_t i = 0; i < str.length() && !requiresQuotes; i++)
{
decoder(static_cast<uint8_t>(str[i]));
if (decoder.error())
requiresQuotes = true;
else if (decoder.has_code_point())
requiresQuotes = !is_bare_key_character(decoder.codepoint);
}
}
if (requiresQuotes)
{
std::string s;
s.reserve(str.length() + 2_sz);
s += '"';
for (auto c : str)
{
if TOML_UNLIKELY(c >= '\x00' && c <= '\x1F')
{
const auto& sv = low_character_escape_table[c];
s.append(reinterpret_cast<const char*>(sv.data()), sv.length());
}
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_API
TOML_EXTERNAL_LINKAGE
size_t default_formatter_inline_columns(const node& node) noexcept
{
switch (node.type())
{
case node_type::table:
{
auto& n = *reinterpret_cast<const table*>(&node);
if (n.empty())
return 2_sz; // "{}"
size_t weight = 3_sz; // "{ }"
for (auto&& [k, v] : n)
{
weight += k.length() + default_formatter_inline_columns(v) + 2_sz; // + ", "
if (weight >= default_formatter_line_wrap)
break;
}
return weight;
}
case node_type::array:
{
auto& n = *reinterpret_cast<const array*>(&node);
if (n.empty())
return 2_sz; // "[]"
size_t weight = 3_sz; // "[ ]"
for (auto& elem : n)
{
weight += default_formatter_inline_columns(elem) + 2_sz; // + ", "
if (weight >= default_formatter_line_wrap)
break;
}
return weight;
}
case node_type::string:
{
auto& n = *reinterpret_cast<const value<std::string>*>(&node);
return n.get().length() + 2_sz; // + ""
}
case node_type::integer:
{
auto& n = *reinterpret_cast<const value<int64_t>*>(&node);
auto v = n.get();
if (!v)
return 1_sz;
size_t weight = {};
if (v < 0)
{
weight += 1;
v *= -1;
}
return weight + static_cast<size_t>(log10(static_cast<double>(v))) + 1_sz;
}
case node_type::floating_point:
{
auto& n = *reinterpret_cast<const value<double>*>(&node);
auto v = n.get();
if (v == 0.0)
return 3_sz; // "0.0"
size_t weight = 2_sz; // ".0"
if (v < 0.0)
{
weight += 1;
v *= -1.0;
}
return weight + static_cast<size_t>(log10(static_cast<double>(v))) + 1_sz;
break;
}
case node_type::boolean: return 5_sz;
case node_type::date: [[fallthrough]];
case node_type::time: return 10_sz;
case node_type::date_time: return 30_sz;
case node_type::none: TOML_UNREACHABLE;
TOML_NO_DEFAULT_CASE;
}
TOML_UNREACHABLE;
}
TOML_API
TOML_EXTERNAL_LINKAGE
bool default_formatter_forces_multiline(const node& node, size_t starting_column_bias) noexcept
{
return (default_formatter_inline_columns(node) + starting_column_bias) > default_formatter_line_wrap;
}
}
TOML_IMPL_NAMESPACE_END
TOML_NAMESPACE_START
{
template <typename Char>
inline void default_formatter<Char>::print_inline(const toml::table& tbl)
{
if (tbl.empty())
impl::print_to_stream("{}"sv, base::stream());
else
{
impl::print_to_stream("{ "sv, base::stream());
bool first = false;
for (auto&& [k, v] : tbl)
{
if (first)
impl::print_to_stream(", "sv, base::stream());
first = true;
print_key_segment(k);
impl::print_to_stream(" = "sv, base::stream());
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:
base::print_value(v, type);
}
}
impl::print_to_stream(" }"sv, base::stream());
}
base::clear_naked_newline();
}
}
TOML_NAMESPACE_END
// implementations of windows wide string nonsense
#if TOML_WINDOWS_COMPAT
TOML_PUSH_WARNINGS
TOML_DISABLE_ALL_WARNINGS
#include <Windows.h> // fuckkkk :(
TOML_POP_WARNINGS
TOML_IMPL_NAMESPACE_START
{
TOML_API
TOML_EXTERNAL_LINKAGE
std::string narrow(std::wstring_view str) noexcept
{
if (str.empty())
return {};
std::string s;
const auto len = WideCharToMultiByte(
65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0, nullptr, nullptr
);
if (len)
{
s.resize(static_cast<size_t>(len));
WideCharToMultiByte(65001, 0, str.data(), static_cast<int>(str.length()), s.data(), len, nullptr, nullptr);
}
return s;
}
TOML_API
TOML_EXTERNAL_LINKAGE
std::wstring widen(std::string_view str) noexcept
{
if (str.empty())
return {};
std::wstring s;
const auto len = MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), nullptr, 0);
if (len)
{
s.resize(static_cast<size_t>(len));
MultiByteToWideChar(65001, 0, str.data(), static_cast<int>(str.length()), s.data(), len);
}
return s;
}
#ifdef __cpp_lib_char8_t
TOML_API
TOML_EXTERNAL_LINKAGE
std::wstring widen(std::u8string_view str) noexcept
{
if (str.empty())
return {};
return widen(std::string_view{ reinterpret_cast<const char*>(str.data()), str.length() });
}
#endif // __cpp_lib_char8_t
}
TOML_IMPL_NAMESPACE_END
#endif // TOML_WINDOWS_COMPAT
TOML_POP_WARNINGS // TOML_DISABLE_SWITCH_WARNINGS, TOML_DISABLE_ARITHMETIC_WARNINGS,
// TOML_DISABLE_PADDING_WARNINGS, TOML_DISABLE_MISC_WARNINGS