14 char *CopyStringTo(string_view
v,
char *
out) {
15 std::memcpy(out, v.data(), v.size());
16 return out + v.size();
19 template <
typename Float>
20 bool FallbackToSnprintf(
const Float v,
const ConversionSpec &conv,
21 FormatSinkImpl *sink) {
22 int w = conv.width() >= 0 ? conv.width() : 0;
23 int p = conv.precision() >= 0 ? conv.precision() : -1;
28 fp = CopyStringTo(conv.flags().ToString(), fp);
29 fp = CopyStringTo(
"*.*", fp);
30 if (std::is_same<long double, Float>()) {
33 *fp++ = conv.conv().Char();
35 assert(fp < fmt +
sizeof(fmt));
40 int n = snprintf(&space[0], space.size(), fmt, w, p,
v);
41 if (n < 0)
return false;
42 if (static_cast<size_t>(n) < space.size()) {
43 result = string_view(space.data(),
n);
54 constexpr
int kMaxFixedPrecision = 39;
56 constexpr
int kBufferLength = 1 +
63 void push_front(
char c) {
67 void push_back(
char c) {
81 char last_digit()
const {
return end[-1] ==
'.' ?
end[-2] :
end[-1]; }
83 int size()
const {
return static_cast<int>(
end -
begin); }
94 template <
typename Float>
95 bool ConvertNonNumericFloats(
char sign_char, Float v,
97 char text[4], *
ptr = text;
98 if (sign_char) *ptr++ = sign_char;
100 ptr = std::copy_n(conv.
conv().
upper() ?
"NAN" :
"nan", 3,
ptr);
101 }
else if (std::isinf(v)) {
102 ptr = std::copy_n(conv.
conv().
upper() ?
"INF" :
"inf", 3,
ptr);
114 template <FormatStyle mode>
115 void RoundUp(Buffer *buffer,
int *exp) {
116 char *p = &buffer->back();
117 while (p >= buffer->begin && (*p ==
'9' || *p ==
'.')) {
118 if (*p ==
'9') *p =
'0';
122 if (p < buffer->
begin) {
125 if (mode == FormatStyle::Precision) {
135 void PrintExponent(
int exp,
char e, Buffer *out) {
145 out->push_back(exp / 100 +
'0');
146 out->push_back(exp / 10 % 10 +
'0');
147 out->push_back(exp % 10 +
'0');
149 out->push_back(exp / 10 +
'0');
150 out->push_back(exp % 10 +
'0');
154 template <
typename Float,
typename Int>
155 constexpr
bool CanFitMantissa() {
157 #if defined(__clang__) && !defined(__SSE3__) 163 std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits;
166 template <
typename Float>
173 template <
typename Float>
174 Decomposed<Float> Decompose(Float v) {
176 Float m = std::frexp(v, &exp);
177 m = std::ldexp(m, std::numeric_limits<Float>::digits);
178 exp -= std::numeric_limits<Float>::digits;
185 template <FormatStyle mode,
typename Int>
186 int PrintIntegralDigits(Int digits, Buffer *out) {
189 for (; digits; digits /= 10) out->push_front(digits % 10 +
'0');
190 printed = out->size();
191 if (mode == FormatStyle::Precision) {
192 out->push_front(*out->begin);
197 }
else if (mode == FormatStyle::Fixed) {
198 out->push_front(
'0');
206 bool RemoveExtraPrecision(
int extra_digits,
bool has_leftover_value,
207 Buffer *out,
int *exp_out) {
208 if (extra_digits <= 0)
return false;
211 out->end -= extra_digits;
213 bool needs_to_round_up = [&] {
216 if (*out->end >
'5')
return true;
217 if (*out->end <
'5')
return false;
218 if (has_leftover_value || std::any_of(out->end + 1, out->end + extra_digits,
219 [](
char c) { return c !=
'0'; }))
223 return out->last_digit() % 2 == 1;
226 if (needs_to_round_up) {
227 RoundUp<FormatStyle::Precision>(
out, exp_out);
235 template <
typename Int,
typename Float, FormatStyle mode>
236 bool FloatToBufferImpl(Int int_mantissa,
int exp,
int precision, Buffer *out,
238 assert((CanFitMantissa<Float, Int>()));
240 const int int_bits = std::numeric_limits<Int>::digits;
245 out->begin = out->end =
246 out->data + 1 + kMaxFixedPrecision + (mode == FormatStyle::Precision);
249 if (std::numeric_limits<Float>::digits + exp > int_bits) {
253 int digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp,
out);
254 int digits_to_zero_pad = precision;
255 if (mode == FormatStyle::Precision) {
256 *exp_out = digits_printed - 1;
257 digits_to_zero_pad -= digits_printed - 1;
258 if (RemoveExtraPrecision(-digits_to_zero_pad,
false, out, exp_out)) {
262 for (; digits_to_zero_pad-- > 0;) out->push_back(
'0');
269 if (exp > int_bits - 4)
return false;
271 const Int mask = (Int{1} << exp) - 1;
274 int digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp,
out);
275 int_mantissa &= mask;
277 int fractional_count = precision;
278 if (mode == FormatStyle::Precision) {
279 if (digits_printed == 0) {
283 while (int_mantissa <= mask) {
288 out->push_front(static_cast<char>(int_mantissa >> exp) +
'0');
290 int_mantissa &= mask;
293 *exp_out = digits_printed - 1;
294 fractional_count -= *exp_out;
295 if (RemoveExtraPrecision(-fractional_count, int_mantissa != 0, out,
304 auto get_next_digit = [&] {
306 int digit =
static_cast<int>(int_mantissa >> exp);
307 int_mantissa &= mask;
312 for (; fractional_count > 0; --fractional_count) {
313 out->push_back(get_next_digit() +
'0');
316 int next_digit = get_next_digit();
317 if (next_digit > 5 ||
318 (next_digit == 5 && (int_mantissa || out->last_digit() % 2 == 1))) {
319 RoundUp<mode>(
out, exp_out);
325 template <FormatStyle mode,
typename Float>
326 bool FloatToBuffer(Decomposed<Float> decomposed,
int precision, Buffer *out,
328 if (precision > kMaxFixedPrecision)
return false;
331 if (CanFitMantissa<Float, std::uint64_t>() &&
332 FloatToBufferImpl<std::uint64_t, Float, mode>(
333 static_cast<std::uint64_t>(decomposed.mantissa),
334 static_cast<std::uint64_t>(decomposed.exponent), precision, out, exp))
337 #if defined(__SIZEOF_INT128__) 339 return CanFitMantissa<Float, __uint128_t>() &&
340 FloatToBufferImpl<__uint128_t, Float, mode>(
341 static_cast<__uint128_t>(decomposed.mantissa),
342 static_cast<__uint128_t
>(decomposed.exponent), precision, out,
348 void WriteBufferToSink(
char sign_char, string_view str,
349 const ConversionSpec &conv, FormatSinkImpl *sink) {
350 int left_spaces = 0, zeros = 0, right_spaces = 0;
352 conv.width() >= 0 ? std::max(conv.width() -
static_cast<int>(str.size()) -
353 static_cast<int>(sign_char != 0),
356 if (conv.flags().left) {
357 right_spaces = missing_chars;
358 }
else if (conv.flags().zero) {
359 zeros = missing_chars;
361 left_spaces = missing_chars;
364 sink->Append(left_spaces,
' ');
365 if (sign_char) sink->Append(1, sign_char);
366 sink->Append(zeros,
'0');
368 sink->Append(right_spaces,
' ');
371 template <
typename Float>
372 bool FloatToSink(
const Float v,
const ConversionSpec &conv,
373 FormatSinkImpl *sink) {
377 if (std::signbit(abs_v)) {
380 }
else if (conv.flags().show_pos) {
382 }
else if (conv.flags().sign_col) {
387 if (ConvertNonNumericFloats(sign_char, abs_v, conv, sink)) {
391 int precision = conv.precision() < 0 ? 6 : conv.precision();
395 auto decomposed = Decompose(abs_v);
399 switch (conv.conv().id()) {
402 if (!FloatToBuffer<FormatStyle::Fixed>(decomposed, precision, &buffer,
404 return FallbackToSnprintf(v, conv, sink);
406 if (!conv.flags().alt && buffer.back() ==
'.') buffer.pop_back();
411 if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
413 return FallbackToSnprintf(v, conv, sink);
415 if (!conv.flags().alt && buffer.back() ==
'.') buffer.pop_back();
416 PrintExponent(exp, conv.conv().upper() ?
'E' :
'e', &buffer);
421 precision = std::max(0, precision - 1);
422 if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
424 return FallbackToSnprintf(v, conv, sink);
426 if (precision + 1 > exp && exp >= -4) {
430 buffer.begin[1] = *buffer.begin;
432 for (; exp < -1; ++exp) *buffer.begin-- =
'0';
433 *buffer.begin-- =
'.';
435 }
else if (exp > 0) {
439 buffer.begin + exp + 2);
443 if (!conv.flags().alt) {
444 while (buffer.back() ==
'0') buffer.pop_back();
445 if (buffer.back() ==
'.') buffer.pop_back();
447 if (exp) PrintExponent(exp, conv.conv().upper() ?
'E' :
'e', &buffer);
452 return FallbackToSnprintf(v, conv, sink);
458 WriteBufferToSink(sign_char,
459 string_view(buffer.begin, buffer.end - buffer.begin), conv,
469 return FloatToSink(v, conv, sink);
474 return FloatToSink(v, conv, sink);
479 return FloatToSink(v, conv, sink);
static uintptr_t RoundUp(uintptr_t addr, uintptr_t align)
void swap(absl::InlinedVector< T, N, A > &a, absl::InlinedVector< T, N, A > &b) noexcept(noexcept(a.swap(b)))
ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)