blob: e01b6ccd2691a818fb071292d41980795b0d0b04 [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
Mathieu Chartier54d220e2015-07-30 16:20:06 -070022#include "stride_iterator.h"
Vladimir Markocf36d492015-08-12 19:27:26 +010023#include "base/bit_utils.h"
24#include "base/casts.h"
Mathieu Chartier54d220e2015-07-30 16:20:06 -070025#include "base/iteration_range.h"
26
27namespace art {
28
29template<typename T>
30class LengthPrefixedArray {
31 public:
Vladimir Markocf36d492015-08-12 19:27:26 +010032 explicit LengthPrefixedArray(size_t length)
Vladimir Marko35831e82015-09-11 11:59:18 +010033 : size_(dchecked_integral_cast<uint32_t>(length)) {}
Mathieu Chartier54d220e2015-07-30 16:20:06 -070034
Vladimir Markocf36d492015-08-12 19:27:26 +010035 T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
Vladimir Marko35831e82015-09-11 11:59:18 +010036 DCHECK_LT(index, size_);
Vladimir Markocf36d492015-08-12 19:27:26 +010037 return AtUnchecked(index, element_size, alignment);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070038 }
39
Vladimir Marko35831e82015-09-11 11:59:18 +010040 const T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) const {
41 DCHECK_LT(index, size_);
42 return AtUnchecked(index, element_size, alignment);
43 }
44
45 StrideIterator<T> begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
Vladimir Markocf36d492015-08-12 19:27:26 +010046 return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070047 }
48
Vladimir Marko35831e82015-09-11 11:59:18 +010049 StrideIterator<const T> begin(size_t element_size = sizeof(T),
50 size_t alignment = alignof(T)) const {
51 return StrideIterator<const T>(&AtUnchecked(0, element_size, alignment), element_size);
52 }
53
54 StrideIterator<T> end(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
55 return StrideIterator<T>(&AtUnchecked(size_, element_size, alignment), element_size);
56 }
57
58 StrideIterator<const T> end(size_t element_size = sizeof(T),
59 size_t alignment = alignof(T)) const {
60 return StrideIterator<const T>(&AtUnchecked(size_, element_size, alignment), element_size);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070061 }
62
Vladimir Markocf36d492015-08-12 19:27:26 +010063 static size_t OffsetOfElement(size_t index,
64 size_t element_size = sizeof(T),
65 size_t alignment = alignof(T)) {
66 DCHECK_ALIGNED_PARAM(element_size, alignment);
67 return RoundUp(offsetof(LengthPrefixedArray<T>, data), alignment) + index * element_size;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070068 }
69
Vladimir Markocf36d492015-08-12 19:27:26 +010070 static size_t ComputeSize(size_t num_elements,
71 size_t element_size = sizeof(T),
72 size_t alignment = alignof(T)) {
73 size_t result = OffsetOfElement(num_elements, element_size, alignment);
74 DCHECK_ALIGNED_PARAM(result, alignment);
75 return result;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070076 }
77
Vladimir Marko35831e82015-09-11 11:59:18 +010078 size_t size() const {
79 return size_;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070080 }
81
Mathieu Chartierc0fe56a2015-08-11 13:01:23 -070082 // Update the length but does not reallocate storage.
Vladimir Marko35831e82015-09-11 11:59:18 +010083 void SetSize(size_t length) {
84 size_ = dchecked_integral_cast<uint32_t>(length);
Mathieu Chartierc0fe56a2015-08-11 13:01:23 -070085 }
86
Mathieu Chartier54d220e2015-07-30 16:20:06 -070087 private:
Vladimir Markocf36d492015-08-12 19:27:26 +010088 T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
89 return *reinterpret_cast<T*>(
90 reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
91 }
92
Vladimir Marko35831e82015-09-11 11:59:18 +010093 const T& AtUnchecked(size_t index, size_t element_size, size_t alignment) const {
94 return *reinterpret_cast<T*>(
95 reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
96 }
97
98 uint32_t size_;
Vladimir Markocf36d492015-08-12 19:27:26 +010099 uint8_t data[0];
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700100};
101
102// Returns empty iteration range if the array is null.
103template<typename T>
104IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
Vladimir Markocf36d492015-08-12 19:27:26 +0100105 LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700106 return arr != nullptr ?
Vladimir Marko35831e82015-09-11 11:59:18 +0100107 MakeIterationRange(arr->begin(element_size, alignment), arr->end(element_size, alignment)) :
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700108 MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
109}
110
111} // namespace art
112
113#endif // ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_