/* * Copyright (C) 2014 The Android Open Source Project * * 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 ART_LIBARTBASE_BASE_ARRAY_REF_H_ #define ART_LIBARTBASE_BASE_ARRAY_REF_H_ #include #include #include namespace art { /** * @brief A container that references an array. * * @details The template class ArrayRef provides a container that references * an external array. This external array must remain alive while the ArrayRef * object is in use. The external array may be a std::vector<>-backed storage * or any other contiguous chunk of memory but that memory must remain valid, * i.e. the std::vector<> must not be resized for example. * * Except for copy/assign and insert/erase/capacity functions, the interface * is essentially the same as std::vector<>. Since we don't want to throw * exceptions, at() is also excluded. */ template class ArrayRef { public: using value_type = T; using reference = T&; using const_reference = const T&; using pointer = T*; using const_pointer = const T*; using iterator = T*; using const_iterator = const T*; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; using difference_type = ptrdiff_t; using size_type = size_t; // Constructors. constexpr ArrayRef() : array_(nullptr), size_(0u) { } template explicit constexpr ArrayRef(T (&array)[size]) : array_(array), size_(size) { } template ::value>::type> explicit constexpr ArrayRef(U (&array)[size]) : array_(array), size_(size) { } constexpr ArrayRef(T* array, size_t size) : array_(array), size_(size) { } template ::value>::type> explicit ArrayRef(Vector& v) : array_(v.data()), size_(v.size()) { } template ::type, value_type>::value>::type> explicit ArrayRef(const Vector& v) : array_(v.data()), size_(v.size()) { } ArrayRef(const ArrayRef&) = default; // Assignment operators. ArrayRef& operator=(const ArrayRef& other) { array_ = other.array_; size_ = other.size_; return *this; } template typename std::enable_if::value, ArrayRef>::type& operator=(const ArrayRef& other) { return *this = ArrayRef(other); } template static ArrayRef Cast(const ArrayRef& src) { return ArrayRef(reinterpret_cast(src.data()), src.size() * sizeof(T) / sizeof(U)); } // Destructor. ~ArrayRef() = default; // Iterators. iterator begin() { return array_; } const_iterator begin() const { return array_; } const_iterator cbegin() const { return array_; } iterator end() { return array_ + size_; } const_iterator end() const { return array_ + size_; } const_iterator cend() const { return array_ + size_; } reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); } // Size. size_type size() const { return size_; } bool empty() const { return size() == 0u; } // Element access. NOTE: Not providing at(). reference operator[](size_type n) { DCHECK_LT(n, size_); return array_[n]; } const_reference operator[](size_type n) const { DCHECK_LT(n, size_); return array_[n]; } reference front() { DCHECK(!empty()); return array_[0]; } const_reference front() const { DCHECK(!empty()); return array_[0]; } reference back() { DCHECK(!empty()); return array_[size_ - 1u]; } const_reference back() const { DCHECK(!empty()); return array_[size_ - 1u]; } value_type* data() { return array_; } const value_type* data() const { return array_; } ArrayRef SubArray(size_type pos) { return SubArray(pos, size() - pos); } ArrayRef SubArray(size_type pos) const { return SubArray(pos, size() - pos); } ArrayRef SubArray(size_type pos, size_type length) { DCHECK_LE(pos, size()); DCHECK_LE(length, size() - pos); return ArrayRef(data() + pos, length); } ArrayRef SubArray(size_type pos, size_type length) const { DCHECK_LE(pos, size()); DCHECK_LE(length, size() - pos); return ArrayRef(data() + pos, length); } private: T* array_; size_t size_; }; template bool operator==(const ArrayRef& lhs, const ArrayRef& rhs) { return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } template bool operator!=(const ArrayRef& lhs, const ArrayRef& rhs) { return !(lhs == rhs); } } // namespace art #endif // ART_LIBARTBASE_BASE_ARRAY_REF_H_