Reduce memory dependency

This commit is contained in:
Victor Zverovich 2024-01-10 19:34:31 -08:00
parent b71ef65b6e
commit fd87a23d34
5 changed files with 49 additions and 42 deletions

View File

@ -863,7 +863,22 @@ template <typename T> class buffer {
}
/** Appends data to the end of the buffer. */
template <typename U> void append(const U* begin, const U* end);
template <typename U> 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<T, U>::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 <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
return ptr_[index];

View File

@ -43,17 +43,17 @@
#include <cstring> // std::memcpy
#include <initializer_list> // std::initializer_list
#include <limits> // std::numeric_limits
#include <memory> // std::uninitialized_copy_n
#include <memory> // std::allocator_traits
#include <stdexcept> // std::runtime_error
#include <string> // std::basic_string
#include <string> // std::string
#include <system_error> // std::system_error
#ifdef __cpp_lib_bit_cast
#include "base.h"
#if FMT_HAS_INCLUDE(<bit>)
# include <bit> // std::bit_cast
#endif
#include "base.h"
// libc++ supports string_view in pre-c++17.
#if FMT_HAS_INCLUDE(<string_view>) && \
(FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
@ -861,20 +861,6 @@ using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
# define FMT_USE_FULL_CACHE_DRAGONBOX 0
#endif
template <typename T>
template <typename U>
void buffer<T>::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 <typename T, typename Enable = void>
struct is_locale : std::false_type {};
template <typename T>
@ -940,7 +926,7 @@ class basic_memory_buffer : public detail::buffer<T> {
// 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 <typename T> auto ptr(T p) -> const void* {
static_assert(std::is_pointer<T>::value, "");
return detail::bit_cast<const void*>(p);
}
template <typename T, typename Deleter>
auto ptr(const std::unique_ptr<T, Deleter>& p) -> const void* {
return p.get();
}
template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
return p.get();
}
/**
\rst

View File

@ -509,6 +509,14 @@ struct formatter<BitRef, Char,
}
};
template <typename T, typename Deleter>
auto ptr(const std::unique_ptr<T, Deleter>& p) -> const void* {
return p.get();
}
template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
return p.get();
}
FMT_EXPORT
template <typename T, typename Char>
struct formatter<std::atomic<T>, Char,

View File

@ -20,7 +20,6 @@
#include <cstring> // std::strlen
#include <iterator> // std::back_inserter
#include <list> // std::list
#include <memory> // std::unique_ptr
#include <type_traits> // std::is_default_constructible
#include "gtest-extra.h"
@ -1540,18 +1539,6 @@ TEST(format_test, format_pointer) {
fmt::format("{0}", reinterpret_cast<void*>(~uintptr_t())));
EXPECT_EQ("0x1234",
fmt::format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234))));
std::unique_ptr<int> 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<int, custom_deleter> upcd(new int(1));
EXPECT_EQ(fmt::format("{}", fmt::ptr(upcd.get())),
fmt::format("{}", fmt::ptr(upcd)));
std::shared_ptr<int> 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<const void*>(
&function_pointer_test)),
fmt::format("{}", fmt::ptr(function_pointer_test)));

View File

@ -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<int> 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<int, custom_deleter> 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<int> sp(new int(1));
EXPECT_EQ(fmt::format("{}", fmt::ptr(sp.get())),
fmt::format("{}", fmt::ptr(sp)));
}