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_RUNTIME_BASE_ARRAY_SLICE_H_ 18 #define ART_RUNTIME_BASE_ARRAY_SLICE_H_ 19 20 #include "length_prefixed_array.h" 21 #include "stride_iterator.h" 22 #include "base/bit_utils.h" 23 #include "base/casts.h" 24 #include "base/iteration_range.h" 25 26 namespace art { 27 28 // An ArraySlice is an abstraction over an array or a part of an array of a particular type. It does 29 // bounds checking and can be made from several common array-like structures in Art. 30 template<typename T> 31 class ArraySlice { 32 public: 33 // Create an empty array slice. ArraySlice()34 ArraySlice() : array_(nullptr), size_(0), element_size_(0) {} 35 36 // Create an array slice of the first 'length' elements of the array, with each element being 37 // element_size bytes long. 38 ArraySlice(T* array, 39 size_t length, 40 size_t element_size = sizeof(T)) array_(array)41 : array_(array), 42 size_(dchecked_integral_cast<uint32_t>(length)), 43 element_size_(element_size) { 44 DCHECK(array_ != nullptr || length == 0); 45 } 46 47 // Create an array slice of the elements between start_offset and end_offset of the array with 48 // each element being element_size bytes long. Both start_offset and end_offset are in 49 // element_size units. 50 ArraySlice(T* array, 51 uint32_t start_offset, 52 uint32_t end_offset, 53 size_t element_size = sizeof(T)) array_(nullptr)54 : array_(nullptr), 55 size_(end_offset - start_offset), 56 element_size_(element_size) { 57 DCHECK(array_ != nullptr || size_ == 0); 58 DCHECK_LE(start_offset, end_offset); 59 if (size_ != 0) { 60 uintptr_t offset = start_offset * element_size_; 61 array_ = *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array) + offset); 62 } 63 } 64 65 // Create an array slice of the elements between start_offset and end_offset of the array with 66 // each element being element_size bytes long and having the given alignment. Both start_offset 67 // and end_offset are in element_size units. 68 ArraySlice(LengthPrefixedArray<T>* array, 69 uint32_t start_offset, 70 uint32_t end_offset, 71 size_t element_size = sizeof(T), 72 size_t alignment = alignof(T)) array_(nullptr)73 : array_(nullptr), 74 size_(end_offset - start_offset), 75 element_size_(element_size) { 76 DCHECK(array != nullptr || size_ == 0); 77 if (size_ != 0) { 78 DCHECK_LE(start_offset, end_offset); 79 DCHECK_LE(start_offset, array->size()); 80 DCHECK_LE(end_offset, array->size()); 81 array_ = &array->At(start_offset, element_size_, alignment); 82 } 83 } 84 At(size_t index)85 T& At(size_t index) { 86 DCHECK_LT(index, size_); 87 return AtUnchecked(index); 88 } 89 At(size_t index)90 const T& At(size_t index) const { 91 DCHECK_LT(index, size_); 92 return AtUnchecked(index); 93 } 94 95 T& operator[](size_t index) { 96 return At(index); 97 } 98 99 const T& operator[](size_t index) const { 100 return At(index); 101 } 102 begin()103 StrideIterator<T> begin() { 104 return StrideIterator<T>(&AtUnchecked(0), element_size_); 105 } 106 begin()107 StrideIterator<const T> begin() const { 108 return StrideIterator<const T>(&AtUnchecked(0), element_size_); 109 } 110 end()111 StrideIterator<T> end() { 112 return StrideIterator<T>(&AtUnchecked(size_), element_size_); 113 } 114 end()115 StrideIterator<const T> end() const { 116 return StrideIterator<const T>(&AtUnchecked(size_), element_size_); 117 } 118 AsRange()119 IterationRange<StrideIterator<T>> AsRange() { 120 return size() != 0 ? MakeIterationRange(begin(), end()) 121 : MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0)); 122 } 123 size()124 size_t size() const { 125 return size_; 126 } 127 ElementSize()128 size_t ElementSize() const { 129 return element_size_; 130 } 131 132 private: AtUnchecked(size_t index)133 T& AtUnchecked(size_t index) { 134 return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_); 135 } 136 AtUnchecked(size_t index)137 const T& AtUnchecked(size_t index) const { 138 return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_); 139 } 140 141 T* array_; 142 size_t size_; 143 size_t element_size_; 144 }; 145 146 } // namespace art 147 148 #endif // ART_RUNTIME_BASE_ARRAY_SLICE_H_ 149