Skip to content

Commit

Permalink
Remove memory dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut committed Jan 11, 2024
1 parent b71ef65 commit eacfc42
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 42 deletions.
17 changes: 16 additions & 1 deletion include/fmt/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
34 changes: 6 additions & 28 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,16 @@
#include <cstring> // std::memcpy
#include <initializer_list> // std::initializer_list
#include <limits> // std::numeric_limits
#include <memory> // std::uninitialized_copy_n
#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))
Expand Down Expand Up @@ -861,20 +860,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>
Expand Down Expand Up @@ -940,7 +925,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
Expand Down Expand Up @@ -3088,7 +3073,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;
}

Expand Down Expand Up @@ -4141,13 +4126,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
Expand Down
8 changes: 8 additions & 0 deletions include/fmt/std.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 0 additions & 13 deletions test/format-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)));
Expand Down
18 changes: 18 additions & 0 deletions test/std-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
}

0 comments on commit eacfc42

Please sign in to comment.