1 // Copyright 2019 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CORE_FXCRT_FX_MEMORY_WRAPPERS_H_ 6 #define CORE_FXCRT_FX_MEMORY_WRAPPERS_H_ 7 8 #include <limits> 9 #include <type_traits> 10 #include <utility> 11 12 #include "core/fxcrt/fx_memory.h" 13 14 // Used with std::unique_ptr to FX_Free raw memory. 15 struct FxFreeDeleter { operatorFxFreeDeleter16 inline void operator()(void* ptr) const { FX_Free(ptr); } 17 }; 18 19 // Escape hatch mechanism to allow non_arithmetic types into data partition. 20 template <typename T> 21 struct IsFXDataPartitionException : std::false_type {}; 22 23 // Use with caution. No further checks are made to see if `T` is appropriate 24 // for the Data Partition (e.g. no pointers, strings, vtables, etc.). This 25 // declaration must occur in the top-level namespace. 26 #define FX_DATA_PARTITION_EXCEPTION(T) \ 27 template <> \ 28 struct IsFXDataPartitionException<T> : std::true_type {} 29 30 // Allocators for mapping STL containers onto Partition Alloc. 31 // Otherwise, replacing e.g. the FX_AllocUninit/FX_Free pairs with STL may 32 // undo some of the nice segregation that we get from PartitionAlloc. 33 template <class T, void* Alloc(size_t, size_t), void Free(void*)> 34 struct FxPartitionAllocAllocator { 35 public: 36 #if !defined(COMPILER_MSVC) || defined(NDEBUG) 37 static_assert(std::is_arithmetic<T>::value || std::is_enum<T>::value || 38 IsFXDataPartitionException<T>::value, 39 "Only numeric types allowed in this partition"); 40 #endif 41 42 using value_type = T; 43 using pointer = T*; 44 using const_pointer = const T*; 45 using reference = T&; 46 using const_reference = const T&; 47 using size_type = size_t; 48 using difference_type = ptrdiff_t; 49 50 template <class U> 51 struct rebind { 52 using other = FxPartitionAllocAllocator<U, Alloc, Free>; 53 }; 54 55 FxPartitionAllocAllocator() noexcept = default; 56 FxPartitionAllocAllocator(const FxPartitionAllocAllocator& other) noexcept = 57 default; 58 ~FxPartitionAllocAllocator() = default; 59 60 template <typename U> FxPartitionAllocAllocatorFxPartitionAllocAllocator61 FxPartitionAllocAllocator( 62 const FxPartitionAllocAllocator<U, Alloc, Free>& other) noexcept {} 63 addressFxPartitionAllocAllocator64 pointer address(reference x) const noexcept { return &x; } addressFxPartitionAllocAllocator65 const_pointer address(const_reference x) const noexcept { return &x; } 66 pointer allocate(size_type n, const void* hint = 0) { 67 return static_cast<pointer>(Alloc(n, sizeof(value_type))); 68 } deallocateFxPartitionAllocAllocator69 void deallocate(pointer p, size_type n) { Free(p); } max_sizeFxPartitionAllocAllocator70 size_type max_size() const noexcept { 71 return std::numeric_limits<size_type>::max() / sizeof(value_type); 72 } 73 74 template <class U, class... Args> constructFxPartitionAllocAllocator75 void construct(U* p, Args&&... args) { 76 new (reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...); 77 } 78 79 template <class U> destroyFxPartitionAllocAllocator80 void destroy(U* p) { 81 p->~U(); 82 } 83 84 // There's no state, so they are all the same, 85 bool operator==(const FxPartitionAllocAllocator& that) { return true; } 86 bool operator!=(const FxPartitionAllocAllocator& that) { return false; } 87 }; 88 89 // Used to put backing store for std::vector<> and such into the 90 // general partition, ensuring they contain data only. 91 template <typename T, 92 typename = std::enable_if_t<std::is_arithmetic<T>::value || 93 std::is_enum<T>::value || 94 IsFXDataPartitionException<T>::value>> 95 using FxAllocAllocator = FxPartitionAllocAllocator<T, 96 pdfium::internal::AllocOrDie, 97 pdfium::internal::Dealloc>; 98 99 // Used to put backing store for std::string<> and std::ostringstream<> 100 // into the string partition. 101 template <typename T> 102 using FxStringAllocator = 103 FxPartitionAllocAllocator<T, 104 pdfium::internal::StringAllocOrDie, 105 pdfium::internal::StringDealloc>; 106 107 #endif // CORE_FXCRT_FX_MEMORY_WRAPPERS_H_ 108