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 18namespace v8 { 19namespace base { 20 21template <typename T> 22class Vector { 23 public: 24 using value_type = T; 25 using iterator = T*; 26 using const_iterator = const T*; 27 28 constexpr Vector() : start_(nullptr), length_(0) {} 29 30 constexpr Vector(T* data, size_t length) : start_(data), length_(length) { 31 DCHECK(length == 0 || data != nullptr); 32 } 33 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'. 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. 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. 54 constexpr size_t size() const { return length_; } 55 56 // Returns whether or not the vector is 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 65 const T& at(size_t index) const { return operator[](index); } 66 67 T& first() { return start_[0]; } 68 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. 75 constexpr T* begin() const { return start_; } 76 77 // For consistency with other containers, do also provide a {data} accessor. 78 constexpr T* data() const { return start_; } 79 80 // Returns a pointer past the end of the data in the vector. 81 constexpr T* end() const { return start_ + length_; } 82 83 // Returns a clone of this vector with a new backing store. 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 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. 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> 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 143template <typename T> 144class V8_NODISCARD ScopedVector : public Vector<T> { 145 public: 146 explicit ScopedVector(size_t length) : Vector<T>(new T[length], length) {} 147 ~ScopedVector() { delete[] this->begin(); } 148 149 private: 150 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector); 151}; 152 153template <typename T> 154class OwnedVector { 155 public: 156 MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(OwnedVector); 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> 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. 175 constexpr size_t size() const { return length_; } 176 177 // Returns whether or not the vector is empty. 178 constexpr bool empty() const { return length_ == 0; } 179 180 // Returns the pointer to the start of the data in the vector. 181 T* start() const { 182 DCHECK_IMPLIES(length_ > 0, data_ != nullptr); 183 return data_.get(); 184 } 185 186 constexpr T* begin() const { return start(); } 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. 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. 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. 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. 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> 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. 252template <size_t N> 253constexpr Vector<const char> StaticCharVector(const char (&array)[N]) { 254 return {array, N - 1}; 255} 256 257// Unknown length, not constexpr. 258inline 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. 264inline Vector<const uint8_t> OneByteVector(const char* data, size_t length) { 265 return {reinterpret_cast<const uint8_t*>(data), length}; 266} 267 268inline Vector<const uint8_t> OneByteVector(const char* data) { 269 return OneByteVector(data, strlen(data)); 270} 271 272template <size_t N> 273Vector<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"). 280template <typename T, size_t N> 281inline constexpr Vector<T> ArrayVector(T (&arr)[N]) { 282 return {arr, N}; 283} 284 285// Construct a Vector from a start pointer and a size. 286template <typename T> 287inline 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. 292template <typename Container> 293inline 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})); 301template <typename T> 302inline constexpr Vector<const T> VectorOf(std::initializer_list<T> list) { 303 return VectorOf(list.begin(), list.size()); 304} 305 306template <typename T, size_t kSize> 307class EmbeddedVector : public Vector<T> { 308 public: 309 EmbeddedVector() : Vector<T>(buffer_, kSize) {} 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