• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2014 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #ifndef ART_LIBARTBASE_BASE_ARRAY_REF_H_
18  #define ART_LIBARTBASE_BASE_ARRAY_REF_H_
19  
20  #include <type_traits>
21  #include <vector>
22  
23  #include <android-base/logging.h>
24  
25  namespace art {
26  
27  /**
28   * @brief A container that references an array.
29   *
30   * @details The template class ArrayRef provides a container that references
31   * an external array. This external array must remain alive while the ArrayRef
32   * object is in use. The external array may be a std::vector<>-backed storage
33   * or any other contiguous chunk of memory but that memory must remain valid,
34   * i.e. the std::vector<> must not be resized for example.
35   *
36   * Except for copy/assign and insert/erase/capacity functions, the interface
37   * is essentially the same as std::vector<>. Since we don't want to throw
38   * exceptions, at() is also excluded.
39   */
40  template <typename T>
41  class ArrayRef {
42   public:
43    using value_type = T;
44    using reference = T&;
45    using const_reference = const T&;
46    using pointer = T*;
47    using const_pointer = const T*;
48    using iterator = T*;
49    using const_iterator = const T*;
50    using reverse_iterator = std::reverse_iterator<iterator>;
51    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
52    using difference_type = ptrdiff_t;
53    using size_type = size_t;
54  
55    // Constructors.
56  
ArrayRef()57    constexpr ArrayRef()
58        : array_(nullptr), size_(0u) {
59    }
60  
61    template <size_t size>
ArrayRef(T (& array)[size])62    explicit constexpr ArrayRef(T (&array)[size])
63        : array_(array), size_(size) {
64    }
65  
66    template <typename U,
67              size_t size,
68              typename = typename std::enable_if<std::is_same<T, const U>::value>::type>
ArrayRef(U (& array)[size])69    explicit constexpr ArrayRef(U (&array)[size])
70        : array_(array), size_(size) {
71    }
72  
ArrayRef(T * array_in,size_t size_in)73    constexpr ArrayRef(T* array_in, size_t size_in)
74        : array_(array_in), size_(size_in) {
75    }
76  
77    template <typename Vector,
78              typename = typename std::enable_if<
79                  std::is_same<typename Vector::value_type, value_type>::value>::type>
ArrayRef(Vector & v)80    explicit ArrayRef(Vector& v)
81        : array_(v.data()), size_(v.size()) {
82    }
83  
84    template <typename Vector,
85              typename = typename std::enable_if<
86                  std::is_same<
87                      typename std::add_const<typename Vector::value_type>::type,
88                      value_type>::value>::type>
ArrayRef(const Vector & v)89    explicit ArrayRef(const Vector& v)
90        : array_(v.data()), size_(v.size()) {
91    }
92  
93    ArrayRef(const ArrayRef&) = default;
94  
95    // Assignment operators.
96  
97    ArrayRef& operator=(const ArrayRef& other) {
98      array_ = other.array_;
99      size_ = other.size_;
100      return *this;
101    }
102  
103    template <typename U>
104    typename std::enable_if<std::is_same<T, const U>::value, ArrayRef>::type&
105    operator=(const ArrayRef<U>& other) {
106      return *this = ArrayRef(other);
107    }
108  
109    template <typename U>
Cast(const ArrayRef<U> & src)110    static ArrayRef Cast(const ArrayRef<U>& src) {
111      return ArrayRef(reinterpret_cast<const T*>(src.data()),
112                      src.size() * sizeof(T) / sizeof(U));
113    }
114  
115    // Destructor.
116    ~ArrayRef() = default;
117  
118    // Iterators.
begin()119    iterator begin() { return array_; }
begin()120    const_iterator begin() const { return array_; }
cbegin()121    const_iterator cbegin() const { return array_; }
end()122    iterator end() { return array_ + size_; }
end()123    const_iterator end() const { return array_ + size_; }
cend()124    const_iterator cend() const { return array_ + size_; }
rbegin()125    reverse_iterator rbegin() { return reverse_iterator(end()); }
rbegin()126    const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
crbegin()127    const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
rend()128    reverse_iterator rend() { return reverse_iterator(begin()); }
rend()129    const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
crend()130    const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }
131  
132    // Size.
size()133    size_type size() const { return size_; }
empty()134    bool empty() const { return size() == 0u; }
135  
136    // Element access. NOTE: Not providing at().
137  
138    reference operator[](size_type n) {
139      DCHECK_LT(n, size_);
140      return array_[n];
141    }
142  
143    const_reference operator[](size_type n) const {
144      DCHECK_LT(n, size_);
145      return array_[n];
146    }
147  
front()148    reference front() {
149      DCHECK(!empty());
150      return array_[0];
151    }
152  
front()153    const_reference front() const {
154      DCHECK(!empty());
155      return array_[0];
156    }
157  
back()158    reference back() {
159      DCHECK(!empty());
160      return array_[size_ - 1u];
161    }
162  
back()163    const_reference back() const {
164      DCHECK(!empty());
165      return array_[size_ - 1u];
166    }
167  
data()168    value_type* data() { return array_; }
data()169    const value_type* data() const { return array_; }
170  
SubArray(size_type pos)171    ArrayRef SubArray(size_type pos) {
172      return SubArray(pos, size() - pos);
173    }
174  
SubArray(size_type pos)175    ArrayRef<const T> SubArray(size_type pos) const {
176      return SubArray(pos, size() - pos);
177    }
178  
SubArray(size_type pos,size_type length)179    ArrayRef SubArray(size_type pos, size_type length) {
180      DCHECK_LE(pos, size());
181      DCHECK_LE(length, size() - pos);
182      return ArrayRef(data() + pos, length);
183    }
184  
SubArray(size_type pos,size_type length)185    ArrayRef<const T> SubArray(size_type pos, size_type length) const {
186      DCHECK_LE(pos, size());
187      DCHECK_LE(length, size() - pos);
188      return ArrayRef<const T>(data() + pos, length);
189    }
190  
191   private:
192    T* array_;
193    size_t size_;
194  };
195  
196  template <typename T>
197  bool operator==(const ArrayRef<T>& lhs, const ArrayRef<T>& rhs) {
198    return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
199  }
200  
201  template <typename T>
202  bool operator!=(const ArrayRef<T>& lhs, const ArrayRef<T>& rhs) {
203    return !(lhs == rhs);
204  }
205  
206  }  // namespace art
207  
208  
209  #endif  // ART_LIBARTBASE_BASE_ARRAY_REF_H_
210