31#ifndef FENNEC_FORMAT_FORMATTER_H
32#define FENNEC_FORMAT_FORMATTER_H
35#include <fennec/string/string.h>
48 string operator()(
const format_arg&,
const T&) {
49 static_assert(
false,
"Formatter not implemented for the provided type.");
59 string operator()(
const format_arg&,
const char (&str)[N]) {
65struct formatter<const char[N]> {
66 string operator()(
const format_arg&,
const char (&str)[N]) {
72struct formatter<cstring> {
73 string operator()(
const format_arg&,
const cstring& str) {
79struct formatter<string> {
80 string operator()(
const format_arg&,
const string& str) {
88template<
typename IntT>
requires(is_integral_v<IntT> and not is_bool_v<IntT>)
89struct formatter<IntT> {
90 string operator()(
const format_arg& fmt, IntT x) {
91 char digits[128] = {};
92 auto chk = fennec::to_chars(digits, digits +
sizeof(digits), fennec::abs(x), fmt.base);
93 assertf(chk !=
nullptr,
"fennec::format error, to_chars error");
94 size_t len = chk - digits;
98 for (
auto& digit : digits) {
102 digit = toupper(digit);
106 const bool has_sign = (x < 0 or fmt.sign !=
'-');
107 const bool zero = fmt.fill ==
'0';
108 const size_t prefix = fmt.alt ? (fmt.type ==
'd' ? 0 : 2 - (fmt.type ==
'o')) : 0;
109 const size_t sgnlen = len + (
zero ? has_sign + prefix : 0);
110 const size_t explen =
fennec::max(sgnlen, fmt.width) + (
zero ? 0 : has_sign + prefix);
111 const size_t fill = fmt.width > sgnlen ? fmt.width - sgnlen : 0;
114 string res = string(explen);
119 memcpy(res.data() + has_sign + prefix, digits, len);
120 memset(res.data() + has_sign + prefix + len, fmt.fill ==
'0' ?
' ' : fmt.fill, fill);
123 memcpy(res.data() + explen - len, digits, len);
124 sign = fmt.fill ==
'0' ? 0 : explen - len - 1 - prefix;
125 memset(res.data(), fmt.fill, explen - len);
128 size_t bef = fill / 2 + has_sign + prefix;
129 size_t aft = explen - bef;
130 memcpy(res.data() + bef, digits, len);
131 sign = fmt.fill ==
'0' ? 0 : bef - 1 - prefix;
132 memset(res.data(), fmt.fill, bef);
133 memset(res.data() + bef + len, fmt.fill ==
'0' ?
' ' : fmt.fill, aft);
139 memcpy(res.data() + has_sign + prefix, digits, len);
143 res[
sign] = (x < 0) ?
'-' : fmt.
sign;
147 res[
sign + has_sign] =
'0';
148 if (fmt.type !=
'o') {
149 res[
sign + has_sign + 1] = fmt.type;
157template<
typename BoolT>
requires(is_bool_v<BoolT>)
158struct formatter<BoolT> {
159 string operator()(
const format_arg& fmt, BoolT x) {
160 if (fmt.type ==
's' or fmt.type ==
'\0') {
161 return x ? string(
"true") : string(
"false");
164 return formatter<uint8_t>{}(fmt,
static_cast<uint8_t>(x));
168template<
typename FloatT>
requires(is_floating_point_v<FloatT>)
169struct formatter<FloatT> {
170 string operator()(
const format_arg& fmt, FloatT x) {
173 if (fennec::isnan(x)) {
174 return string(
"nan");
176 if (fennec::isinf(x)) {
177 return string(
"inf");
181 char digits[128] = {};
182 auto chk = fennec::to_chars(digits, digits +
sizeof(digits), fennec::abs(x), fmt.type, fmt.precision);
183 assertf(chk !=
nullptr,
"fennec::format error, to_chars error");
184 size_t len = chk - digits;
188 for (
auto& digit : digits) {
192 digit = toupper(digit);
196 const bool has_sign = (x < 0 or fmt.sign !=
'-');
197 const bool zero = fmt.fill ==
'0';
198 const size_t prefix = fmt.alt ? 2 : 0;
199 const size_t sgnlen = len + (
zero ? has_sign + prefix : 0);
200 const size_t explen =
fennec::max(sgnlen, fmt.width) + (
zero ? 0 : has_sign + prefix);
201 const size_t fill = fmt.width > sgnlen ? fmt.width - sgnlen : 0;
204 string res = string(explen);
209 memcpy(res.data() + has_sign + prefix, digits, len);
210 memset(res.data() + has_sign + prefix + len, fmt.fill ==
'0' ?
' ' : fmt.fill, fill);
213 memcpy(res.data() + explen - len, digits, len);
214 sign = fmt.fill ==
'0' ? 0 : explen - len - 1 - prefix;
215 memset(res.data(), fmt.fill, explen - len);
218 size_t bef = fill / 2 + has_sign + prefix;
219 size_t aft = explen - bef;
220 memcpy(res.data() + bef, digits, len);
221 sign = fmt.fill ==
'0' ? 0 : bef - 1 - prefix;
222 memset(res.data(), fmt.fill, bef);
223 memset(res.data() + bef + len, fmt.fill ==
'0' ?
' ' : fmt.fill, aft);
229 memcpy(res.data() + has_sign + prefix, digits, len);
233 res[
sign] = (x < 0) ?
'-' : fmt.
sign;
237 res[
sign + has_sign] =
'0';
238 res[
sign + has_sign + 1] = fmt.type + (
'x' -
'a');
constexpr genType max(genType x, genType y)
Returns if , otherwise it returns .
Definition common.h:705
constexpr genType sign(genType x)
Returns if , if , or if .
Definition common.h:306
constexpr genType zero()
Definition constants.h:549
::uint8_t uint8_t
Unsigned 8-bit integer.
Definition types.h:272