From e8efdef8de1569e51d8d2b7d452d529d3ca56810 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 17 Oct 2018 08:19:46 -0700 Subject: [PATCH] Avoid extra copy --- include/fmt/format-inl.h | 12 ++++++++---- include/fmt/format.h | 14 ++++---------- test/format-impl-test.cc | 3 ++- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 524b229a..1257f2b0 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -667,14 +667,16 @@ FMT_FUNC void format_float(char *buffer, size_t &size, int exp, template FMT_FUNC typename std::enable_if::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::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 diff --git a/include/fmt/format.h b/include/fmt/format.h index a64afe73..ddd5a54c 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -299,10 +299,10 @@ struct grisu2_specs { // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf template FMT_API typename std::enable_if::type - grisu2_format(Double value, char *buffer, size_t &size, grisu2_specs); + grisu2_format(Double value, buffer &buf, grisu2_specs); template inline typename std::enable_if::type - grisu2_format(Double, char *, size_t &, grisu2_specs) { return false; } + grisu2_format(Double, buffer &, grisu2_specs) { return false; } template typename Allocator::value_type *allocate(Allocator& alloc, std::size_t n) { @@ -2862,22 +2862,16 @@ void basic_writer::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(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(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(); diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 49132f60..c66a587a 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -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