1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_LENGTH_PREFIXED_ARRAY_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_LENGTH_PREFIXED_ARRAY_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <stddef.h> // for offsetof() 21*795d594fSAndroid Build Coastguard Worker #include <string.h> // for memset() 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker #include "bit_utils.h" 24*795d594fSAndroid Build Coastguard Worker #include "casts.h" 25*795d594fSAndroid Build Coastguard Worker #include "iteration_range.h" 26*795d594fSAndroid Build Coastguard Worker #include "stride_iterator.h" 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker namespace art { 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker template<typename T> 31*795d594fSAndroid Build Coastguard Worker class LengthPrefixedArray { 32*795d594fSAndroid Build Coastguard Worker public: LengthPrefixedArray(size_t length)33*795d594fSAndroid Build Coastguard Worker explicit LengthPrefixedArray(size_t length) 34*795d594fSAndroid Build Coastguard Worker : size_(dchecked_integral_cast<uint32_t>(length)) {} 35*795d594fSAndroid Build Coastguard Worker 36*795d594fSAndroid Build Coastguard Worker T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 37*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, size_); 38*795d594fSAndroid Build Coastguard Worker return AtUnchecked(index, element_size, alignment); 39*795d594fSAndroid Build Coastguard Worker } 40*795d594fSAndroid Build Coastguard Worker 41*795d594fSAndroid Build Coastguard Worker const T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) const { 42*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, size_); 43*795d594fSAndroid Build Coastguard Worker return AtUnchecked(index, element_size, alignment); 44*795d594fSAndroid Build Coastguard Worker } 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Worker StrideIterator<T> begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 47*795d594fSAndroid Build Coastguard Worker return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size); 48*795d594fSAndroid Build Coastguard Worker } 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker StrideIterator<const T> begin(size_t element_size = sizeof(T), 51*795d594fSAndroid Build Coastguard Worker size_t alignment = alignof(T)) const { 52*795d594fSAndroid Build Coastguard Worker return StrideIterator<const T>(&AtUnchecked(0, element_size, alignment), element_size); 53*795d594fSAndroid Build Coastguard Worker } 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker StrideIterator<T> end(size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 56*795d594fSAndroid Build Coastguard Worker return StrideIterator<T>(&AtUnchecked(size_, element_size, alignment), element_size); 57*795d594fSAndroid Build Coastguard Worker } 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker StrideIterator<const T> end(size_t element_size = sizeof(T), 60*795d594fSAndroid Build Coastguard Worker size_t alignment = alignof(T)) const { 61*795d594fSAndroid Build Coastguard Worker return StrideIterator<const T>(&AtUnchecked(size_, element_size, alignment), element_size); 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker static size_t OffsetOfElement(size_t index, 65*795d594fSAndroid Build Coastguard Worker size_t element_size = sizeof(T), 66*795d594fSAndroid Build Coastguard Worker size_t alignment = alignof(T)) { 67*795d594fSAndroid Build Coastguard Worker DCHECK_ALIGNED_PARAM(element_size, alignment); 68*795d594fSAndroid Build Coastguard Worker return RoundUp(offsetof(LengthPrefixedArray<T>, data_), alignment) + index * element_size; 69*795d594fSAndroid Build Coastguard Worker } 70*795d594fSAndroid Build Coastguard Worker 71*795d594fSAndroid Build Coastguard Worker static size_t ComputeSize(size_t num_elements, 72*795d594fSAndroid Build Coastguard Worker size_t element_size = sizeof(T), 73*795d594fSAndroid Build Coastguard Worker size_t alignment = alignof(T)) { 74*795d594fSAndroid Build Coastguard Worker size_t result = OffsetOfElement(num_elements, element_size, alignment); 75*795d594fSAndroid Build Coastguard Worker DCHECK_ALIGNED_PARAM(result, alignment); 76*795d594fSAndroid Build Coastguard Worker return result; 77*795d594fSAndroid Build Coastguard Worker } 78*795d594fSAndroid Build Coastguard Worker size()79*795d594fSAndroid Build Coastguard Worker size_t size() const { 80*795d594fSAndroid Build Coastguard Worker return size_; 81*795d594fSAndroid Build Coastguard Worker } 82*795d594fSAndroid Build Coastguard Worker 83*795d594fSAndroid Build Coastguard Worker // Update the length but does not reallocate storage. SetSize(size_t length)84*795d594fSAndroid Build Coastguard Worker void SetSize(size_t length) { 85*795d594fSAndroid Build Coastguard Worker size_ = dchecked_integral_cast<uint32_t>(length); 86*795d594fSAndroid Build Coastguard Worker } 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker // Clear the potentially uninitialized padding between the size_ and actual data. 89*795d594fSAndroid Build Coastguard Worker void ClearPadding(size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 90*795d594fSAndroid Build Coastguard Worker size_t gap_offset = offsetof(LengthPrefixedArray<T>, data_); 91*795d594fSAndroid Build Coastguard Worker size_t gap_size = OffsetOfElement(0, element_size, alignment) - gap_offset; 92*795d594fSAndroid Build Coastguard Worker memset(reinterpret_cast<uint8_t*>(this) + gap_offset, 0, gap_size); 93*795d594fSAndroid Build Coastguard Worker } 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker private: AtUnchecked(size_t index,size_t element_size,size_t alignment)96*795d594fSAndroid Build Coastguard Worker T& AtUnchecked(size_t index, size_t element_size, size_t alignment) { 97*795d594fSAndroid Build Coastguard Worker return *reinterpret_cast<T*>( 98*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment)); 99*795d594fSAndroid Build Coastguard Worker } 100*795d594fSAndroid Build Coastguard Worker AtUnchecked(size_t index,size_t element_size,size_t alignment)101*795d594fSAndroid Build Coastguard Worker const T& AtUnchecked(size_t index, size_t element_size, size_t alignment) const { 102*795d594fSAndroid Build Coastguard Worker return *reinterpret_cast<T*>( 103*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment)); 104*795d594fSAndroid Build Coastguard Worker } 105*795d594fSAndroid Build Coastguard Worker 106*795d594fSAndroid Build Coastguard Worker uint32_t size_; 107*795d594fSAndroid Build Coastguard Worker uint8_t data_[0]; 108*795d594fSAndroid Build Coastguard Worker }; 109*795d594fSAndroid Build Coastguard Worker 110*795d594fSAndroid Build Coastguard Worker // Returns empty iteration range if the array is null. 111*795d594fSAndroid Build Coastguard Worker template<typename T> 112*795d594fSAndroid Build Coastguard Worker IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray( 113*795d594fSAndroid Build Coastguard Worker LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 114*795d594fSAndroid Build Coastguard Worker return arr != nullptr ? 115*795d594fSAndroid Build Coastguard Worker MakeIterationRange(arr->begin(element_size, alignment), arr->end(element_size, alignment)) : 116*795d594fSAndroid Build Coastguard Worker MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0)); 117*795d594fSAndroid Build Coastguard Worker } 118*795d594fSAndroid Build Coastguard Worker 119*795d594fSAndroid Build Coastguard Worker } // namespace art 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBARTBASE_BASE_LENGTH_PREFIXED_ARRAY_H_ 122