1*a821937bSPeng Liu //===----------------------------------------------------------------------===// 2*a821937bSPeng Liu // 3*a821937bSPeng Liu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*a821937bSPeng Liu // See https://llvm.org/LICENSE.txt for license information. 5*a821937bSPeng Liu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*a821937bSPeng Liu // 7*a821937bSPeng Liu //===----------------------------------------------------------------------===// 8*a821937bSPeng Liu 9*a821937bSPeng Liu #ifndef TEST_SUPPORT_INCREASING_ALLOCATOR_H 10*a821937bSPeng Liu #define TEST_SUPPORT_INCREASING_ALLOCATOR_H 11*a821937bSPeng Liu 12*a821937bSPeng Liu #include <cstddef> 13*a821937bSPeng Liu #include <memory> 14*a821937bSPeng Liu 15*a821937bSPeng Liu #include "test_macros.h" 16*a821937bSPeng Liu 17*a821937bSPeng Liu // The increasing_allocator is a custom allocator that enforces an increasing minimum allocation size, 18*a821937bSPeng Liu // ensuring that it allocates an increasing amount of memory, possibly exceeding the requested amount. 19*a821937bSPeng Liu // This unique behavior is particularly useful for testing the shrink_to_fit functionality in std::vector, 20*a821937bSPeng Liu // vector<bool>, and std::basic_string, ensuring that shrink_to_fit does not increase the capacity of 21*a821937bSPeng Liu // the allocated memory. 22*a821937bSPeng Liu 23*a821937bSPeng Liu template <typename T> 24*a821937bSPeng Liu struct increasing_allocator { 25*a821937bSPeng Liu using value_type = T; 26*a821937bSPeng Liu std::size_t min_elements = 1000; 27*a821937bSPeng Liu increasing_allocator() = default; 28*a821937bSPeng Liu 29*a821937bSPeng Liu template <typename U> 30*a821937bSPeng Liu TEST_CONSTEXPR_CXX20 increasing_allocator(const increasing_allocator<U>& other) TEST_NOEXCEPT 31*a821937bSPeng Liu : min_elements(other.min_elements) {} 32*a821937bSPeng Liu 33*a821937bSPeng Liu #if TEST_STD_VER >= 23 34*a821937bSPeng Liu TEST_CONSTEXPR_CXX23 std::allocation_result<T*> allocate_at_least(std::size_t n) { 35*a821937bSPeng Liu if (n < min_elements) 36*a821937bSPeng Liu n = min_elements; 37*a821937bSPeng Liu min_elements += 1000; 38*a821937bSPeng Liu return std::allocator<T>{}.allocate_at_least(n); 39*a821937bSPeng Liu } 40*a821937bSPeng Liu #endif // TEST_STD_VER >= 23 41*a821937bSPeng Liu 42*a821937bSPeng Liu TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); } 43*a821937bSPeng Liu 44*a821937bSPeng Liu TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n) TEST_NOEXCEPT { std::allocator<T>().deallocate(p, n); } 45*a821937bSPeng Liu }; 46*a821937bSPeng Liu 47*a821937bSPeng Liu template <typename T, typename U> 48*a821937bSPeng Liu TEST_CONSTEXPR_CXX20 bool operator==(increasing_allocator<T>, increasing_allocator<U>) TEST_NOEXCEPT { 49*a821937bSPeng Liu return true; 50*a821937bSPeng Liu } 51*a821937bSPeng Liu 52*a821937bSPeng Liu #endif // TEST_SUPPORT_INCREASING_ALLOCATOR_H 53