• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 the V8 project authors. All rights reserved.
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 V8_UTILS_VECTOR_H_
6 #define V8_UTILS_VECTOR_H_
7 
8 #include <algorithm>
9 #include <cstring>
10 #include <iterator>
11 #include <memory>
12 #include <type_traits>
13 
14 #include "src/common/checks.h"
15 #include "src/common/globals.h"
16 #include "src/utils/allocation.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 template <typename T>
22 class Vector {
23  public:
24   using value_type = T;
25   using iterator = T*;
26   using const_iterator = const T*;
27 
Vector()28   constexpr Vector() : start_(nullptr), length_(0) {}
29 
Vector(T * data,size_t length)30   constexpr Vector(T* data, size_t length) : start_(data), length_(length) {
31     CONSTEXPR_DCHECK(length == 0 || data != nullptr);
32   }
33 
New(size_t length)34   static Vector<T> New(size_t length) {
35     return Vector<T>(NewArray<T>(length), length);
36   }
37 
38   // Returns a vector using the same backing storage as this one,
39   // spanning from and including 'from', to but not including 'to'.
SubVector(size_t from,size_t to)40   Vector<T> SubVector(size_t from, size_t to) const {
41     DCHECK_LE(from, to);
42     DCHECK_LE(to, length_);
43     return Vector<T>(begin() + from, to - from);
44   }
45 
46   // Returns the length of the vector. Only use this if you really need an
47   // integer return value. Use {size()} otherwise.
length()48   int length() const {
49     DCHECK_GE(std::numeric_limits<int>::max(), length_);
50     return static_cast<int>(length_);
51   }
52 
53   // Returns the length of the vector as a size_t.
size()54   constexpr size_t size() const { return length_; }
55 
56   // Returns whether or not the vector is empty.
empty()57   constexpr bool empty() const { return length_ == 0; }
58 
59   // Access individual vector elements - checks bounds in debug mode.
60   T& operator[](size_t index) const {
61     DCHECK_LT(index, length_);
62     return start_[index];
63   }
64 
at(size_t index)65   const T& at(size_t index) const { return operator[](index); }
66 
first()67   T& first() { return start_[0]; }
68 
last()69   T& last() {
70     DCHECK_LT(0, length_);
71     return start_[length_ - 1];
72   }
73 
74   // Returns a pointer to the start of the data in the vector.
begin()75   constexpr T* begin() const { return start_; }
76 
77   // For consistency with other containers, do also provide a {data} accessor.
data()78   constexpr T* data() const { return start_; }
79 
80   // Returns a pointer past the end of the data in the vector.
end()81   constexpr T* end() const { return start_ + length_; }
82 
83   // Returns a clone of this vector with a new backing store.
Clone()84   Vector<T> Clone() const {
85     T* result = NewArray<T>(length_);
86     for (size_t i = 0; i < length_; i++) result[i] = start_[i];
87     return Vector<T>(result, length_);
88   }
89 
Truncate(size_t length)90   void Truncate(size_t length) {
91     DCHECK(length <= length_);
92     length_ = length;
93   }
94 
95   // Releases the array underlying this vector. Once disposed the
96   // vector is empty.
Dispose()97   void Dispose() {
98     DeleteArray(start_);
99     start_ = nullptr;
100     length_ = 0;
101   }
102 
103   Vector<T> operator+(size_t offset) {
104     DCHECK_LE(offset, length_);
105     return Vector<T>(start_ + offset, length_ - offset);
106   }
107 
108   Vector<T> operator+=(size_t offset) {
109     DCHECK_LE(offset, length_);
110     start_ += offset;
111     length_ -= offset;
112     return *this;
113   }
114 
115   // Implicit conversion from Vector<T> to Vector<const T>.
116   operator Vector<const T>() const { return {start_, length_}; }
117 
118   template <typename S>
cast(Vector<S> input)119   static Vector<T> cast(Vector<S> input) {
120     // Casting is potentially dangerous, so be really restrictive here. This
121     // might be lifted once we have use cases for that.
122     STATIC_ASSERT(std::is_pod<S>::value);
123     STATIC_ASSERT(std::is_pod<T>::value);
124     DCHECK_EQ(0, (input.size() * sizeof(S)) % sizeof(T));
125     DCHECK_EQ(0, reinterpret_cast<uintptr_t>(input.begin()) % alignof(T));
126     return Vector<T>(reinterpret_cast<T*>(input.begin()),
127                      input.size() * sizeof(S) / sizeof(T));
128   }
129 
130   bool operator==(const Vector<const T> other) const {
131     return std::equal(begin(), end(), other.begin(), other.end());
132   }
133 
134   bool operator!=(const Vector<const T> other) const {
135     return !operator==(other);
136   }
137 
138  private:
139   T* start_;
140   size_t length_;
141 };
142 
143 template <typename T>
144 class ScopedVector : public Vector<T> {
145  public:
ScopedVector(size_t length)146   explicit ScopedVector(size_t length)
147       : Vector<T>(NewArray<T>(length), length) {}
~ScopedVector()148   ~ScopedVector() { DeleteArray(this->begin()); }
149 
150  private:
151   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector);
152 };
153 
154 template <typename T>
155 class OwnedVector {
156  public:
157   MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(OwnedVector);
OwnedVector(std::unique_ptr<T[]> data,size_t length)158   OwnedVector(std::unique_ptr<T[]> data, size_t length)
159       : data_(std::move(data)), length_(length) {
160     DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
161   }
162 
163   // Implicit conversion from {OwnedVector<U>} to {OwnedVector<T>}, instantiable
164   // if {std::unique_ptr<U>} can be converted to {std::unique_ptr<T>}.
165   // Can be used to convert {OwnedVector<T>} to {OwnedVector<const T>}.
166   template <typename U,
167             typename = typename std::enable_if<std::is_convertible<
168                 std::unique_ptr<U>, std::unique_ptr<T>>::value>::type>
OwnedVector(OwnedVector<U> && other)169   OwnedVector(OwnedVector<U>&& other)
170       : data_(std::move(other.data_)), length_(other.length_) {
171     STATIC_ASSERT(sizeof(U) == sizeof(T));
172     other.length_ = 0;
173   }
174 
175   // Returns the length of the vector as a size_t.
size()176   constexpr size_t size() const { return length_; }
177 
178   // Returns whether or not the vector is empty.
empty()179   constexpr bool empty() const { return length_ == 0; }
180 
181   // Returns the pointer to the start of the data in the vector.
start()182   T* start() const {
183     DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
184     return data_.get();
185   }
186 
begin()187   constexpr T* begin() const { return start(); }
end()188   constexpr T* end() const { return start() + size(); }
189 
190   // Access individual vector elements - checks bounds in debug mode.
191   T& operator[](size_t index) const {
192     DCHECK_LT(index, length_);
193     return data_[index];
194   }
195 
196   // Returns a {Vector<T>} view of the data in this vector.
as_vector()197   Vector<T> as_vector() const { return Vector<T>(start(), size()); }
198 
199   // Releases the backing data from this vector and transfers ownership to the
200   // caller. This vector will be empty afterwards.
ReleaseData()201   std::unique_ptr<T[]> ReleaseData() {
202     length_ = 0;
203     return std::move(data_);
204   }
205 
206   // Allocates a new vector of the specified size via the default allocator.
207   // Elements in the new vector are value-initialized.
New(size_t size)208   static OwnedVector<T> New(size_t size) {
209     if (size == 0) return {};
210     return OwnedVector<T>(std::make_unique<T[]>(size), size);
211   }
212 
213   // Allocates a new vector of the specified size via the default allocator.
214   // Elements in the new vector are default-initialized.
NewForOverwrite(size_t size)215   static OwnedVector<T> NewForOverwrite(size_t size) {
216     if (size == 0) return {};
217     // TODO(v8): Use {std::make_unique_for_overwrite} once we allow C++20.
218     return OwnedVector<T>(std::unique_ptr<T[]>(new T[size]), size);
219   }
220 
221   // Allocates a new vector containing the specified collection of values.
222   // {Iterator} is the common type of {std::begin} and {std::end} called on a
223   // {const U&}. This function is only instantiable if that type exists.
224   template <typename U, typename Iterator = typename std::common_type<
225                             decltype(std::begin(std::declval<const U&>())),
226                             decltype(std::end(std::declval<const U&>()))>::type>
Of(const U & collection)227   static OwnedVector<T> Of(const U& collection) {
228     Iterator begin = std::begin(collection);
229     Iterator end = std::end(collection);
230     using non_const_t = typename std::remove_const<T>::type;
231     auto vec =
232         OwnedVector<non_const_t>::NewForOverwrite(std::distance(begin, end));
233     std::copy(begin, end, vec.start());
234     return vec;
235   }
236 
237   bool operator==(std::nullptr_t) const { return data_ == nullptr; }
238   bool operator!=(std::nullptr_t) const { return data_ != nullptr; }
239 
240  private:
241   template <typename U>
242   friend class OwnedVector;
243 
244   std::unique_ptr<T[]> data_;
245   size_t length_ = 0;
246 };
247 
248 // The vectors returned by {StaticCharVector}, {CStrVector}, or {OneByteVector}
249 // do not contain a null-termination byte. If you want the null byte, use
250 // {ArrayVector}.
251 
252 // Known length, constexpr.
253 template <size_t N>
StaticCharVector(const char (& array)[N])254 constexpr Vector<const char> StaticCharVector(const char (&array)[N]) {
255   return {array, N - 1};
256 }
257 
258 // Unknown length, not constexpr.
CStrVector(const char * data)259 inline Vector<const char> CStrVector(const char* data) {
260   return {data, strlen(data)};
261 }
262 
263 // OneByteVector is never constexpr because the data pointer is
264 // {reinterpret_cast}ed.
OneByteVector(const char * data,size_t length)265 inline Vector<const uint8_t> OneByteVector(const char* data, size_t length) {
266   return {reinterpret_cast<const uint8_t*>(data), length};
267 }
268 
OneByteVector(const char * data)269 inline Vector<const uint8_t> OneByteVector(const char* data) {
270   return OneByteVector(data, strlen(data));
271 }
272 
273 template <size_t N>
StaticOneByteVector(const char (& array)[N])274 Vector<const uint8_t> StaticOneByteVector(const char (&array)[N]) {
275   return OneByteVector(array, N - 1);
276 }
277 
278 // For string literals, ArrayVector("foo") returns a vector ['f', 'o', 'o', \0]
279 // with length 4 and null-termination.
280 // If you want ['f', 'o', 'o'], use CStrVector("foo").
281 template <typename T, size_t N>
ArrayVector(T (& arr)[N])282 inline constexpr Vector<T> ArrayVector(T (&arr)[N]) {
283   return {arr, N};
284 }
285 
286 // Construct a Vector from a start pointer and a size.
287 template <typename T>
VectorOf(T * start,size_t size)288 inline constexpr Vector<T> VectorOf(T* start, size_t size) {
289   return {start, size};
290 }
291 
292 // Construct a Vector from anything providing a {data()} and {size()} accessor.
293 template <typename Container>
294 inline constexpr auto VectorOf(Container&& c)
295     -> decltype(VectorOf(c.data(), c.size())) {
296   return VectorOf(c.data(), c.size());
297 }
298 
299 // Construct a Vector from an initializer list. The vector can obviously only be
300 // used as long as the initializer list is live. Valid uses include direct use
301 // in parameter lists: F(VectorOf({1, 2, 3}));
302 template <typename T>
VectorOf(std::initializer_list<T> list)303 inline constexpr Vector<const T> VectorOf(std::initializer_list<T> list) {
304   return VectorOf(list.begin(), list.size());
305 }
306 
307 template <typename T, size_t kSize>
308 class EmbeddedVector : public Vector<T> {
309  public:
EmbeddedVector()310   EmbeddedVector() : Vector<T>(buffer_, kSize) {}
311 
EmbeddedVector(const T & initial_value)312   explicit EmbeddedVector(const T& initial_value) : Vector<T>(buffer_, kSize) {
313     std::fill_n(buffer_, kSize, initial_value);
314   }
315 
316  private:
317   T buffer_[kSize];
318 
319   DISALLOW_COPY_AND_ASSIGN(EmbeddedVector);
320 };
321 
322 }  // namespace internal
323 }  // namespace v8
324 
325 #endif  // V8_UTILS_VECTOR_H_
326