Home | History | Annotate | Download | only in base
      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.
     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))
     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))
     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))
     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 
     85   T& At(size_t index) {
     86     DCHECK_LT(index, size_);
     87     return AtUnchecked(index);
     88   }
     89 
     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 
    103   StrideIterator<T> begin() {
    104     return StrideIterator<T>(&AtUnchecked(0), element_size_);
    105   }
    106 
    107   StrideIterator<const T> begin() const {
    108     return StrideIterator<const T>(&AtUnchecked(0), element_size_);
    109   }
    110 
    111   StrideIterator<T> end() {
    112     return StrideIterator<T>(&AtUnchecked(size_), element_size_);
    113   }
    114 
    115   StrideIterator<const T> end() const {
    116     return StrideIterator<const T>(&AtUnchecked(size_), element_size_);
    117   }
    118 
    119   IterationRange<StrideIterator<T>> AsRange() {
    120     return size() != 0 ? MakeIterationRange(begin(), end())
    121                        : MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
    122   }
    123 
    124   size_t size() const {
    125     return size_;
    126   }
    127 
    128   size_t ElementSize() const {
    129     return element_size_;
    130   }
    131 
    132   bool Contains(const T* element) const {
    133     return &AtUnchecked(0) <= element && element < &AtUnchecked(size_);
    134   }
    135 
    136  private:
    137   T& AtUnchecked(size_t index) {
    138     return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_);
    139   }
    140 
    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_RUNTIME_BASE_ARRAY_SLICE_H_
    153