mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-27 04:20:06 +00:00
Avoid extra copy
This commit is contained in:
parent
98f1c1fe87
commit
e8efdef8de
@ -667,14 +667,16 @@ FMT_FUNC void format_float(char *buffer, size_t &size, int exp,
|
||||
|
||||
template <typename Double>
|
||||
FMT_FUNC typename std::enable_if<sizeof(Double) == sizeof(uint64_t), bool>::type
|
||||
grisu2_format(Double value, char *buffer, size_t &size,
|
||||
grisu2_specs specs) {
|
||||
grisu2_format(Double value, buffer &buf, grisu2_specs specs) {
|
||||
FMT_ASSERT(value >= 0, "value is negative");
|
||||
char *buffer = buf.data();
|
||||
if (value == 0) {
|
||||
gen_digits_params params(specs, 1);
|
||||
*buffer = '0';
|
||||
size = 1;
|
||||
size_t size = 1;
|
||||
format_float(buffer, size, 0, params);
|
||||
FMT_ASSERT(buf.capacity() >= size, "");
|
||||
buf.resize(size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -705,12 +707,14 @@ FMT_FUNC typename std::enable_if<sizeof(Double) == sizeof(uint64_t), bool>::type
|
||||
// lo (p2 in Grisu) contains the least significants digits of scaled_upper.
|
||||
// lo = supper % one.
|
||||
uint64_t lo = upper.f & (one.f - 1);
|
||||
size = 0;
|
||||
size_t size = 0;
|
||||
if (!grisu2_gen_digits(buffer, size, hi, lo, exp, delta, one, diff,
|
||||
params.max_digits)) {
|
||||
return false;
|
||||
}
|
||||
format_float(buffer, size, cached_exp + exp, params);
|
||||
FMT_ASSERT(buf.capacity() >= size, "");
|
||||
buf.resize(size);
|
||||
return true;
|
||||
}
|
||||
} // namespace internal
|
||||
|
@ -299,10 +299,10 @@ struct grisu2_specs {
|
||||
// https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
|
||||
template <typename Double>
|
||||
FMT_API typename std::enable_if<sizeof(Double) == sizeof(uint64_t), bool>::type
|
||||
grisu2_format(Double value, char *buffer, size_t &size, grisu2_specs);
|
||||
grisu2_format(Double value, buffer &buf, grisu2_specs);
|
||||
template <typename Double>
|
||||
inline typename std::enable_if<sizeof(Double) != sizeof(uint64_t), bool>::type
|
||||
grisu2_format(Double, char *, size_t &, grisu2_specs) { return false; }
|
||||
grisu2_format(Double, buffer &, grisu2_specs) { return false; }
|
||||
|
||||
template <typename Allocator>
|
||||
typename Allocator::value_type *allocate(Allocator& alloc, std::size_t n) {
|
||||
@ -2862,22 +2862,16 @@ void basic_writer<Range>::write_double(T value, const format_specs &spec) {
|
||||
bool use_grisu = internal::use_grisu() && sizeof(T) <= sizeof(double) &&
|
||||
type != 'a' && type != 'A';
|
||||
if (use_grisu) {
|
||||
char buf[100]; // TODO: correct buffer size
|
||||
size_t size = 0;
|
||||
auto gs = internal::grisu2_specs();
|
||||
gs.type = type;
|
||||
gs.precision = spec.precision();
|
||||
gs.flags = spec.flags_;
|
||||
use_grisu = internal::grisu2_format(
|
||||
static_cast<double>(value), buf, size, gs);
|
||||
if (use_grisu) {
|
||||
FMT_ASSERT(size <= 100, "buffer overflow");
|
||||
buffer.append(buf, buf + size); // TODO: avoid extra copy
|
||||
}
|
||||
use_grisu = internal::grisu2_format(static_cast<double>(value), buffer, gs);
|
||||
}
|
||||
if (!use_grisu) {
|
||||
format_specs normalized_spec(spec);
|
||||
normalized_spec.type_ = handler.type;
|
||||
buffer.clear();
|
||||
write_double_sprintf(value, normalized_spec, buffer);
|
||||
}
|
||||
size_t n = buffer.size();
|
||||
|
@ -104,7 +104,8 @@ TEST(FPTest, GetCachedPower) {
|
||||
|
||||
TEST(FPTest, Grisu2FormatCompilesWithNonIEEEDouble) {
|
||||
size_t size = 0;
|
||||
grisu2_format(4.2f, FMT_NULL, size, fmt::internal::grisu2_specs());
|
||||
fmt::memory_buffer buf;
|
||||
grisu2_format(4.2f, buf, fmt::internal::grisu2_specs());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
Loading…
Reference in New Issue
Block a user