Allocator::max_size support in basic_memory_buffer (#1960)
This commit is contained in:
parent
bb68f6089b
commit
97c8873214
@ -742,9 +742,11 @@ void basic_memory_buffer<T, SIZE, Allocator>::grow(size_t size) {
|
|||||||
#ifdef FMT_FUZZ
|
#ifdef FMT_FUZZ
|
||||||
if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
|
if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
|
||||||
#endif
|
#endif
|
||||||
|
const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
|
||||||
size_t old_capacity = this->capacity();
|
size_t old_capacity = this->capacity();
|
||||||
size_t new_capacity = old_capacity + old_capacity / 2;
|
size_t new_capacity = old_capacity + old_capacity / 2;
|
||||||
if (size > new_capacity) new_capacity = size;
|
if (size > new_capacity) new_capacity = size;
|
||||||
|
else if (new_capacity > max_size) new_capacity = (std::max)(size, max_size);
|
||||||
T* old_data = this->data();
|
T* old_data = this->data();
|
||||||
T* new_data =
|
T* new_data =
|
||||||
std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
|
std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
|
||||||
|
@ -354,6 +354,53 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) {
|
|||||||
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
|
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Allocator, size_t MaxSize>
|
||||||
|
class allocator_max_size: public Allocator {
|
||||||
|
public:
|
||||||
|
using typename Allocator::value_type;
|
||||||
|
size_t max_size() const FMT_NOEXCEPT {
|
||||||
|
return MaxSize;
|
||||||
|
}
|
||||||
|
value_type* allocate(size_t n) {
|
||||||
|
if (n > max_size()) {
|
||||||
|
throw std::length_error("size > max_size");
|
||||||
|
}
|
||||||
|
return std::allocator_traits<Allocator>::allocate(
|
||||||
|
*static_cast<Allocator *>(this), n);
|
||||||
|
}
|
||||||
|
void deallocate(value_type* p, size_t n) {
|
||||||
|
std::allocator_traits<Allocator>::deallocate(
|
||||||
|
*static_cast<Allocator *>(this), p, n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(MemoryBufferTest, AllocatorMaxSize) {
|
||||||
|
// 160 = 128 + 32
|
||||||
|
using TestAllocator = allocator_max_size<std::allocator<char>, 160>;
|
||||||
|
basic_memory_buffer<char, 10, TestAllocator> buffer;
|
||||||
|
buffer.resize(128);
|
||||||
|
bool throws_on_resize = false;
|
||||||
|
try {
|
||||||
|
// new_capacity = 128 + 128/2 = 192 > 160
|
||||||
|
buffer.resize(160);
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
throws_on_resize = true;
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(throws_on_resize);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(MemoryBufferTest, AllocatorMaxSizeOverflow) {
|
||||||
|
using TestAllocator = allocator_max_size<std::allocator<char>, 160>;
|
||||||
|
basic_memory_buffer<char, 10, TestAllocator> buffer;
|
||||||
|
bool throws_on_resize = false;
|
||||||
|
try {
|
||||||
|
buffer.resize(161);
|
||||||
|
} catch (const std::exception &) {
|
||||||
|
throws_on_resize = true;
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(throws_on_resize);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(UtilTest, UTF8ToUTF16) {
|
TEST(UtilTest, UTF8ToUTF16) {
|
||||||
fmt::detail::utf8_to_utf16 u("лошадка");
|
fmt::detail::utf8_to_utf16 u("лошадка");
|
||||||
EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
|
EXPECT_EQ(L"\x043B\x043E\x0448\x0430\x0434\x043A\x0430", u.str());
|
||||||
|
Loading…
Reference in New Issue
Block a user