9#if !TOML_IMPLEMENTATION
10#error This is an implementation-only header.
23#if TOML_INT_CHARCONV || TOML_FLOAT_CHARCONV
26#if !TOML_INT_CHARCONV || !TOML_FLOAT_CHARCONV
37 inline constexpr size_t charconv_buffer_length = 0;
73 if (!min_digits) min_digits = 1;
75 for (
size_t i = 0;
i < min_digits;
i++)
stream.put(
'0');
80 static constexpr auto value_flags_mask = value_flags::format_as_binary |
81 value_flags::format_as_octal |
82 value_flags::format_as_hexadecimal;
83 format &= value_flags_mask;
86 if (format != value_flags::none &&
val >
T{}) {
88 case value_flags::format_as_binary:
91 case value_flags::format_as_octal:
94 case value_flags::format_as_hexadecimal:
106 const auto len =
static_cast<size_t>(
res.ptr -
buf);
107 for (
size_t i =
len;
i < min_digits;
i++)
stream.put(
'0');
109 for (
size_t i = 0;
i <
len;
i++)
116 using unsigned_type =
117 std::conditional_t<(
sizeof(
T) >
sizeof(
unsigned)), std::make_unsigned_t<T>,
unsigned>;
119 std::conditional_t<std::is_signed_v<T>, std::make_signed_t<unsigned_type>, unsigned_type>;
123 for (
size_t i =
len;
i < min_digits;
i++)
stream.put(
'0');
125 bool found_one =
false;
126 const auto v =
static_cast<unsigned_type
>(
val);
127 unsigned_type mask = unsigned_type{1} << (
len - 1u);
128 for (
size_t i = 0;
i <
len;
i++) {
132 }
else if (found_one)
137 std::ostringstream ss;
138 ss.imbue(std::locale::classic());
139 ss << std::uppercase << std::setbase(
base);
140 if (min_digits) ss << std::setfill('0') << std::setw(static_cast<int>(min_digits));
141 ss << static_cast<cast_type>(
val);
142 const auto str = std::move(ss).str();
149 template <
typename T>
152 switch (impl::fpclassify(
val)) {
153 case impl::fp_class::neg_inf:
154 impl::print_to_stream(
stream,
"-inf"sv);
157 case impl::fp_class::pos_inf:
158 impl::print_to_stream(
stream,
"inf"sv);
161 case impl::fp_class::nan:
162 impl::print_to_stream(
stream,
"nan"sv);
165 case impl::fp_class::ok: {
166 static constexpr auto needs_decimal_point = [](
auto&&
s)
noexcept {
168 if (
c ==
'.' ||
c ==
'E' ||
c ==
'e')
return false;
172#if TOML_FLOAT_CHARCONV
174 const auto hex = !!(format & value_flags::format_as_hexadecimal);
175 char buf[charconv_buffer_length<T>];
178 auto str = std::string_view{
buf,
static_cast<size_t>(
res.ptr -
buf)};
180 char buf2[charconv_buffer_length<T>];
181 if (!
hex && relaxed_precision) {
182 res = std::to_chars(buf2, buf2 +
sizeof(buf2),
val, std::chars_format::general, 6);
183 const auto str2 = std::string_view{buf2,
static_cast<size_t>(
res.ptr - buf2)};
184 if (str2.length() <
str.length())
str = str2;
188 if (!
hex && needs_decimal_point(
str)) toml::impl::print_to_stream(
stream,
".0"sv);
192 std::ostringstream ss;
193 ss.imbue(std::locale::classic());
194 if (!relaxed_precision) ss.precision(std::numeric_limits<T>::max_digits10);
195 if (!!(format & value_flags::format_as_hexadecimal)) ss << std::hexfloat;
197 const auto str = std::move(ss).str();
199 if (!(format & value_flags::format_as_hexadecimal) && needs_decimal_point(
str))
200 impl::print_to_stream(
stream,
".0"sv);
221 stream.write(
val.data(),
static_cast<std::streamsize
>(
val.length()));
226 stream.write(
val.data(),
static_cast<std::streamsize
>(
val.length()));
237 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
243 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
249 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
255 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
261 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
267 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
273 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
279 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
285 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
291 TOML_ANON_NAMESPACE::print_integer_to_stream(
stream,
val, format, min_digits);
296 bool relaxed_precision) {
297 TOML_ANON_NAMESPACE::print_floating_point_to_stream(
stream,
val, format, relaxed_precision);
302 bool relaxed_precision) {
303 TOML_ANON_NAMESPACE::print_floating_point_to_stream(
stream,
val, format, relaxed_precision);
327 if (
val.nanosecond &&
val.nanosecond <= 999999999u) {
329 auto ns =
val.nanosecond;
331 while (ns % 10u == 0
u) {
346 auto mins =
static_cast<int>(
val.minutes);
352 const auto hours = mins / 60;
388#if TOML_ENABLE_FORMATTERS
392 stream << toml_formatter{arr};
397 stream << toml_formatter{tbl};
enum TOML_OPEN_FLAGS_ENUM value_flags
Metadata associated with TOML values.
#define TOML_CALLCONV
Calling convention to apply to exported free/static functions. \detail Not defined by default (let th...
#define TOML_INTERNAL_LINKAGE
#define TOML_EXTERNAL_LINKAGE
#define TOML_IMPL_NAMESPACE_END
TOML_EXPORTED_FREE_FUNCTION void TOML_CALLCONV print_to_stream(std::ostream &, std::string_view)
constexpr size_t charconv_buffer_length< int16_t >
constexpr size_t charconv_buffer_length< uint8_t >
constexpr size_t charconv_buffer_length< int64_t >
TOML_ANON_NAMESPACE_START
TOML_INTERNAL_LINKAGE void print_floating_point_to_stream(std::ostream &stream, T val, value_flags format, bool relaxed_precision)
constexpr size_t charconv_buffer_length< uint16_t >
constexpr size_t charconv_buffer_length< int8_t >
constexpr size_t charconv_buffer_length< uint32_t >
constexpr size_t charconv_buffer_length< int32_t >
constexpr size_t charconv_buffer_length< uint64_t >
constexpr size_t charconv_buffer_length< double >
constexpr size_t charconv_buffer_length< float >
TOML_INTERNAL_LINKAGE void print_integer_to_stream(std::ostream &stream, T val, value_flags format={}, size_t min_digits=0)
TOML_IMPL_NAMESPACE_START
A source document line-and-column pair.
A source document region.