• 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_BASE_VECTOR_H_
6 #define V8_BASE_VECTOR_H_
7 
8 #include <algorithm>
9 #include <cstring>
10 #include <iterator>
11 #include <limits>
12 #include <memory>
13 #include <type_traits>
14 
15 #include "src/base/logging.h"
16 #include "src/base/macros.h"
17 
18 namespace v8 {
19 namespace base {
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     DCHECK(length == 0 || data != nullptr);
32   }
33 
New(size_t length)34   static Vector<T> New(size_t length) {
35     return Vector<T>(new 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 = new 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     delete[] 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 V8_NODISCARD ScopedVector : public Vector<T> {
145  public:
ScopedVector(size_t length)146   explicit ScopedVector(size_t length) : Vector<T>(new T[length], length) {}
~ScopedVector()147   ~ScopedVector() { delete[] this->begin(); }
148 
149  private:
150   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector);
151 };
152 
153 template <typename T>
154 class OwnedVector {
155  public:
156   MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(OwnedVector);
OwnedVector(std::unique_ptr<T[]> data,size_t length)157   OwnedVector(std::unique_ptr<T[]> data, size_t length)
158       : data_(std::move(data)), length_(length) {
159     DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
160   }
161 
162   // Implicit conversion from {OwnedVector<U>} to {OwnedVector<T>}, instantiable
163   // if {std::unique_ptr<U>} can be converted to {std::unique_ptr<T>}.
164   // Can be used to convert {OwnedVector<T>} to {OwnedVector<const T>}.
165   template <typename U,
166             typename = typename std::enable_if<std::is_convertible<
167                 std::unique_ptr<U>, std::unique_ptr<T>>::value>::type>
OwnedVector(OwnedVector<U> && other)168   OwnedVector(OwnedVector<U>&& other)
169       : data_(std::move(other.data_)), length_(other.length_) {
170     STATIC_ASSERT(sizeof(U) == sizeof(T));
171     other.length_ = 0;
172   }
173 
174   // Returns the length of the vector as a size_t.
size()175   constexpr size_t size() const { return length_; }
176 
177   // Returns whether or not the vector is empty.
empty()178   constexpr bool empty() const { return length_ == 0; }
179 
180   // Returns the pointer to the start of the data in the vector.
start()181   T* start() const {
182     DCHECK_IMPLIES(length_ > 0, data_ != nullptr);
183     return data_.get();
184   }
185 
begin()186   constexpr T* begin() const { return start(); }
end()187   constexpr T* end() const { return start() + size(); }
188 
189   // Access individual vector elements - checks bounds in debug mode.
190   T& operator[](size_t index) const {
191     DCHECK_LT(index, length_);
192     return data_[index];
193   }
194 
195   // Returns a {Vector<T>} view of the data in this vector.
as_vector()196   Vector<T> as_vector() const { return Vector<T>(start(), size()); }
197 
198   // Releases the backing data from this vector and transfers ownership to the
199   // caller. This vector will be empty afterwards.
ReleaseData()200   std::unique_ptr<T[]> ReleaseData() {
201     length_ = 0;
202     return std::move(data_);
203   }
204 
205   // Allocates a new vector of the specified size via the default allocator.
206   // Elements in the new vector are value-initialized.
New(size_t size)207   static OwnedVector<T> New(size_t size) {
208     if (size == 0) return {};
209     return OwnedVector<T>(std::make_unique<T[]>(size), size);
210   }
211 
212   // Allocates a new vector of the specified size via the default allocator.
213   // Elements in the new vector are default-initialized.
NewForOverwrite(size_t size)214   static OwnedVector<T> NewForOverwrite(size_t size) {
215     if (size == 0) return {};
216     // TODO(v8): Use {std::make_unique_for_overwrite} once we allow C++20.
217     return OwnedVector<T>(std::unique_ptr<T[]>(new T[size]), size);
218   }
219 
220   // Allocates a new vector containing the specified collection of values.
221   // {Iterator} is the common type of {std::begin} and {std::end} called on a
222   // {const U&}. This function is only instantiable if that type exists.
223   template <typename U, typename Iterator = typename std::common_type<
224                             decltype(std::begin(std::declval<const U&>())),
225                             decltype(std::end(std::declval<const U&>()))>::type>
Of(const U & collection)226   static OwnedVector<T> Of(const U& collection) {
227     Iterator begin = std::begin(collection);
228     Iterator end = std::end(collection);
229     using non_const_t = typename std::remove_const<T>::type;
230     auto vec =
231         OwnedVector<non_const_t>::NewForOverwrite(std::distance(begin, end));
232     std::copy(begin, end, vec.start());
233     return vec;
234   }
235 
236   bool operator==(std::nullptr_t) const { return data_ == nullptr; }
237   bool operator!=(std::nullptr_t) const { return data_ != nullptr; }
238 
239  private:
240   template <typename U>
241   friend class OwnedVector;
242 
243   std::unique_ptr<T[]> data_;
244   size_t length_ = 0;
245 };
246 
247 // The vectors returned by {StaticCharVector}, {CStrVector}, or {OneByteVector}
248 // do not contain a null-termination byte. If you want the null byte, use
249 // {ArrayVector}.
250 
251 // Known length, constexpr.
252 template <size_t N>
StaticCharVector(const char (& array)[N])253 constexpr Vector<const char> StaticCharVector(const char (&array)[N]) {
254   return {array, N - 1};
255 }
256 
257 // Unknown length, not constexpr.
CStrVector(const char * data)258 inline Vector<const char> CStrVector(const char* data) {
259   return {data, strlen(data)};
260 }
261 
262 // OneByteVector is never constexpr because the data pointer is
263 // {reinterpret_cast}ed.
OneByteVector(const char * data,size_t length)264 inline Vector<const uint8_t> OneByteVector(const char* data, size_t length) {
265   return {reinterpret_cast<const uint8_t*>(data), length};
266 }
267 
OneByteVector(const char * data)268 inline Vector<const uint8_t> OneByteVector(const char* data) {
269   return OneByteVector(data, strlen(data));
270 }
271 
272 template <size_t N>
StaticOneByteVector(const char (& array)[N])273 Vector<const uint8_t> StaticOneByteVector(const char (&array)[N]) {
274   return OneByteVector(array, N - 1);
275 }
276 
277 // For string literals, ArrayVector("foo") returns a vector ['f', 'o', 'o', \0]
278 // with length 4 and null-termination.
279 // If you want ['f', 'o', 'o'], use CStrVector("foo").
280 template <typename T, size_t N>
ArrayVector(T (& arr)[N])281 inline constexpr Vector<T> ArrayVector(T (&arr)[N]) {
282   return {arr, N};
283 }
284 
285 // Construct a Vector from a start pointer and a size.
286 template <typename T>
VectorOf(T * start,size_t size)287 inline constexpr Vector<T> VectorOf(T* start, size_t size) {
288   return {start, size};
289 }
290 
291 // Construct a Vector from anything providing a {data()} and {size()} accessor.
292 template <typename Container>
293 inline constexpr auto VectorOf(Container&& c)
294     -> decltype(VectorOf(c.data(), c.size())) {
295   return VectorOf(c.data(), c.size());
296 }
297 
298 // Construct a Vector from an initializer list. The vector can obviously only be
299 // used as long as the initializer list is live. Valid uses include direct use
300 // in parameter lists: F(VectorOf({1, 2, 3}));
301 template <typename T>
VectorOf(std::initializer_list<T> list)302 inline constexpr Vector<const T> VectorOf(std::initializer_list<T> list) {
303   return VectorOf(list.begin(), list.size());
304 }
305 
306 template <typename T, size_t kSize>
307 class EmbeddedVector : public Vector<T> {
308  public:
EmbeddedVector()309   EmbeddedVector() : Vector<T>(buffer_, kSize) {}
EmbeddedVector(const T & initial_value)310   explicit EmbeddedVector(const T& initial_value) : Vector<T>(buffer_, kSize) {
311     std::fill_n(buffer_, kSize, initial_value);
312   }
313   EmbeddedVector(const EmbeddedVector&) = delete;
314   EmbeddedVector& operator=(const EmbeddedVector&) = delete;
315 
316  private:
317   T buffer_[kSize];
318 };
319 
320 }  // namespace base
321 }  // namespace v8
322 
323 #endif  // V8_BASE_VECTOR_H_
324