From 21b0458291b05f02a12a216123386969b552576e Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 13 Jan 2024 21:48:37 +0500 Subject: [PATCH] Use std::allocator_traits (#3804) Signed-off-by: Vladislav Shchapov --- include/fmt/format.h | 23 +++++++++-------------- test/format-test.cc | 35 +++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 6ffba5dd..46c89e34 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -43,9 +43,13 @@ #include // std::memcpy #include // std::initializer_list #include // std::numeric_limits -#include // std::runtime_error -#include // std::string -#include // std::system_error +#if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI) +// Workaround for pre gcc 5 libstdc++. +# include // std::allocator_traits +#endif +#include // std::runtime_error +#include // std::string +#include // std::system_error #include "base.h" @@ -509,14 +513,6 @@ FMT_INLINE void assume(bool condition) { #endif } -template struct allocator_size { - using type = size_t; -}; -template -struct allocator_size> { - using type = typename Allocator::size_type; -}; - template auto copy_str(InputIt begin, InputIt end, appender out) -> appender { get_container(out).append(begin, end); @@ -915,9 +911,8 @@ class basic_memory_buffer : public detail::buffer { static FMT_CONSTEXPR20 void grow(detail::buffer& buf, size_t size) { detail::abort_fuzzing_if(size > 5000); auto& self = static_cast(buf); - constexpr size_t max_size = - detail::max_value::type>() / - sizeof(T); + const size_t max_size = + std::allocator_traits::max_size(self.alloc_); size_t old_capacity = buf.capacity(); size_t new_capacity = old_capacity + old_capacity / 2; if (size > new_capacity) diff --git a/test/format-test.cc b/test/format-test.cc index a76c44cf..b38a3bd4 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -413,30 +413,37 @@ TEST(memory_buffer_test, exception_in_deallocate) { EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size)); } -class smol_allocator : public std::allocator { +template +class max_size_allocator : public Allocator { public: - using size_type = unsigned char; - - auto allocate(size_t n) -> value_type* { - if (n > fmt::detail::max_value()) + using typename Allocator::value_type; + size_t max_size() const noexcept { return MaxSize; } + value_type* allocate(size_t n) { + if (n > max_size()) { throw std::length_error("size > max_size"); - return std::allocator::allocate(n); + } + return std::allocator_traits::allocate( + *static_cast(this), n); } void deallocate(value_type* p, size_t n) { - std::allocator::deallocate(p, n); + std::allocator_traits::deallocate(*static_cast(this), + p, n); } }; TEST(memory_buffer_test, max_size_allocator) { - basic_memory_buffer buffer; - buffer.resize(200); - // new_capacity = 200 + 200/2 = 300 > 256 - buffer.resize(255); // Shouldn't throw. + // 160 = 128 + 32 + using test_allocator = max_size_allocator, 160>; + basic_memory_buffer buffer; + buffer.resize(128); + // new_capacity = 128 + 128/2 = 192 > 160 + buffer.resize(160); // Shouldn't throw. } TEST(memory_buffer_test, max_size_allocator_overflow) { - basic_memory_buffer buffer; - EXPECT_THROW(buffer.resize(256), std::exception); + using test_allocator = max_size_allocator, 160>; + basic_memory_buffer buffer; + EXPECT_THROW(buffer.resize(161), std::exception); } 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(-42l).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()).str(), std::to_string(max_value())); }