blob: 1c65f87b8c65e68eec049ae7f44d72b046ee0a63 [file] [log] [blame]
// Copyright 2022 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CORE_FXCRT_FIXED_SIZE_DATA_VECTOR_H_
#define CORE_FXCRT_FIXED_SIZE_DATA_VECTOR_H_
#include <stddef.h>
#include <memory>
#include <utility>
#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/span.h"
namespace fxcrt {
// A simple data container that has a fixed size.
// Unlike std::vector, it cannot be implicitly copied and its data is only
// accessible using spans.
// It can either initialize its data with zeros, or leave its data
// uninitialized.
template <typename T>
class FixedSizeDataVector {
public:
FixedSizeDataVector() = default;
// Allocates a vector of the given size with uninitialized memory.
// A CHECK() failure occurs when insufficient memory.
static FixedSizeDataVector Uninit(size_t size) {
if (size == 0) {
return FixedSizeDataVector();
}
return FixedSizeDataVector(FX_AllocUninit(T, size), size);
}
// Allocates a vector of the given size with zeroed memory.
// A CHECK() failure occurs when insufficient memory.
static FixedSizeDataVector Zeroed(size_t size) {
if (size == 0) {
return FixedSizeDataVector();
}
return FixedSizeDataVector(FX_Alloc(T, size), size);
}
// Same as above, but return an empty vector when insufficient memory.
static FixedSizeDataVector TryZeroed(size_t size) {
if (size == 0) {
return FixedSizeDataVector();
}
T* ptr = FX_TryAlloc(T, size);
return FixedSizeDataVector(ptr, ptr ? size : 0u);
}
FixedSizeDataVector(const FixedSizeDataVector&) = delete;
FixedSizeDataVector& operator=(const FixedSizeDataVector&) = delete;
FixedSizeDataVector(FixedSizeDataVector<T>&& that) noexcept
: data_(std::move(that.data_)), size_(std::exchange(that.size_, 0)) {}
FixedSizeDataVector& operator=(FixedSizeDataVector<T>&& that) noexcept {
data_ = std::move(that.data_);
size_ = std::exchange(that.size_, 0);
return *this;
}
~FixedSizeDataVector() = default;
bool empty() const { return size_ == 0; }
size_t size() const { return size_; }
// Implicit access to data via span.
operator pdfium::span<T>() { return span(); }
operator pdfium::span<const T>() const { return span(); }
// Explicit access to data via span.
pdfium::span<T> span() {
// SAFETY: size_ describes size of data_.
return UNSAFE_BUFFERS(pdfium::make_span(data_.get(), size_));
}
pdfium::span<const T> span() const {
// SAFETY: size_ describes size of data_.
return UNSAFE_BUFFERS(pdfium::make_span(data_.get(), size_));
}
// Convenience methods to slice the vector into spans.
pdfium::span<T> subspan(size_t offset,
size_t count = pdfium::dynamic_extent) {
return span().subspan(offset, count);
}
pdfium::span<const T> subspan(size_t offset,
size_t count = pdfium::dynamic_extent) const {
return span().subspan(offset, count);
}
pdfium::span<T> first(size_t count) { return span().first(count); }
pdfium::span<const T> first(size_t count) const {
return span().first(count);
}
pdfium::span<T> last(size_t count) { return span().last(count); }
pdfium::span<const T> last(size_t count) const { return span().last(count); }
private:
FixedSizeDataVector(T* ptr, size_t size) : data_(ptr), size_(size) {}
std::unique_ptr<T, FxFreeDeleter> data_;
size_t size_ = 0;
};
} // namespace fxcrt
using fxcrt::FixedSizeDataVector;
#endif // CORE_FXCRT_FIXED_SIZE_DATA_VECTOR_H_