1/*
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5// ATTENTION: The code in this file is highly EXPERIMENTAL.
6// Adventurous users should note that the APIs will probably change.
7
8//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===//
9//
10// The LLVM Compiler Infrastructure
11//
12// This file is distributed under the University of Illinois Open Source
13// License. See LICENSE.TXT for details.
14//
15//===----------------------------------------------------------------------===//
16
17// ONNX: modified from llvm::ArrayRef.
18// removed llvm-specific functionality
19// removed some implicit const -> non-const conversions that rely on
20// complicated std::enable_if meta-programming
21// removed a bunch of slice variants for simplicity...
22
23#pragma once
24#include <assert.h>
25#include <array>
26#include <vector>
27
28namespace ONNX_NAMESPACE {
29/// ArrayRef - Represent a constant reference to an array (0 or more elements
30/// consecutively in memory), i.e. a start pointer and a length. It allows
31/// various APIs to take consecutive elements easily and conveniently.
32///
33/// This class does not own the underlying data, it is expected to be used in
34/// situations where the data resides in some other buffer, whose lifetime
35/// extends past that of the ArrayRef. For this reason, it is not in general
36/// safe to store an ArrayRef.
37///
38/// This is intended to be trivially copyable, so it should be passed by
39/// value.
40template <typename T>
41class ArrayRef {
42 public:
43 typedef const T* iterator;
44 typedef const T* const_iterator;
45 typedef size_t size_type;
46
47 typedef std::reverse_iterator<iterator> reverse_iterator;
48
49 private:
50 /// The start of the array, in an external buffer.
51 const T* Data;
52
53 /// The number of elements.
54 size_type Length;
55
56 public:
57 /// @name Constructors
58 /// @{
59
60 /// Construct an empty ArrayRef.
61 /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {}
62
63 /// Construct an ArrayRef from a single element.
64 /*implicit*/ ArrayRef(const T& OneElt) : Data(&OneElt), Length(1) {}
65
66 /// Construct an ArrayRef from a pointer and length.
67 /*implicit*/ ArrayRef(const T* data, size_t length) : Data(data), Length(length) {}
68
69 /// Construct an ArrayRef from a range.
70 ArrayRef(const T* begin, const T* end) : Data(begin), Length(end - begin) {}
71
72 /// Construct an ArrayRef from a std::vector.
73 template <typename A>
74 /*implicit*/ ArrayRef(const std::vector<T, A>& Vec) : Data(Vec.data()), Length(Vec.size()) {}
75
76 /// Construct an ArrayRef from a std::array
77 template <size_t N>
78 /*implicit*/ constexpr ArrayRef(const std::array<T, N>& Arr) : Data(Arr.data()), Length(N) {}
79
80 /// Construct an ArrayRef from a C array.
81 template <size_t N>
82 /*implicit*/ constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {}
83
84 /// Construct an ArrayRef from a std::initializer_list.
85 /*implicit*/ ArrayRef(const std::initializer_list<T>& Vec)
86 : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()), Length(Vec.size()) {}
87
88 /// @}
89 /// @name Simple Operations
90 /// @{
91
92 iterator begin() const {
93 return Data;
94 }
95 iterator end() const {
96 return Data + Length;
97 }
98
99 reverse_iterator rbegin() const {
100 return reverse_iterator(end());
101 }
102 reverse_iterator rend() const {
103 return reverse_iterator(begin());
104 }
105
106 /// empty - Check if the array is empty.
107 bool empty() const {
108 return Length == 0;
109 }
110
111 const T* data() const {
112 return Data;
113 }
114
115 /// size - Get the array size.
116 size_t size() const {
117 return Length;
118 }
119
120 /// front - Get the first element.
121 const T& front() const {
122 assert(!empty());
123 return Data[0];
124 }
125
126 /// back - Get the last element.
127 const T& back() const {
128 assert(!empty());
129 return Data[Length - 1];
130 }
131
132 /// equals - Check for element-wise equality.
133 bool equals(ArrayRef RHS) const {
134 if (Length != RHS.Length)
135 return false;
136 return std::equal(begin(), end(), RHS.begin());
137 }
138
139 /// slice(n, m) - Chop off the first N elements of the array, and keep M
140 /// elements in the array.
141 ArrayRef<T> slice(size_t N, size_t M) const {
142 assert(N + M <= size() && "Invalid specifier");
143 return ArrayRef<T>(data() + N, M);
144 }
145
146 /// slice(n) - Chop off the first N elements of the array.
147 ArrayRef<T> slice(size_t N) const {
148 return slice(N, size() - N);
149 }
150
151 /// @}
152 /// @name Operator Overloads
153 /// @{
154 const T& operator[](size_t Index) const {
155 assert(Index < Length && "Invalid index!");
156 return Data[Index];
157 }
158
159 /// Vector compatibility
160 const T& at(size_t Index) const {
161 assert(Index < Length && "Invalid index!");
162 return Data[Index];
163 }
164
165 /// Disallow accidental assignment from a temporary.
166 ///
167 /// The declaration here is extra complicated so that "arrayRef = {}"
168 /// continues to select the move assignment operator.
169 template <typename U>
170 typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type& operator=(U&& Temporary) = delete;
171
172 /// Disallow accidental assignment from a temporary.
173 ///
174 /// The declaration here is extra complicated so that "arrayRef = {}"
175 /// continues to select the move assignment operator.
176 template <typename U>
177 typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type& operator=(std::initializer_list<U>) = delete;
178
179 /// @}
180 /// @name Expensive Operations
181 /// @{
182 std::vector<T> vec() const {
183 return std::vector<T>(Data, Data + Length);
184 }
185
186 /// @}
187 /// @name Conversion operators
188 /// @{
189 operator std::vector<T>() const {
190 return std::vector<T>(Data, Data + Length);
191 }
192
193 /// @}
194};
195
196} // namespace ONNX_NAMESPACE
197