aboutsummaryrefslogtreecommitdiff
path: root/src/utils/array_2d.h
blob: df2da9f7b3958b162c989d2e642d4718dacd436b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * 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 <cassert>
#include <cstddef>
#include <cstring>
#include <memory>
#include <new>
#include <type_traits>

#include "src/utils/compiler_attributes.h"

namespace libgav1 {

// Exposes a 1D allocated memory buffer as a 2D array.
template <typename T>
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<T*>(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<ptrdiff_t>(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 <typename T>
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<T>::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<T[]> data_;
  size_t allocated_size_ = 0;
  size_t size_ = 0;
  Array2DView<T> data_view_;
};

}  // namespace libgav1

#endif  // LIBGAV1_SRC_UTILS_ARRAY_2D_H_