1 // Copyright 2022 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_FIXED_SIZE_DATA_VECTOR_H_ 6 #define CORE_FXCRT_FIXED_SIZE_DATA_VECTOR_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <utility> 12 13 #include "core/fxcrt/fx_memory_wrappers.h" 14 #include "third_party/base/containers/span.h" 15 16 namespace fxcrt { 17 18 enum class DataVectorAllocOption { 19 kInitialized, 20 kUninitialized, 21 kTryInitialized, 22 }; 23 24 // A simple data container that has a fixed size. 25 // Unlike std::vector, it cannot be implicitly copied and its data is only 26 // accessible using spans. 27 // It can either initialize its data with zeros, or leave its data 28 // uninitialized. 29 template <typename T, DataVectorAllocOption OPTION> 30 class FixedSizeDataVector { 31 public: FixedSizeDataVector()32 FixedSizeDataVector() : FixedSizeDataVector(0) {} FixedSizeDataVector(size_t size)33 explicit FixedSizeDataVector(size_t size) 34 : data_(MaybeInit(size, OPTION)), size_(CalculateSize(size, OPTION)) {} 35 FixedSizeDataVector(const FixedSizeDataVector&) = delete; 36 FixedSizeDataVector& operator=(const FixedSizeDataVector&) = delete; 37 template <DataVectorAllocOption OTHER_OPTION> FixedSizeDataVector(FixedSizeDataVector<T,OTHER_OPTION> && that)38 FixedSizeDataVector(FixedSizeDataVector<T, OTHER_OPTION>&& that) noexcept { 39 data_ = std::move(that.data_); 40 size_ = that.size_; 41 that.size_ = 0; 42 } 43 template <DataVectorAllocOption OTHER_OPTION> 44 FixedSizeDataVector& operator=( 45 FixedSizeDataVector<T, OTHER_OPTION>&& that) noexcept { 46 data_ = std::move(that.data_); 47 size_ = that.size_; 48 that.size_ = 0; 49 return *this; 50 } 51 ~FixedSizeDataVector() = default; 52 53 operator pdfium::span<const T>() const { return span(); } 54 writable_span()55 pdfium::span<T> writable_span() { 56 return pdfium::make_span(data_.get(), size_); 57 } 58 span()59 pdfium::span<const T> span() const { 60 return pdfium::make_span(data_.get(), size_); 61 } 62 size()63 size_t size() const { return size_; } empty()64 bool empty() const { return size_ == 0; } 65 66 private: 67 friend class FixedSizeDataVector<T, DataVectorAllocOption::kInitialized>; 68 friend class FixedSizeDataVector<T, DataVectorAllocOption::kUninitialized>; 69 friend class FixedSizeDataVector<T, DataVectorAllocOption::kTryInitialized>; 70 MaybeInit(size_t size,DataVectorAllocOption alloc_option)71 static T* MaybeInit(size_t size, DataVectorAllocOption alloc_option) { 72 if (size == 0) 73 return nullptr; 74 switch (alloc_option) { 75 case DataVectorAllocOption::kInitialized: 76 return FX_Alloc(T, size); 77 case DataVectorAllocOption::kUninitialized: 78 return FX_AllocUninit(T, size); 79 case DataVectorAllocOption::kTryInitialized: 80 return FX_TryAlloc(T, size); 81 } 82 } 83 CalculateSize(size_t size,DataVectorAllocOption alloc_option)84 size_t CalculateSize(size_t size, DataVectorAllocOption alloc_option) const { 85 switch (alloc_option) { 86 case DataVectorAllocOption::kInitialized: 87 case DataVectorAllocOption::kUninitialized: 88 return size; 89 case DataVectorAllocOption::kTryInitialized: 90 return data_ ? size : 0; 91 } 92 } 93 94 std::unique_ptr<T, FxFreeDeleter> data_; 95 size_t size_; 96 }; 97 98 } // namespace fxcrt 99 100 #endif // CORE_FXCRT_FIXED_SIZE_DATA_VECTOR_H_ 101