/* * Copyright 2019 The libgav1 Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef LIBGAV1_SRC_UTILS_ARRAY_2D_H_ #define LIBGAV1_SRC_UTILS_ARRAY_2D_H_ #include #include #include #include #include #include #include "src/utils/compiler_attributes.h" namespace libgav1 { // Exposes a 1D allocated memory buffer as a 2D array. template class Array2DView { public: Array2DView() = default; Array2DView(int rows, int columns, T* const data) { Reset(rows, columns, data); } // Copyable and Movable. Array2DView(const Array2DView& rhs) = default; Array2DView& operator=(const Array2DView& rhs) = default; void Reset(int rows, int columns, T* const data) { rows_ = rows; columns_ = columns; data_ = data; } int rows() const { return rows_; } int columns() const { return columns_; } T* operator[](int row) { return const_cast(GetRow(row)); } const T* operator[](int row) const { return GetRow(row); } private: const T* GetRow(int row) const { assert(row < rows_); const ptrdiff_t offset = static_cast(row) * columns_; return data_ + offset; } int rows_ = 0; int columns_ = 0; T* data_ = nullptr; }; // Allocates and owns the contiguous memory and exposes an Array2DView of // dimension |rows| x |columns|. template class Array2D { public: Array2D() = default; // Copyable and Movable. Array2D(const Array2D& rhs) = default; Array2D& operator=(const Array2D& rhs) = default; LIBGAV1_MUST_USE_RESULT bool Reset(int rows, int columns, bool zero_initialize = true) { size_ = rows * columns; // If T is not a trivial type, we should always reallocate the data_ // buffer, so that the destructors of any existing objects are invoked. if (!std::is_trivial::value || allocated_size_ < size_) { // Note: This invokes the global operator new if T is a non-class type, // such as integer or enum types, or a class type that is not derived // from libgav1::Allocable, such as std::unique_ptr. If we enforce a // maximum allocation size or keep track of our own heap memory // consumption, we will need to handle the allocations here that use the // global operator new. if (zero_initialize) { data_.reset(new (std::nothrow) T[size_]()); } else { data_.reset(new (std::nothrow) T[size_]); } if (data_ == nullptr) { allocated_size_ = 0; return false; } allocated_size_ = size_; } else if (zero_initialize) { // Cast the data_ pointer to void* to avoid the GCC -Wclass-memaccess // warning. The memset is safe because T is a trivial type. void* dest = data_.get(); memset(dest, 0, sizeof(T) * size_); } data_view_.Reset(rows, columns, data_.get()); return true; } int rows() const { return data_view_.rows(); } int columns() const { return data_view_.columns(); } size_t size() const { return size_; } T* data() { return data_.get(); } const T* data() const { return data_.get(); } T* operator[](int row) { return data_view_[row]; } const T* operator[](int row) const { return data_view_[row]; } private: std::unique_ptr data_; size_t allocated_size_ = 0; size_t size_ = 0; Array2DView data_view_; }; } // namespace libgav1 #endif // LIBGAV1_SRC_UTILS_ARRAY_2D_H_