blob: 806026386380ec36b3eb61c9c54bf6d1dabf60c8 [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
Alex Lighte64300b2015-12-15 15:02:47 -080017#ifndef ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
18#define ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
Mathieu Chartier54d220e2015-07-30 16:20:06 -070019
20#include <stddef.h> // for offsetof()
Vladimir Markod9813cb2016-03-15 12:41:27 +000021#include <string.h> // for memset()
Mathieu Chartier54d220e2015-07-30 16:20:06 -070022
Mathieu Chartier54d220e2015-07-30 16:20:06 -070023#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)
Vladimir Marko35831e82015-09-11 11:59:18 +010034 : size_(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)) {
Vladimir Marko35831e82015-09-11 11:59:18 +010037 DCHECK_LT(index, size_);
Vladimir Markocf36d492015-08-12 19:27:26 +010038 return AtUnchecked(index, element_size, alignment);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070039 }
40
Vladimir Marko35831e82015-09-11 11:59:18 +010041 const T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) const {
42 DCHECK_LT(index, size_);
43 return AtUnchecked(index, element_size, alignment);
44 }
45
46 StrideIterator<T> begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
Vladimir Markocf36d492015-08-12 19:27:26 +010047 return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070048 }
49
Vladimir Marko35831e82015-09-11 11:59:18 +010050 StrideIterator<const T> begin(size_t element_size = sizeof(T),
51 size_t alignment = alignof(T)) const {
52 return StrideIterator<const T>(&AtUnchecked(0, element_size, alignment), element_size);
53 }
54
55 StrideIterator<T> end(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
56 return StrideIterator<T>(&AtUnchecked(size_, element_size, alignment), element_size);
57 }
58
59 StrideIterator<const T> end(size_t element_size = sizeof(T),
60 size_t alignment = alignof(T)) const {
61 return StrideIterator<const T>(&AtUnchecked(size_, element_size, alignment), element_size);
Mathieu Chartier54d220e2015-07-30 16:20:06 -070062 }
63
Vladimir Markocf36d492015-08-12 19:27:26 +010064 static size_t OffsetOfElement(size_t index,
65 size_t element_size = sizeof(T),
66 size_t alignment = alignof(T)) {
67 DCHECK_ALIGNED_PARAM(element_size, alignment);
68 return RoundUp(offsetof(LengthPrefixedArray<T>, data), alignment) + index * element_size;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070069 }
70
Vladimir Markocf36d492015-08-12 19:27:26 +010071 static size_t ComputeSize(size_t num_elements,
72 size_t element_size = sizeof(T),
73 size_t alignment = alignof(T)) {
74 size_t result = OffsetOfElement(num_elements, element_size, alignment);
75 DCHECK_ALIGNED_PARAM(result, alignment);
76 return result;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070077 }
78
Vladimir Marko35831e82015-09-11 11:59:18 +010079 size_t size() const {
80 return size_;
Mathieu Chartier54d220e2015-07-30 16:20:06 -070081 }
82
Mathieu Chartierc0fe56a2015-08-11 13:01:23 -070083 // Update the length but does not reallocate storage.
Vladimir Marko35831e82015-09-11 11:59:18 +010084 void SetSize(size_t length) {
85 size_ = dchecked_integral_cast<uint32_t>(length);
Mathieu Chartierc0fe56a2015-08-11 13:01:23 -070086 }
87
Vladimir Markod9813cb2016-03-15 12:41:27 +000088 // Clear the potentially uninitialized padding between the size_ and actual data.
89 void ClearPadding(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
90 size_t gap_offset = offsetof(LengthPrefixedArray<T>, data);
91 size_t gap_size = OffsetOfElement(0, element_size, alignment) - gap_offset;
92 memset(reinterpret_cast<uint8_t*>(this) + gap_offset, 0, gap_size);
93 }
94
Mathieu Chartier54d220e2015-07-30 16:20:06 -070095 private:
Vladimir Markocf36d492015-08-12 19:27:26 +010096 T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
97 return *reinterpret_cast<T*>(
98 reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
99 }
100
Vladimir Marko35831e82015-09-11 11:59:18 +0100101 const T& AtUnchecked(size_t index, size_t element_size, size_t alignment) const {
102 return *reinterpret_cast<T*>(
103 reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
104 }
105
106 uint32_t size_;
Vladimir Markocf36d492015-08-12 19:27:26 +0100107 uint8_t data[0];
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700108};
109
110// Returns empty iteration range if the array is null.
111template<typename T>
112IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
Vladimir Markocf36d492015-08-12 19:27:26 +0100113 LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700114 return arr != nullptr ?
Vladimir Marko35831e82015-09-11 11:59:18 +0100115 MakeIterationRange(arr->begin(element_size, alignment), arr->end(element_size, alignment)) :
Mathieu Chartier54d220e2015-07-30 16:20:06 -0700116 MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
117}
118
119} // namespace art
120
Alex Lighte64300b2015-12-15 15:02:47 -0800121#endif // ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_