mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-25 19:50:05 +00:00
Remove <memory> dependency
This commit is contained in:
parent
3c9608416a
commit
297b22f585
@ -43,7 +43,6 @@
|
|||||||
#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
|
||||||
#include <memory> // std::allocator_traits
|
|
||||||
#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,6 +508,14 @@ 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);
|
||||||
@ -907,8 +914,9 @@ 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);
|
||||||
const size_t max_size =
|
constexpr size_t max_size =
|
||||||
std::allocator_traits<Allocator>::max_size(self.alloc_);
|
detail::max_value<typename detail::allocator_size<Allocator>::type>() /
|
||||||
|
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)
|
||||||
@ -916,8 +924,7 @@ class basic_memory_buffer : public detail::buffer<T> {
|
|||||||
else if (new_capacity > max_size)
|
else if (new_capacity > max_size)
|
||||||
new_capacity = size > max_size ? size : max_size;
|
new_capacity = size > max_size ? size : max_size;
|
||||||
T* old_data = buf.data();
|
T* old_data = buf.data();
|
||||||
T* new_data =
|
T* new_data = self.alloc_.allocate(new_capacity);
|
||||||
std::allocator_traits<Allocator>::allocate(self.alloc_, new_capacity);
|
|
||||||
// Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
|
// Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
|
||||||
detail::assume(buf.size() <= new_capacity);
|
detail::assume(buf.size() <= new_capacity);
|
||||||
// The following code doesn't throw, so the raw pointer above doesn't leak.
|
// The following code doesn't throw, so the raw pointer above doesn't leak.
|
||||||
|
@ -360,9 +360,7 @@ struct formatter<Tuple, Char,
|
|||||||
|
|
||||||
template <typename T, typename Char> struct is_range {
|
template <typename T, typename Char> struct is_range {
|
||||||
static constexpr const bool value =
|
static constexpr const bool value =
|
||||||
detail::is_range_<T>::value && !detail::has_to_string_view<T>::value &&
|
detail::is_range_<T>::value && !detail::has_to_string_view<T>::value;
|
||||||
!std::is_convertible<T, std::basic_string<Char>>::value &&
|
|
||||||
!std::is_convertible<T, detail::std_string_view<Char>>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -413,37 +413,30 @@ TEST(memory_buffer_test, exception_in_deallocate) {
|
|||||||
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
|
EXPECT_CALL(alloc, deallocate(&mem2[0], 2 * size));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Allocator, size_t MaxSize>
|
class smol_allocator : public std::allocator<char> {
|
||||||
class max_size_allocator : public Allocator {
|
|
||||||
public:
|
public:
|
||||||
using typename Allocator::value_type;
|
using size_type = unsigned char;
|
||||||
size_t max_size() const noexcept { return MaxSize; }
|
|
||||||
value_type* allocate(size_t n) {
|
auto allocate(size_t n) -> value_type* {
|
||||||
if (n > max_size()) {
|
if (n > fmt::detail::max_value<size_type>())
|
||||||
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_traits<Allocator>::deallocate(*static_cast<Allocator*>(this),
|
std::allocator<char>::deallocate(p, n);
|
||||||
p, n);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(memory_buffer_test, max_size_allocator) {
|
TEST(memory_buffer_test, max_size_allocator) {
|
||||||
// 160 = 128 + 32
|
basic_memory_buffer<char, 10, smol_allocator> buffer;
|
||||||
using test_allocator = max_size_allocator<std::allocator<char>, 160>;
|
buffer.resize(200);
|
||||||
basic_memory_buffer<char, 10, test_allocator> buffer;
|
// new_capacity = 200 + 200/2 = 300 > 256
|
||||||
buffer.resize(128);
|
buffer.resize(255); // Shouldn't throw.
|
||||||
// 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) {
|
||||||
using test_allocator = max_size_allocator<std::allocator<char>, 160>;
|
basic_memory_buffer<char, 10, smol_allocator> buffer;
|
||||||
basic_memory_buffer<char, 10, test_allocator> buffer;
|
EXPECT_THROW(buffer.resize(256), std::exception);
|
||||||
EXPECT_THROW(buffer.resize(161), std::exception);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(format_test, exception_from_lib) {
|
TEST(format_test, exception_from_lib) {
|
||||||
|
@ -17,9 +17,12 @@
|
|||||||
|
|
||||||
template <typename T> class mock_allocator {
|
template <typename T> class mock_allocator {
|
||||||
public:
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using size_type = size_t;
|
||||||
|
|
||||||
mock_allocator() {}
|
mock_allocator() {}
|
||||||
mock_allocator(const mock_allocator&) {}
|
mock_allocator(const mock_allocator&) {}
|
||||||
using value_type = T;
|
|
||||||
MOCK_METHOD(T*, allocate, (size_t));
|
MOCK_METHOD(T*, allocate, (size_t));
|
||||||
MOCK_METHOD(void, deallocate, (T*, size_t));
|
MOCK_METHOD(void, deallocate, (T*, size_t));
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user