blob: e4b1e7d0e9277f875f36a56388059db0d60c5d0f [file] [log] [blame]
buzbee862a7602013-04-05 10:58:54 -07001/*
2 * Copyright (C) 2013 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
Nicolas Geoffray818f2102014-02-18 16:43:35 +000017#ifndef ART_COMPILER_UTILS_GROWABLE_ARRAY_H_
18#define ART_COMPILER_UTILS_GROWABLE_ARRAY_H_
buzbee862a7602013-04-05 10:58:54 -070019
20#include <stdint.h>
21#include <stddef.h>
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070022
Mathieu Chartierb666f482015-02-18 14:33:14 -080023#include "base/arena_object.h"
buzbee862a7602013-04-05 10:58:54 -070024
25namespace art {
26
Vladimir Markoe39c54e2014-09-22 14:50:02 +010027// Deprecated
28// TODO: Replace all uses with ArenaVector<T>.
buzbee862a7602013-04-05 10:58:54 -070029template<typename T>
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070030class GrowableArray : public ArenaObject<kArenaAllocGrowableArray> {
buzbee862a7602013-04-05 10:58:54 -070031 public:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070032 GrowableArray(ArenaAllocator* arena, size_t init_length)
buzbee862a7602013-04-05 10:58:54 -070033 : arena_(arena),
buzbeea5abf702013-04-12 14:39:29 -070034 num_allocated_(init_length),
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070035 num_used_(0) {
Vladimir Markoe4fcc5b2015-02-13 10:28:29 +000036 elem_list_ = arena_->AllocArray<T>(init_length, kArenaAllocGrowableArray);
Andreas Gampec8ccf682014-09-29 20:07:43 -070037 }
buzbee862a7602013-04-05 10:58:54 -070038
Nicolas Geoffray86dde162015-01-26 12:54:33 +000039 GrowableArray(ArenaAllocator* arena, size_t init_length, T initial_data)
40 : arena_(arena),
41 num_allocated_(init_length),
Nicolas Geoffray827eedb2015-01-26 15:18:36 +000042 num_used_(init_length) {
Vladimir Markoe4fcc5b2015-02-13 10:28:29 +000043 elem_list_ = arena_->AllocArray<T>(init_length, kArenaAllocGrowableArray);
Nicolas Geoffray86dde162015-01-26 12:54:33 +000044 for (size_t i = 0; i < init_length; ++i) {
45 elem_list_[i] = initial_data;
46 }
47 }
48
David Brazdil2d7352b2015-04-20 14:52:42 +010049 bool Contains(T value) const {
50 for (size_t i = 0; i < num_used_; ++i) {
51 if (elem_list_[i] == value) {
52 return true;
53 }
54 }
55 return false;
56 }
buzbee862a7602013-04-05 10:58:54 -070057
58 // Expand the list size to at least new length.
59 void Resize(size_t new_length) {
60 if (new_length <= num_allocated_) return;
buzbeea5abf702013-04-12 14:39:29 -070061 // If it's a small list double the size, else grow 1.5x.
62 size_t target_length =
63 (num_allocated_ < 128) ? num_allocated_ << 1 : num_allocated_ + (num_allocated_ >> 1);
buzbee862a7602013-04-05 10:58:54 -070064 if (new_length > target_length) {
65 target_length = new_length;
66 }
Vladimir Markoe4fcc5b2015-02-13 10:28:29 +000067 T* new_array = arena_->AllocArray<T>(target_length, kArenaAllocGrowableArray);
buzbee862a7602013-04-05 10:58:54 -070068 memcpy(new_array, elem_list_, sizeof(T) * num_allocated_);
buzbee862a7602013-04-05 10:58:54 -070069 num_allocated_ = target_length;
70 elem_list_ = new_array;
Andreas Gampec8ccf682014-09-29 20:07:43 -070071 }
buzbee862a7602013-04-05 10:58:54 -070072
73 // NOTE: does not return storage, just resets use count.
74 void Reset() {
75 num_used_ = 0;
76 }
77
78 // Insert an element to the end of a list, resizing if necessary.
79 void Insert(T elem) {
80 if (num_used_ == num_allocated_) {
81 Resize(num_used_ + 1);
82 }
83 elem_list_[num_used_++] = elem;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000084 }
85
86 void InsertAt(size_t index, T elem) {
87 DCHECK(index <= Size());
88 Insert(elem);
89 for (size_t i = Size() - 1; i > index; --i) {
90 elem_list_[i] = elem_list_[i - 1];
91 }
92 elem_list_[index] = elem;
93 }
94
95 void Add(T elem) {
96 Insert(elem);
97 }
buzbee862a7602013-04-05 10:58:54 -070098
99 T Get(size_t index) const {
100 DCHECK_LT(index, num_used_);
101 return elem_list_[index];
Andreas Gampec8ccf682014-09-29 20:07:43 -0700102 }
buzbee862a7602013-04-05 10:58:54 -0700103
104 // Overwrite existing element at position index. List must be large enough.
105 void Put(size_t index, T elem) {
106 DCHECK_LT(index, num_used_);
107 elem_list_[index] = elem;
108 }
109
110 void Increment(size_t index) {
111 DCHECK_LT(index, num_used_);
112 elem_list_[index]++;
113 }
114
buzbeebd663de2013-09-10 15:41:31 -0700115 /*
116 * Remove an existing element from list. If there are more than one copy
117 * of the element, only the first one encountered will be deleted.
118 */
119 // TODO: consider renaming this.
buzbee862a7602013-04-05 10:58:54 -0700120 void Delete(T element) {
121 bool found = false;
122 for (size_t i = 0; i < num_used_ - 1; i++) {
123 if (!found && elem_list_[i] == element) {
124 found = true;
125 }
126 if (found) {
127 elem_list_[i] = elem_list_[i+1];
128 }
129 }
130 // We should either have found the element, or it was the last (unscanned) element.
131 DCHECK(found || (element == elem_list_[num_used_ - 1]));
132 num_used_--;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700133 }
buzbee862a7602013-04-05 10:58:54 -0700134
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100135 void DeleteAt(size_t index) {
136 for (size_t i = index; i < num_used_ - 1; i++) {
137 elem_list_[i] = elem_list_[i + 1];
138 }
139 num_used_--;
Andreas Gampec8ccf682014-09-29 20:07:43 -0700140 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100141
buzbee862a7602013-04-05 10:58:54 -0700142 size_t GetNumAllocated() const { return num_allocated_; }
143
144 size_t Size() const { return num_used_; }
145
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000146 bool IsEmpty() const { return num_used_ == 0; }
147
148 T Pop() {
149 DCHECK_GE(num_used_, (size_t)0);
150 return elem_list_[--num_used_];
151 }
152
153 T Peek() const {
154 DCHECK_GE(num_used_, (size_t)0);
155 return elem_list_[num_used_ - 1];
156 }
157
buzbeebd663de2013-09-10 15:41:31 -0700158 void SetSize(size_t new_size) {
159 Resize(new_size);
160 num_used_ = new_size;
161 }
162
buzbee862a7602013-04-05 10:58:54 -0700163 T* GetRawStorage() const { return elem_list_; }
164
buzbee862a7602013-04-05 10:58:54 -0700165 private:
166 ArenaAllocator* const arena_;
167 size_t num_allocated_;
168 size_t num_used_;
buzbee862a7602013-04-05 10:58:54 -0700169 T* elem_list_;
170};
171
172} // namespace art
173
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000174#endif // ART_COMPILER_UTILS_GROWABLE_ARRAY_H_