1 /* 2 * Copyright (C) 2015 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_SLICE_H_ 18 #define ART_LIBARTBASE_BASE_ARRAY_SLICE_H_ 19 20 #include "bit_utils.h" 21 #include "casts.h" 22 #include "iteration_range.h" 23 #include "stride_iterator.h" 24 25 namespace art { 26 27 // An ArraySlice is an abstraction over an array or a part of an array of a particular type. It does 28 // bounds checking and can be made from several common array-like structures in Art. 29 template <typename T> 30 class ArraySlice { 31 public: 32 using value_type = T; 33 using reference = T&; 34 using const_reference = const T&; 35 using pointer = T*; 36 using const_pointer = const T*; 37 using iterator = StrideIterator<T>; 38 using const_iterator = StrideIterator<const T>; 39 using reverse_iterator = std::reverse_iterator<iterator>; 40 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 41 using difference_type = ptrdiff_t; 42 using size_type = size_t; 43 44 // Create an empty array slice. ArraySlice()45 ArraySlice() : array_(nullptr), size_(0), element_size_(0) {} 46 47 // Create an array slice of the first 'length' elements of the array, with each element being 48 // element_size bytes long. 49 ArraySlice(T* array, 50 size_t length, 51 size_t element_size = sizeof(T)) array_(array)52 : array_(array), 53 size_(dchecked_integral_cast<uint32_t>(length)), 54 element_size_(element_size) { 55 DCHECK(array_ != nullptr || length == 0); 56 } 57 58 // Iterators. begin()59 iterator begin() { return iterator(&AtUnchecked(0), element_size_); } begin()60 const_iterator begin() const { return const_iterator(&AtUnchecked(0), element_size_); } cbegin()61 const_iterator cbegin() const { return const_iterator(&AtUnchecked(0), element_size_); } end()62 StrideIterator<T> end() { return StrideIterator<T>(&AtUnchecked(size_), element_size_); } end()63 const_iterator end() const { return const_iterator(&AtUnchecked(size_), element_size_); } cend()64 const_iterator cend() const { return const_iterator(&AtUnchecked(size_), element_size_); } rbegin()65 reverse_iterator rbegin() { return reverse_iterator(end()); } rbegin()66 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } crbegin()67 const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); } rend()68 reverse_iterator rend() { return reverse_iterator(begin()); } rend()69 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } crend()70 const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); } 71 72 // Size. size()73 size_type size() const { return size_; } empty()74 bool empty() const { return size() == 0u; } 75 76 // Element access. NOTE: Not providing at() and data(). 77 78 reference operator[](size_t index) { 79 DCHECK_LT(index, size_); 80 return AtUnchecked(index); 81 } 82 83 const_reference operator[](size_t index) const { 84 DCHECK_LT(index, size_); 85 return AtUnchecked(index); 86 } 87 front()88 reference front() { 89 DCHECK(!empty()); 90 return (*this)[0]; 91 } 92 front()93 const_reference front() const { 94 DCHECK(!empty()); 95 return (*this)[0]; 96 } 97 back()98 reference back() { 99 DCHECK(!empty()); 100 return (*this)[size_ - 1u]; 101 } 102 back()103 const_reference back() const { 104 DCHECK(!empty()); 105 return (*this)[size_ - 1u]; 106 } 107 SubArray(size_type pos)108 ArraySlice<T> SubArray(size_type pos) { 109 return SubArray(pos, size() - pos); 110 } 111 SubArray(size_type pos)112 ArraySlice<const T> SubArray(size_type pos) const { 113 return SubArray(pos, size() - pos); 114 } 115 SubArray(size_type pos,size_type length)116 ArraySlice<T> SubArray(size_type pos, size_type length) { 117 DCHECK_LE(pos, size()); 118 DCHECK_LE(length, size() - pos); 119 return ArraySlice<T>(&AtUnchecked(pos), length, element_size_); 120 } 121 SubArray(size_type pos,size_type length)122 ArraySlice<const T> SubArray(size_type pos, size_type length) const { 123 DCHECK_LE(pos, size()); 124 DCHECK_LE(length, size() - pos); 125 return ArraySlice<const T>(&AtUnchecked(pos), length, element_size_); 126 } 127 ElementSize()128 size_t ElementSize() const { 129 return element_size_; 130 } 131 Contains(const T * element)132 bool Contains(const T* element) const { 133 return &AtUnchecked(0) <= element && element < &AtUnchecked(size_); 134 } 135 136 private: AtUnchecked(size_t index)137 T& AtUnchecked(size_t index) { 138 return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_); 139 } 140 AtUnchecked(size_t index)141 const T& AtUnchecked(size_t index) const { 142 return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_); 143 } 144 145 T* array_; 146 size_t size_; 147 size_t element_size_; 148 }; 149 150 } // namespace art 151 152 #endif // ART_LIBARTBASE_BASE_ARRAY_SLICE_H_ 153