blob: d9bc656673ba57d74b463e2678a768ca4ae976be [file] [log] [blame]
Mathieu Chartier54d220e2015-07-30 16:20:06 -07001/*
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_LENGTH_PREFIXED_ARRAY_H_
18#define ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_
19
20#include <stddef.h> // for offsetof()
21
22#include "linear_alloc.h"
23#include "stride_iterator.h"
Vladimir Markocf36d492015-08-12 19:27:26 +010024#include "base/bit_utils.h"
25#include "base/casts.h"
Mathieu Chartier54d220e2015-07-30 16:20:06 -070026#include "base/iteration_range.h"
27
28namespace art {
29
30template<typename T>
31class LengthPrefixedArray {
32 public:
Vladimir Markocf36d492015-08-12 19:27:26 +010033 explicit LengthPrefixedArray(size_t length)
34 : length_(dchecked_integral_cast<uint32_t>(length)) {}
Mathieu Chartier54d220e2015-07-30 16:20:06 -070035
Vladimir Markocf36d492015-08-12 19:27:26 +010036 T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
Mathieu Chartier54d220e2015-07-30 16:20:06 -070037 DCHECK_LT(index, length_);
Vladimir Markocf36d492015-08-12 19:27:26 +010038 return AtUnchecked(index, element_size, alignment);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070039 }
40
Vladimir Markocf36d492015-08-12 19:27:26 +010041 StrideIterator<T> Begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
42 return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070043 }
44
Vladimir Markocf36d492015-08-12 19:27:26 +010045 StrideIterator<T> End(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
46 return StrideIterator<T>(&AtUnchecked(length_, element_size, alignment), element_size);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070047 }
48
Vladimir Markocf36d492015-08-12 19:27:26 +010049 static size_t OffsetOfElement(size_t index,
50 size_t element_size = sizeof(T),
51 size_t alignment = alignof(T)) {
52 DCHECK_ALIGNED_PARAM(element_size, alignment);
53 return RoundUp(offsetof(LengthPrefixedArray<T>, data), alignment) + index * element_size;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070054 }
55
Vladimir Markocf36d492015-08-12 19:27:26 +010056 static size_t ComputeSize(size_t num_elements,
57 size_t element_size = sizeof(T),
58 size_t alignment = alignof(T)) {
59 size_t result = OffsetOfElement(num_elements, element_size, alignment);
60 DCHECK_ALIGNED_PARAM(result, alignment);
61 return result;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070062 }
63
64 uint64_t Length() const {
65 return length_;
66 }
67
Mathieu Chartierc0fe56a2015-08-11 13:01:23 -070068 // Update the length but does not reallocate storage.
Vladimir Markocf36d492015-08-12 19:27:26 +010069 void SetLength(size_t length) {
70 length_ = dchecked_integral_cast<uint32_t>(length);
Mathieu Chartierc0fe56a2015-08-11 13:01:23 -070071 }
72
Mathieu Chartier54d220e2015-07-30 16:20:06 -070073 private:
Vladimir Markocf36d492015-08-12 19:27:26 +010074 T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
75 return *reinterpret_cast<T*>(
76 reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
77 }
78
79 uint32_t length_;
80 uint8_t data[0];
Mathieu Chartier54d220e2015-07-30 16:20:06 -070081};
82
83// Returns empty iteration range if the array is null.
84template<typename T>
85IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
Vladimir Markocf36d492015-08-12 19:27:26 +010086 LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
Mathieu Chartier54d220e2015-07-30 16:20:06 -070087 return arr != nullptr ?
Vladimir Markocf36d492015-08-12 19:27:26 +010088 MakeIterationRange(arr->Begin(element_size, alignment), arr->End(element_size, alignment)) :
Mathieu Chartier54d220e2015-07-30 16:20:06 -070089 MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
90}
91
92} // namespace art
93
94#endif // ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_