1/*
2 * Copyright (C) 2016 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 CHRE_UTIL_FIXED_SIZE_VECTOR_IMPL_H_
18#define CHRE_UTIL_FIXED_SIZE_VECTOR_IMPL_H_
19
20#include <new>
21
22#include "chre/util/container_support.h"
23#include "chre/util/memory.h"
24
25namespace chre {
26
27template<typename ElementType, size_t kCapacity>
28FixedSizeVector<ElementType, kCapacity>::~FixedSizeVector() {
29  destroy(data(), size());
30}
31
32template<typename ElementType, size_t kCapacity>
33ElementType& FixedSizeVector<ElementType, kCapacity>::back() {
34  CHRE_ASSERT(mSize > 0);
35  return data()[mSize - 1];
36}
37
38template<typename ElementType, size_t kCapacity>
39const ElementType& FixedSizeVector<ElementType, kCapacity>::back() const {
40  CHRE_ASSERT(mSize > 0);
41  return data()[mSize - 1];
42}
43
44template<typename ElementType, size_t kCapacity>
45ElementType& FixedSizeVector<ElementType, kCapacity>::front() {
46  CHRE_ASSERT(mSize > 0);
47  return data()[0];
48}
49
50template<typename ElementType, size_t kCapacity>
51const ElementType& FixedSizeVector<ElementType, kCapacity>::front() const {
52  CHRE_ASSERT(mSize > 0);
53  return data()[0];
54}
55
56template<typename ElementType, size_t kCapacity>
57ElementType *FixedSizeVector<ElementType, kCapacity>::data() {
58  return reinterpret_cast<ElementType *>(mData);
59}
60
61template<typename ElementType, size_t kCapacity>
62const ElementType *FixedSizeVector<ElementType, kCapacity>::data() const {
63  return reinterpret_cast<const ElementType *>(mData);
64}
65
66template<typename ElementType, size_t kCapacity>
67size_t FixedSizeVector<ElementType, kCapacity>::size() const {
68  return mSize;
69}
70
71template<typename ElementType, size_t kCapacity>
72size_t FixedSizeVector<ElementType, kCapacity>::capacity() const {
73  return kCapacity;
74}
75
76template<typename ElementType, size_t kCapacity>
77bool FixedSizeVector<ElementType, kCapacity>::empty() const {
78  return (mSize == 0);
79}
80
81template<typename ElementType, size_t kCapacity>
82bool FixedSizeVector<ElementType, kCapacity>::full() const {
83  return (mSize == kCapacity);
84}
85
86template<typename ElementType, size_t kCapacity>
87void FixedSizeVector<ElementType, kCapacity>::push_back(
88    const ElementType& element) {
89  CHRE_ASSERT(!full());
90  if (!full()) {
91    new (&data()[mSize++]) ElementType(element);
92  }
93}
94
95template<typename ElementType, size_t kCapacity>
96template<typename... Args>
97void FixedSizeVector<ElementType, kCapacity>::emplace_back(Args&&... args) {
98  CHRE_ASSERT(!full());
99  if (!full()) {
100    new (&data()[mSize++]) ElementType(std::forward<Args>(args)...);
101  }
102}
103
104template<typename ElementType, size_t kCapacity>
105ElementType& FixedSizeVector<ElementType, kCapacity>::operator[](
106    size_t index) {
107  CHRE_ASSERT(index < mSize);
108  if (index >= mSize) {
109    index = mSize - 1;
110  }
111
112  return data()[index];
113}
114
115template<typename ElementType, size_t kCapacity>
116const ElementType& FixedSizeVector<ElementType, kCapacity>::operator[](
117    size_t index) const {
118  CHRE_ASSERT(index < mSize);
119  if (index >= mSize) {
120    index = mSize - 1;
121  }
122
123  return data()[index];
124}
125
126template<typename ElementType, size_t kCapacity>
127void FixedSizeVector<ElementType, kCapacity>::erase(size_t index) {
128  CHRE_ASSERT(index < mSize);
129  if (index < mSize) {
130    mSize--;
131    for (size_t i = index; i < mSize; i++) {
132      moveOrCopyAssign(data()[i], data()[i + 1]);
133    }
134
135    data()[mSize].~ElementType();
136  }
137}
138
139template<typename ElementType, size_t kCapacity>
140void FixedSizeVector<ElementType, kCapacity>::swap(size_t index0,
141                                                   size_t index1) {
142  CHRE_ASSERT(index0 < mSize && index1 < mSize);
143  if (index0 < mSize && index1 < mSize && index0 != index1) {
144    typename std::aligned_storage<sizeof(ElementType),
145        alignof(ElementType)>::type tempStorage;
146    ElementType& temp = *reinterpret_cast<ElementType *>(&tempStorage);
147    uninitializedMoveOrCopy(&data()[index0], 1, &temp);
148    moveOrCopyAssign(data()[index0], data()[index1]);
149    moveOrCopyAssign(data()[index1], temp);
150  }
151}
152
153template<typename ElementType, size_t kCapacity>
154typename FixedSizeVector<ElementType, kCapacity>::iterator
155    FixedSizeVector<ElementType, kCapacity>::begin() {
156  return data();
157}
158
159template<typename ElementType, size_t kCapacity>
160typename FixedSizeVector<ElementType, kCapacity>::iterator
161    FixedSizeVector<ElementType, kCapacity>::end() {
162  return (data() + mSize);
163}
164
165template<typename ElementType, size_t kCapacity>
166typename FixedSizeVector<ElementType, kCapacity>::const_iterator
167    FixedSizeVector<ElementType, kCapacity>::begin() const {
168  return cbegin();
169}
170
171template<typename ElementType, size_t kCapacity>
172typename FixedSizeVector<ElementType, kCapacity>::const_iterator
173    FixedSizeVector<ElementType, kCapacity>::end() const {
174  return cend();
175}
176
177template<typename ElementType, size_t kCapacity>
178typename FixedSizeVector<ElementType, kCapacity>::const_iterator
179    FixedSizeVector<ElementType, kCapacity>::cbegin() const {
180  return data();
181}
182
183template<typename ElementType, size_t kCapacity>
184typename FixedSizeVector<ElementType, kCapacity>::const_iterator
185    FixedSizeVector<ElementType, kCapacity>::cend() const {
186  return (data() + mSize);
187}
188
189template<typename ElementType, size_t kCapacity>
190void FixedSizeVector<ElementType, kCapacity>::resize(size_t newSize) {
191  CHRE_ASSERT(newSize <= kCapacity);
192  if (newSize > kCapacity) {
193    newSize = kCapacity;
194  }
195
196  if (newSize > size()) {
197    for (size_t i = size(); i < newSize; i++) {
198      emplace_back();
199    }
200  } else {
201    for (size_t i = newSize; i < size(); i++) {
202      data()[i].~ElementType();
203    }
204
205    mSize = newSize;
206  }
207}
208
209}  // namespace chre
210
211#endif  // CHRE_UTIL_FIXED_SIZE_VECTOR_IMPL_H_
212