Use std::allocator_traits (#3804)

Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
This commit is contained in:
Vladislav Shchapov 2024-01-13 21:48:37 +05:00 committed by GitHub
parent df6a3564b0
commit 21b0458291
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 28 deletions

View File

@ -43,6 +43,10 @@
#include <cstring> // std::memcpy #include <cstring> // std::memcpy
#include <initializer_list> // std::initializer_list #include <initializer_list> // std::initializer_list
#include <limits> // std::numeric_limits #include <limits> // std::numeric_limits
#if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)
// Workaround for pre gcc 5 libstdc++.
# include <memory> // std::allocator_traits
#endif
#include <stdexcept> // std::runtime_error #include <stdexcept> // std::runtime_error
#include <string> // std::string #include <string> // std::string
#include <system_error> // std::system_error #include <system_error> // std::system_error
@ -509,14 +513,6 @@ FMT_INLINE void assume(bool condition) {
#endif #endif
} }
template <typename Allocator, typename Enable = void> struct allocator_size {
using type = size_t;
};
template <typename Allocator>
struct allocator_size<Allocator, void_t<typename Allocator::size_type>> {
using type = typename Allocator::size_type;
};
template <typename Char, typename InputIt> template <typename Char, typename InputIt>
auto copy_str(InputIt begin, InputIt end, appender out) -> appender { auto copy_str(InputIt begin, InputIt end, appender out) -> appender {
get_container(out).append(begin, end); get_container(out).append(begin, end);
@ -915,9 +911,8 @@ class basic_memory_buffer : public detail::buffer<T> {
static FMT_CONSTEXPR20 void grow(detail::buffer<T>& buf, size_t size) { static FMT_CONSTEXPR20 void grow(detail::buffer<T>& buf, size_t size) {
detail::abort_fuzzing_if(size > 5000); detail::abort_fuzzing_if(size > 5000);
auto& self = static_cast<basic_memory_buffer&>(buf); auto& self = static_cast<basic_memory_buffer&>(buf);
constexpr size_t max_size = const size_t max_size =
detail::max_value<typename detail::allocator_size<Allocator>::type>() / std::allocator_traits<Allocator>::max_size(self.alloc_);
sizeof(T);
size_t old_capacity = buf.capacity(); size_t old_capacity = buf.capacity();
size_t new_capacity = old_capacity + old_capacity / 2; size_t new_capacity = old_capacity + old_capacity / 2;
if (size > new_capacity) if (size > new_capacity)

View File

@ -413,30 +413,37 @@ TEST(memory_buffer_test, exception_in_deallocate) {
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size)); EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
} }
class smol_allocator : public std::allocator<char> { template <typename Allocator, size_t MaxSize>
class max_size_allocator : public Allocator {
public: public:
using size_type = unsigned char; using typename Allocator::value_type;
size_t max_size() const noexcept { return MaxSize; }
auto allocate(size_t n) -> value_type* { value_type* allocate(size_t n) {
if (n > fmt::detail::max_value<size_type>()) if (n > max_size()) {
throw std::length_error("size > max_size"); throw std::length_error("size > max_size");
return std::allocator<char>::allocate(n); }
return std::allocator_traits<Allocator>::allocate(
*static_cast<Allocator*>(this), n);
} }
void deallocate(value_type* p, size_t n) { void deallocate(value_type* p, size_t n) {
std::allocator<char>::deallocate(p, n); std::allocator_traits<Allocator>::deallocate(*static_cast<Allocator*>(this),
p, n);
} }
}; };
TEST(memory_buffer_test, max_size_allocator) { TEST(memory_buffer_test, max_size_allocator) {
basic_memory_buffer<char, 10, smol_allocator> buffer; // 160 = 128 + 32
buffer.resize(200); using test_allocator = max_size_allocator<std::allocator<char>, 160>;
// new_capacity = 200 + 200/2 = 300 > 256 basic_memory_buffer<char, 10, test_allocator> buffer;
buffer.resize(255); // Shouldn't throw. buffer.resize(128);
// new_capacity = 128 + 128/2 = 192 > 160
buffer.resize(160); // Shouldn't throw.
} }
TEST(memory_buffer_test, max_size_allocator_overflow) { TEST(memory_buffer_test, max_size_allocator_overflow) {
basic_memory_buffer<char, 10, smol_allocator> buffer; using test_allocator = max_size_allocator<std::allocator<char>, 160>;
EXPECT_THROW(buffer.resize(256), std::exception); basic_memory_buffer<char, 10, test_allocator> buffer;
EXPECT_THROW(buffer.resize(161), std::exception);
} }
TEST(format_test, exception_from_lib) { TEST(format_test, exception_from_lib) {
@ -2152,7 +2159,7 @@ TEST(format_int_test, format_int) {
EXPECT_EQ(fmt::format_int(42ul).str(), "42"); EXPECT_EQ(fmt::format_int(42ul).str(), "42");
EXPECT_EQ(fmt::format_int(-42l).str(), "-42"); EXPECT_EQ(fmt::format_int(-42l).str(), "-42");
EXPECT_EQ(fmt::format_int(42ull).str(), "42"); EXPECT_EQ(fmt::format_int(42ull).str(), "42");
EXPECT_EQ(fmt::format_int(-42ll).str(), "-42");\ EXPECT_EQ(fmt::format_int(-42ll).str(), "-42");
EXPECT_EQ(fmt::format_int(max_value<int64_t>()).str(), EXPECT_EQ(fmt::format_int(max_value<int64_t>()).str(),
std::to_string(max_value<int64_t>())); std::to_string(max_value<int64_t>()));
} }