From fd87a23d34e1df139ac511c9bbcfdda1ba59a232 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 10 Jan 2024 19:34:31 -0800 Subject: [PATCH] Reduce memory dependency --- include/fmt/base.h | 17 ++++++++++++++++- include/fmt/format.h | 35 +++++++---------------------------- include/fmt/std.h | 8 ++++++++ test/format-test.cc | 13 ------------- test/std-test.cc | 18 ++++++++++++++++++ 5 files changed, 49 insertions(+), 42 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index da017d3e..56378b2c 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -863,7 +863,22 @@ template class buffer { } /** Appends data to the end of the buffer. */ - template void append(const U* begin, const U* end); + template void append(const U* begin, const U* end) { + while (begin != end) { + auto count = to_unsigned(end - begin); + try_reserve(size_ + count); + auto free_cap = capacity_ - size_; + if (free_cap < count) count = free_cap; + if (std::is_same::value) { + memcpy(ptr_ + size_, begin, count * sizeof(T)); + } else { + T* out = ptr_ + size_; + for (size_t i = 0; i < count; ++i) out[i] = begin[i]; + } + size_ += count; + begin += count; + } + } template FMT_CONSTEXPR auto operator[](Idx index) -> T& { return ptr_[index]; diff --git a/include/fmt/format.h b/include/fmt/format.h index 37508fb1..6c94d2d0 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -43,17 +43,17 @@ #include // std::memcpy #include // std::initializer_list #include // std::numeric_limits -#include // std::uninitialized_copy_n +#include // std::allocator_traits #include // std::runtime_error -#include // std::basic_string +#include // std::string #include // std::system_error -#ifdef __cpp_lib_bit_cast +#include "base.h" + +#if FMT_HAS_INCLUDE() # include // std::bit_cast #endif -#include "base.h" - // libc++ supports string_view in pre-c++17. #if FMT_HAS_INCLUDE() && \ (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) @@ -861,20 +861,6 @@ using is_double_double = bool_constant::digits == 106>; # define FMT_USE_FULL_CACHE_DRAGONBOX 0 #endif -template -template -void buffer::append(const U* begin, const U* end) { - while (begin != end) { - auto count = to_unsigned(end - begin); - try_reserve(size_ + count); - auto free_cap = capacity_ - size_; - if (free_cap < count) count = free_cap; - std::uninitialized_copy_n(begin, count, ptr_ + size_); - size_ += count; - begin += count; - } -} - template struct is_locale : std::false_type {}; template @@ -940,7 +926,7 @@ class basic_memory_buffer : public detail::buffer { // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). detail::assume(buf.size() <= new_capacity); // The following code doesn't throw, so the raw pointer above doesn't leak. - std::uninitialized_copy_n(old_data, buf.size(), new_data); + memcpy(new_data, old_data, buf.size() * sizeof(T)); self.set(new_data, new_capacity); // deallocate must not throw according to the standard, but even if it does, // the buffer already uses the new storage and will deallocate it in @@ -3088,7 +3074,7 @@ class bigint { bigits_.resize(to_unsigned(num_bigits + exp_difference)); for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j) bigits_[j] = bigits_[i]; - std::uninitialized_fill_n(bigits_.data(), exp_difference, 0u); + memset(bigits_.data(), 0, to_unsigned(exp_difference) * sizeof(bigit)); exp_ -= exp_difference; } @@ -4141,13 +4127,6 @@ template auto ptr(T p) -> const void* { static_assert(std::is_pointer::value, ""); return detail::bit_cast(p); } -template -auto ptr(const std::unique_ptr& p) -> const void* { - return p.get(); -} -template auto ptr(const std::shared_ptr& p) -> const void* { - return p.get(); -} /** \rst diff --git a/include/fmt/std.h b/include/fmt/std.h index d8f30a19..205e6dd1 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -509,6 +509,14 @@ struct formatter +auto ptr(const std::unique_ptr& p) -> const void* { + return p.get(); +} +template auto ptr(const std::shared_ptr& p) -> const void* { + return p.get(); +} + FMT_EXPORT template struct formatter, Char, diff --git a/test/format-test.cc b/test/format-test.cc index 223fb1b3..3e53147d 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -20,7 +20,6 @@ #include // std::strlen #include // std::back_inserter #include // std::list -#include // std::unique_ptr #include // std::is_default_constructible #include "gtest-extra.h" @@ -1540,18 +1539,6 @@ TEST(format_test, format_pointer) { fmt::format("{0}", reinterpret_cast(~uintptr_t()))); EXPECT_EQ("0x1234", fmt::format("{}", fmt::ptr(reinterpret_cast(0x1234)))); - std::unique_ptr up(new int(1)); - EXPECT_EQ(fmt::format("{}", fmt::ptr(up.get())), - fmt::format("{}", fmt::ptr(up))); - struct custom_deleter { - void operator()(int* p) const { delete p; } - }; - std::unique_ptr upcd(new int(1)); - EXPECT_EQ(fmt::format("{}", fmt::ptr(upcd.get())), - fmt::format("{}", fmt::ptr(upcd))); - std::shared_ptr sp(new int(1)); - EXPECT_EQ(fmt::format("{}", fmt::ptr(sp.get())), - fmt::format("{}", fmt::ptr(sp))); EXPECT_EQ(fmt::format("{}", fmt::detail::bit_cast( &function_pointer_test)), fmt::format("{}", fmt::ptr(function_pointer_test))); diff --git a/test/std-test.cc b/test/std-test.cc index de3feaa0..f5566848 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -304,3 +304,21 @@ TEST(std_test, format_atomic_flag) { EXPECT_EQ(fmt::format("{}", cf), "false"); } #endif // __cpp_lib_atomic_flag_test + +TEST(std_test, format_unique_ptr) { + std::unique_ptr up(new int(1)); + EXPECT_EQ(fmt::format("{}", fmt::ptr(up.get())), + fmt::format("{}", fmt::ptr(up))); + struct custom_deleter { + void operator()(int* p) const { delete p; } + }; + std::unique_ptr upcd(new int(1)); + EXPECT_EQ(fmt::format("{}", fmt::ptr(upcd.get())), + fmt::format("{}", fmt::ptr(upcd))); +} + +TEST(std_test, format_shared_ptr) { + std::shared_ptr sp(new int(1)); + EXPECT_EQ(fmt::format("{}", fmt::ptr(sp.get())), + fmt::format("{}", fmt::ptr(sp))); +}