blob: 2ac158b9fd5f35c13db9d43640af7ff1d6e16783 [file] [log] [blame]
The Android Open Source Projectcbb10112009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2005 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#define LOG_TAG "Vector"
18
19#include <string.h>
20#include <stdlib.h>
21#include <stdio.h>
22
Mathias Agopianbdf73c72012-08-09 19:39:15 -070023#include <cutils/log.h>
24
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080025#include <utils/Errors.h>
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080026#include <utils/VectorImpl.h>
27
Sergio Girod2529f22015-09-23 16:22:59 +010028#include "SharedBuffer.h"
29
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080030/*****************************************************************************/
31
32
33namespace android {
34
35// ----------------------------------------------------------------------------
36
37const size_t kMinVectorCapacity = 4;
38
39static inline size_t max(size_t a, size_t b) {
40 return a>b ? a : b;
41}
42
43// ----------------------------------------------------------------------------
44
45VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
46 : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
47{
48}
49
50VectorImpl::VectorImpl(const VectorImpl& rhs)
51 : mStorage(rhs.mStorage), mCount(rhs.mCount),
52 mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
53{
54 if (mStorage) {
Mathias Agopiane79aadd2012-08-31 16:20:23 -070055 SharedBuffer::bufferFromData(mStorage)->acquire();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080056 }
57}
58
59VectorImpl::~VectorImpl()
60{
Mathias Agopianbdf73c72012-08-09 19:39:15 -070061 ALOGW_IF(mCount,
62 "[%p] subclasses of VectorImpl must call finish_vector()"
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080063 " in their destructor. Leaking %d bytes.",
64 this, (int)(mCount*mItemSize));
65 // We can't call _do_destroy() here because the vtable is already gone.
66}
67
68VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
69{
Mathias Agopianbdf73c72012-08-09 19:39:15 -070070 LOG_ALWAYS_FATAL_IF(mItemSize != rhs.mItemSize,
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080071 "Vector<> have different types (this=%p, rhs=%p)", this, &rhs);
72 if (this != &rhs) {
73 release_storage();
74 if (rhs.mCount) {
75 mStorage = rhs.mStorage;
76 mCount = rhs.mCount;
Mathias Agopiane79aadd2012-08-31 16:20:23 -070077 SharedBuffer::bufferFromData(mStorage)->acquire();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080078 } else {
79 mStorage = 0;
80 mCount = 0;
81 }
82 }
83 return *this;
84}
85
86void* VectorImpl::editArrayImpl()
87{
88 if (mStorage) {
Mathias Agopiane79aadd2012-08-31 16:20:23 -070089 SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage)->attemptEdit();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080090 if (sb == 0) {
91 sb = SharedBuffer::alloc(capacity() * mItemSize);
92 if (sb) {
93 _do_copy(sb->data(), mStorage, mCount);
94 release_storage();
95 mStorage = sb->data();
96 }
97 }
98 }
99 return mStorage;
100}
101
102size_t VectorImpl::capacity() const
103{
104 if (mStorage) {
Mathias Agopiane79aadd2012-08-31 16:20:23 -0700105 return SharedBuffer::bufferFromData(mStorage)->size() / mItemSize;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800106 }
107 return 0;
108}
109
110ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
111{
Jeff Brown9efaaa42010-06-16 01:53:36 -0700112 return insertArrayAt(vector.arrayImpl(), index, vector.size());
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800113}
114
115ssize_t VectorImpl::appendVector(const VectorImpl& vector)
116{
117 return insertVectorAt(vector, size());
118}
119
Jeff Brown9efaaa42010-06-16 01:53:36 -0700120ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
121{
122 if (index > size())
123 return BAD_INDEX;
124 void* where = _grow(index, length);
125 if (where) {
126 _do_copy(where, array, length);
127 }
128 return where ? index : (ssize_t)NO_MEMORY;
129}
130
131ssize_t VectorImpl::appendArray(const void* array, size_t length)
132{
133 return insertArrayAt(array, size(), length);
134}
135
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800136ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
137{
138 return insertAt(0, index, numItems);
139}
140
141ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems)
142{
143 if (index > size())
144 return BAD_INDEX;
145 void* where = _grow(index, numItems);
146 if (where) {
147 if (item) {
148 _do_splat(where, item, numItems);
149 } else {
150 _do_construct(where, numItems);
151 }
152 }
153 return where ? index : (ssize_t)NO_MEMORY;
154}
155
156static int sortProxy(const void* lhs, const void* rhs, void* func)
157{
158 return (*(VectorImpl::compar_t)func)(lhs, rhs);
159}
160
161status_t VectorImpl::sort(VectorImpl::compar_t cmp)
162{
163 return sort(sortProxy, (void*)cmp);
164}
165
166status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state)
167{
168 // the sort must be stable. we're using insertion sort which
169 // is well suited for small and already sorted arrays
170 // for big arrays, it could be better to use mergesort
171 const ssize_t count = size();
172 if (count > 1) {
173 void* array = const_cast<void*>(arrayImpl());
174 void* temp = 0;
175 ssize_t i = 1;
176 while (i < count) {
177 void* item = reinterpret_cast<char*>(array) + mItemSize*(i);
178 void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
179 if (cmp(curr, item, state) > 0) {
180
181 if (!temp) {
182 // we're going to have to modify the array...
183 array = editArrayImpl();
184 if (!array) return NO_MEMORY;
185 temp = malloc(mItemSize);
186 if (!temp) return NO_MEMORY;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800187 item = reinterpret_cast<char*>(array) + mItemSize*(i);
188 curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
Mathias Agopian15d0edc2010-03-29 13:45:18 -0700189 } else {
190 _do_destroy(temp, 1);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800191 }
192
193 _do_copy(temp, item, 1);
194
195 ssize_t j = i-1;
196 void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
197 do {
Mathias Agopian15d0edc2010-03-29 13:45:18 -0700198 _do_destroy(next, 1);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800199 _do_copy(next, curr, 1);
200 next = curr;
201 --j;
Nick Kralevichc76698f2015-08-28 06:40:23 -0700202 curr = NULL;
203 if (j >= 0) {
204 curr = reinterpret_cast<char*>(array) + mItemSize*(j);
205 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800206 } while (j>=0 && (cmp(curr, temp, state) > 0));
207
Mathias Agopian15d0edc2010-03-29 13:45:18 -0700208 _do_destroy(next, 1);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800209 _do_copy(next, temp, 1);
210 }
211 i++;
212 }
213
214 if (temp) {
215 _do_destroy(temp, 1);
216 free(temp);
217 }
218 }
219 return NO_ERROR;
220}
221
222void VectorImpl::pop()
223{
224 if (size())
225 removeItemsAt(size()-1, 1);
226}
227
228void VectorImpl::push()
229{
230 push(0);
231}
232
233void VectorImpl::push(const void* item)
234{
235 insertAt(item, size());
236}
237
238ssize_t VectorImpl::add()
239{
240 return add(0);
241}
242
Jeff Brown9efaaa42010-06-16 01:53:36 -0700243ssize_t VectorImpl::add(const void* item)
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800244{
Jeff Brown9efaaa42010-06-16 01:53:36 -0700245 return insertAt(item, size());
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800246}
247
248ssize_t VectorImpl::replaceAt(size_t index)
249{
250 return replaceAt(0, index);
251}
252
253ssize_t VectorImpl::replaceAt(const void* prototype, size_t index)
254{
Steve Blockae074452012-01-09 18:35:44 +0000255 ALOG_ASSERT(index<size(),
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800256 "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
257
Mathias Agopianbdf73c72012-08-09 19:39:15 -0700258 if (index >= size()) {
259 return BAD_INDEX;
260 }
261
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800262 void* item = editItemLocation(index);
Jeff Brownbbbd7612011-07-14 00:29:49 -0700263 if (item != prototype) {
264 if (item == 0)
265 return NO_MEMORY;
266 _do_destroy(item, 1);
267 if (prototype == 0) {
268 _do_construct(item, 1);
269 } else {
270 _do_copy(item, prototype, 1);
271 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800272 }
273 return ssize_t(index);
274}
275
276ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
277{
Steve Blockae074452012-01-09 18:35:44 +0000278 ALOG_ASSERT((index+count)<=size(),
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800279 "[%p] remove: index=%d, count=%d, size=%d",
280 this, (int)index, (int)count, (int)size());
281
282 if ((index+count) > size())
283 return BAD_VALUE;
284 _shrink(index, count);
285 return index;
286}
287
288void VectorImpl::finish_vector()
289{
290 release_storage();
291 mStorage = 0;
292 mCount = 0;
293}
294
295void VectorImpl::clear()
296{
297 _shrink(0, mCount);
298}
299
300void* VectorImpl::editItemLocation(size_t index)
301{
Steve Blockae074452012-01-09 18:35:44 +0000302 ALOG_ASSERT(index<capacity(),
Mathias Agopian266a7d62011-07-11 16:26:18 -0700303 "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800304 this, (int)index, (int)capacity(), (int)mCount);
Mathias Agopianbdf73c72012-08-09 19:39:15 -0700305
306 if (index < capacity()) {
307 void* buffer = editArrayImpl();
308 if (buffer) {
309 return reinterpret_cast<char*>(buffer) + index*mItemSize;
310 }
311 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800312 return 0;
313}
314
315const void* VectorImpl::itemLocation(size_t index) const
316{
Steve Blockae074452012-01-09 18:35:44 +0000317 ALOG_ASSERT(index<capacity(),
Mathias Agopian266a7d62011-07-11 16:26:18 -0700318 "[%p] itemLocation: index=%d, capacity=%d, count=%d",
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800319 this, (int)index, (int)capacity(), (int)mCount);
320
Mathias Agopianbdf73c72012-08-09 19:39:15 -0700321 if (index < capacity()) {
322 const void* buffer = arrayImpl();
323 if (buffer) {
324 return reinterpret_cast<const char*>(buffer) + index*mItemSize;
325 }
326 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800327 return 0;
328}
329
330ssize_t VectorImpl::setCapacity(size_t new_capacity)
331{
332 size_t current_capacity = capacity();
333 ssize_t amount = new_capacity - size();
334 if (amount <= 0) {
335 // we can't reduce the capacity
336 return current_capacity;
337 }
338 SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
339 if (sb) {
340 void* array = sb->data();
341 _do_copy(array, mStorage, size());
342 release_storage();
343 mStorage = const_cast<void*>(array);
344 } else {
345 return NO_MEMORY;
346 }
347 return new_capacity;
348}
349
Jesse Hallb73559d2013-03-11 10:16:48 -0700350ssize_t VectorImpl::resize(size_t size) {
351 ssize_t result = NO_ERROR;
352 if (size > mCount) {
353 result = insertAt(mCount, size - mCount);
354 } else if (size < mCount) {
355 result = removeItemsAt(size, mCount - size);
356 }
357 return result < 0 ? result : size;
358}
359
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800360void VectorImpl::release_storage()
361{
362 if (mStorage) {
Mathias Agopiane79aadd2012-08-31 16:20:23 -0700363 const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800364 if (sb->release(SharedBuffer::eKeepStorage) == 1) {
365 _do_destroy(mStorage, mCount);
366 SharedBuffer::dealloc(sb);
367 }
368 }
369}
370
371void* VectorImpl::_grow(size_t where, size_t amount)
372{
Steve Blockb37fbe92011-10-20 11:56:00 +0100373// ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800374// this, (int)where, (int)amount, (int)mCount, (int)capacity());
375
Steve Blockae074452012-01-09 18:35:44 +0000376 ALOG_ASSERT(where <= mCount,
Jeff Brownaa5daed2011-07-13 22:22:02 -0700377 "[%p] _grow: where=%d, amount=%d, count=%d",
378 this, (int)where, (int)amount, (int)mCount); // caller already checked
379
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800380 const size_t new_size = mCount + amount;
381 if (capacity() < new_size) {
382 const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2);
Steve Blockb37fbe92011-10-20 11:56:00 +0100383// ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800384 if ((mStorage) &&
385 (mCount==where) &&
386 (mFlags & HAS_TRIVIAL_COPY) &&
387 (mFlags & HAS_TRIVIAL_DTOR))
388 {
Mathias Agopiane79aadd2012-08-31 16:20:23 -0700389 const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800390 SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
Shuo Gaoeb0eb4f2013-10-17 11:36:11 +0800391 if (sb) {
392 mStorage = sb->data();
393 } else {
394 return NULL;
395 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800396 } else {
397 SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
398 if (sb) {
399 void* array = sb->data();
Jeff Brownbbbd7612011-07-14 00:29:49 -0700400 if (where != 0) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800401 _do_copy(array, mStorage, where);
402 }
Jeff Brownbbbd7612011-07-14 00:29:49 -0700403 if (where != mCount) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800404 const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
405 void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
406 _do_copy(dest, from, mCount-where);
407 }
408 release_storage();
409 mStorage = const_cast<void*>(array);
Shuo Gaoeb0eb4f2013-10-17 11:36:11 +0800410 } else {
411 return NULL;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800412 }
413 }
414 } else {
Mathias Agopian03b168a2012-05-17 16:52:21 -0700415 void* array = editArrayImpl();
Jeff Brownbbbd7612011-07-14 00:29:49 -0700416 if (where != mCount) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800417 const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
Jeff Brownbbbd7612011-07-14 00:29:49 -0700418 void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
419 _do_move_forward(to, from, mCount - where);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800420 }
421 }
Jeff Brownbbbd7612011-07-14 00:29:49 -0700422 mCount = new_size;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800423 void* free_space = const_cast<void*>(itemLocation(where));
424 return free_space;
425}
426
427void VectorImpl::_shrink(size_t where, size_t amount)
428{
429 if (!mStorage)
430 return;
431
Steve Blockb37fbe92011-10-20 11:56:00 +0100432// ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800433// this, (int)where, (int)amount, (int)mCount, (int)capacity());
434
Steve Blockae074452012-01-09 18:35:44 +0000435 ALOG_ASSERT(where + amount <= mCount,
Jeff Brownaa5daed2011-07-13 22:22:02 -0700436 "[%p] _shrink: where=%d, amount=%d, count=%d",
437 this, (int)where, (int)amount, (int)mCount); // caller already checked
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800438
439 const size_t new_size = mCount - amount;
440 if (new_size*3 < capacity()) {
441 const size_t new_capacity = max(kMinVectorCapacity, new_size*2);
Steve Blockb37fbe92011-10-20 11:56:00 +0100442// ALOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
Jeff Brownbbbd7612011-07-14 00:29:49 -0700443 if ((where == new_size) &&
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800444 (mFlags & HAS_TRIVIAL_COPY) &&
445 (mFlags & HAS_TRIVIAL_DTOR))
446 {
Mathias Agopiane79aadd2012-08-31 16:20:23 -0700447 const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800448 SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
Shuo Gaoeb0eb4f2013-10-17 11:36:11 +0800449 if (sb) {
450 mStorage = sb->data();
451 } else {
452 return;
453 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800454 } else {
455 SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
456 if (sb) {
457 void* array = sb->data();
Jeff Brownbbbd7612011-07-14 00:29:49 -0700458 if (where != 0) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800459 _do_copy(array, mStorage, where);
460 }
Jeff Brownbbbd7612011-07-14 00:29:49 -0700461 if (where != new_size) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800462 const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
463 void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
Jeff Brownbbbd7612011-07-14 00:29:49 -0700464 _do_copy(dest, from, new_size - where);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800465 }
466 release_storage();
467 mStorage = const_cast<void*>(array);
Shuo Gaoeb0eb4f2013-10-17 11:36:11 +0800468 } else{
469 return;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800470 }
471 }
472 } else {
Jeff Brownbbbd7612011-07-14 00:29:49 -0700473 void* array = editArrayImpl();
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800474 void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
475 _do_destroy(to, amount);
Jeff Brownbbbd7612011-07-14 00:29:49 -0700476 if (where != new_size) {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800477 const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
Jeff Brownbbbd7612011-07-14 00:29:49 -0700478 _do_move_backward(to, from, new_size - where);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800479 }
480 }
Jeff Brownbbbd7612011-07-14 00:29:49 -0700481 mCount = new_size;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800482}
483
484size_t VectorImpl::itemSize() const {
485 return mItemSize;
486}
487
488void VectorImpl::_do_construct(void* storage, size_t num) const
489{
490 if (!(mFlags & HAS_TRIVIAL_CTOR)) {
491 do_construct(storage, num);
492 }
493}
494
495void VectorImpl::_do_destroy(void* storage, size_t num) const
496{
497 if (!(mFlags & HAS_TRIVIAL_DTOR)) {
498 do_destroy(storage, num);
499 }
500}
501
502void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const
503{
504 if (!(mFlags & HAS_TRIVIAL_COPY)) {
505 do_copy(dest, from, num);
506 } else {
507 memcpy(dest, from, num*itemSize());
508 }
509}
510
511void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
512 do_splat(dest, item, num);
513}
514
515void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
516 do_move_forward(dest, from, num);
517}
518
519void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
520 do_move_backward(dest, from, num);
521}
522
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800523/*****************************************************************************/
524
525SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
526 : VectorImpl(itemSize, flags)
527{
528}
529
530SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
531: VectorImpl(rhs)
532{
533}
534
535SortedVectorImpl::~SortedVectorImpl()
536{
537}
538
539SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
540{
541 return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
542}
543
544ssize_t SortedVectorImpl::indexOf(const void* item) const
545{
546 return _indexOrderOf(item);
547}
548
549size_t SortedVectorImpl::orderOf(const void* item) const
550{
551 size_t o;
552 _indexOrderOf(item, &o);
553 return o;
554}
555
556ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
557{
Nick Kralevich1f286982015-08-22 14:27:03 -0700558 if (order) *order = 0;
559 if (isEmpty()) {
560 return NAME_NOT_FOUND;
561 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800562 // binary search
563 ssize_t err = NAME_NOT_FOUND;
564 ssize_t l = 0;
565 ssize_t h = size()-1;
566 ssize_t mid;
567 const void* a = arrayImpl();
568 const size_t s = itemSize();
569 while (l <= h) {
570 mid = l + (h - l)/2;
571 const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
572 const int c = do_compare(curr, item);
573 if (c == 0) {
574 err = l = mid;
575 break;
576 } else if (c < 0) {
577 l = mid + 1;
578 } else {
579 h = mid - 1;
580 }
581 }
582 if (order) *order = l;
583 return err;
584}
585
586ssize_t SortedVectorImpl::add(const void* item)
587{
588 size_t order;
589 ssize_t index = _indexOrderOf(item, &order);
590 if (index < 0) {
591 index = VectorImpl::insertAt(item, order, 1);
592 } else {
593 index = VectorImpl::replaceAt(item, index);
594 }
595 return index;
596}
597
598ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
599{
600 // naive merge...
601 if (!vector.isEmpty()) {
602 const void* buffer = vector.arrayImpl();
603 const size_t is = itemSize();
604 size_t s = vector.size();
605 for (size_t i=0 ; i<s ; i++) {
606 ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
607 if (err<0) {
608 return err;
609 }
610 }
611 }
612 return NO_ERROR;
613}
614
615ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
616{
617 // we've merging a sorted vector... nice!
618 ssize_t err = NO_ERROR;
619 if (!vector.isEmpty()) {
620 // first take care of the case where the vectors are sorted together
621 if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
622 err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
623 } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
624 err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
625 } else {
626 // this could be made a little better
627 err = merge(static_cast<const VectorImpl&>(vector));
628 }
629 }
630 return err;
631}
632
633ssize_t SortedVectorImpl::remove(const void* item)
634{
635 ssize_t i = indexOf(item);
636 if (i>=0) {
637 VectorImpl::removeItemsAt(i, 1);
638 }
639 return i;
640}
641
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800642/*****************************************************************************/
643
644}; // namespace android
645