length_prefixed_array.h revision e64300b8488716056775ecbfa2915dd1b4ce7e08
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_LENGTH_PREFIXED_ARRAY_H_
18#define ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
19
20#include <stddef.h>  // for offsetof()
21
22#include "stride_iterator.h"
23#include "base/bit_utils.h"
24#include "base/casts.h"
25#include "base/iteration_range.h"
26
27namespace art {
28
29template<typename T>
30class LengthPrefixedArray {
31 public:
32  explicit LengthPrefixedArray(size_t length)
33      : size_(dchecked_integral_cast<uint32_t>(length)) {}
34
35  T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
36    DCHECK_LT(index, size_);
37    return AtUnchecked(index, element_size, alignment);
38  }
39
40  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)) {
46    return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size);
47  }
48
49  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);
61  }
62
63  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;
68  }
69
70  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;
76  }
77
78  size_t size() const {
79    return size_;
80  }
81
82  // Update the length but does not reallocate storage.
83  void SetSize(size_t length) {
84    size_ = dchecked_integral_cast<uint32_t>(length);
85  }
86
87 private:
88  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
93  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_;
99  uint8_t data[0];
100};
101
102// Returns empty iteration range if the array is null.
103template<typename T>
104IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
105    LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
106  return arr != nullptr ?
107      MakeIterationRange(arr->begin(element_size, alignment), arr->end(element_size, alignment)) :
108      MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
109}
110
111}  // namespace art
112
113#endif  // ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
114