• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
23 #include <utils/Log.h>
24 #include <utils/Errors.h>
25 #include <utils/SharedBuffer.h>
26 #include <utils/VectorImpl.h>
27 
28 /*****************************************************************************/
29 
30 
31 namespace android {
32 
33 // ----------------------------------------------------------------------------
34 
35 const size_t kMinVectorCapacity = 4;
36 
max(size_t a,size_t b)37 static inline size_t max(size_t a, size_t b) {
38     return a>b ? a : b;
39 }
40 
41 // ----------------------------------------------------------------------------
42 
VectorImpl(size_t itemSize,uint32_t flags)43 VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
44     : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
45 {
46 }
47 
VectorImpl(const VectorImpl & rhs)48 VectorImpl::VectorImpl(const VectorImpl& rhs)
49     :   mStorage(rhs.mStorage), mCount(rhs.mCount),
50         mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
51 {
52     if (mStorage) {
53         SharedBuffer::sharedBuffer(mStorage)->acquire();
54     }
55 }
56 
~VectorImpl()57 VectorImpl::~VectorImpl()
58 {
59     ALOG_ASSERT(!mCount,
60         "[%p] "
61         "subclasses of VectorImpl must call finish_vector()"
62         " in their destructor. Leaking %d bytes.",
63         this, (int)(mCount*mItemSize));
64     // We can't call _do_destroy() here because the vtable is already gone.
65 }
66 
operator =(const VectorImpl & rhs)67 VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
68 {
69     ALOG_ASSERT(mItemSize == rhs.mItemSize,
70         "Vector<> have different types (this=%p, rhs=%p)", this, &rhs);
71     if (this != &rhs) {
72         release_storage();
73         if (rhs.mCount) {
74             mStorage = rhs.mStorage;
75             mCount = rhs.mCount;
76             SharedBuffer::sharedBuffer(mStorage)->acquire();
77         } else {
78             mStorage = 0;
79             mCount = 0;
80         }
81     }
82     return *this;
83 }
84 
editArrayImpl()85 void* VectorImpl::editArrayImpl()
86 {
87     if (mStorage) {
88         SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage)->attemptEdit();
89         if (sb == 0) {
90             sb = SharedBuffer::alloc(capacity() * mItemSize);
91             if (sb) {
92                 _do_copy(sb->data(), mStorage, mCount);
93                 release_storage();
94                 mStorage = sb->data();
95             }
96         }
97     }
98     return mStorage;
99 }
100 
capacity() const101 size_t VectorImpl::capacity() const
102 {
103     if (mStorage) {
104         return SharedBuffer::sharedBuffer(mStorage)->size() / mItemSize;
105     }
106     return 0;
107 }
108 
insertVectorAt(const VectorImpl & vector,size_t index)109 ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
110 {
111     return insertArrayAt(vector.arrayImpl(), index, vector.size());
112 }
113 
appendVector(const VectorImpl & vector)114 ssize_t VectorImpl::appendVector(const VectorImpl& vector)
115 {
116     return insertVectorAt(vector, size());
117 }
118 
insertArrayAt(const void * array,size_t index,size_t length)119 ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
120 {
121     if (index > size())
122         return BAD_INDEX;
123     void* where = _grow(index, length);
124     if (where) {
125         _do_copy(where, array, length);
126     }
127     return where ? index : (ssize_t)NO_MEMORY;
128 }
129 
appendArray(const void * array,size_t length)130 ssize_t VectorImpl::appendArray(const void* array, size_t length)
131 {
132     return insertArrayAt(array, size(), length);
133 }
134 
insertAt(size_t index,size_t numItems)135 ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
136 {
137     return insertAt(0, index, numItems);
138 }
139 
insertAt(const void * item,size_t index,size_t numItems)140 ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems)
141 {
142     if (index > size())
143         return BAD_INDEX;
144     void* where = _grow(index, numItems);
145     if (where) {
146         if (item) {
147             _do_splat(where, item, numItems);
148         } else {
149             _do_construct(where, numItems);
150         }
151     }
152     return where ? index : (ssize_t)NO_MEMORY;
153 }
154 
sortProxy(const void * lhs,const void * rhs,void * func)155 static int sortProxy(const void* lhs, const void* rhs, void* func)
156 {
157     return (*(VectorImpl::compar_t)func)(lhs, rhs);
158 }
159 
sort(VectorImpl::compar_t cmp)160 status_t VectorImpl::sort(VectorImpl::compar_t cmp)
161 {
162     return sort(sortProxy, (void*)cmp);
163 }
164 
sort(VectorImpl::compar_r_t cmp,void * state)165 status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state)
166 {
167     // the sort must be stable. we're using insertion sort which
168     // is well suited for small and already sorted arrays
169     // for big arrays, it could be better to use mergesort
170     const ssize_t count = size();
171     if (count > 1) {
172         void* array = const_cast<void*>(arrayImpl());
173         void* temp = 0;
174         ssize_t i = 1;
175         while (i < count) {
176             void* item = reinterpret_cast<char*>(array) + mItemSize*(i);
177             void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
178             if (cmp(curr, item, state) > 0) {
179 
180                 if (!temp) {
181                     // we're going to have to modify the array...
182                     array = editArrayImpl();
183                     if (!array) return NO_MEMORY;
184                     temp = malloc(mItemSize);
185                     if (!temp) return NO_MEMORY;
186                     item = reinterpret_cast<char*>(array) + mItemSize*(i);
187                     curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
188                 } else {
189                     _do_destroy(temp, 1);
190                 }
191 
192                 _do_copy(temp, item, 1);
193 
194                 ssize_t j = i-1;
195                 void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
196                 do {
197                     _do_destroy(next, 1);
198                     _do_copy(next, curr, 1);
199                     next = curr;
200                     --j;
201                     curr = reinterpret_cast<char*>(array) + mItemSize*(j);
202                 } while (j>=0 && (cmp(curr, temp, state) > 0));
203 
204                 _do_destroy(next, 1);
205                 _do_copy(next, temp, 1);
206             }
207             i++;
208         }
209 
210         if (temp) {
211             _do_destroy(temp, 1);
212             free(temp);
213         }
214     }
215     return NO_ERROR;
216 }
217 
pop()218 void VectorImpl::pop()
219 {
220     if (size())
221         removeItemsAt(size()-1, 1);
222 }
223 
push()224 void VectorImpl::push()
225 {
226     push(0);
227 }
228 
push(const void * item)229 void VectorImpl::push(const void* item)
230 {
231     insertAt(item, size());
232 }
233 
add()234 ssize_t VectorImpl::add()
235 {
236     return add(0);
237 }
238 
add(const void * item)239 ssize_t VectorImpl::add(const void* item)
240 {
241     return insertAt(item, size());
242 }
243 
replaceAt(size_t index)244 ssize_t VectorImpl::replaceAt(size_t index)
245 {
246     return replaceAt(0, index);
247 }
248 
replaceAt(const void * prototype,size_t index)249 ssize_t VectorImpl::replaceAt(const void* prototype, size_t index)
250 {
251     ALOG_ASSERT(index<size(),
252         "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
253 
254     void* item = editItemLocation(index);
255     if (item != prototype) {
256         if (item == 0)
257             return NO_MEMORY;
258         _do_destroy(item, 1);
259         if (prototype == 0) {
260             _do_construct(item, 1);
261         } else {
262             _do_copy(item, prototype, 1);
263         }
264     }
265     return ssize_t(index);
266 }
267 
removeItemsAt(size_t index,size_t count)268 ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
269 {
270     ALOG_ASSERT((index+count)<=size(),
271         "[%p] remove: index=%d, count=%d, size=%d",
272                this, (int)index, (int)count, (int)size());
273 
274     if ((index+count) > size())
275         return BAD_VALUE;
276    _shrink(index, count);
277    return index;
278 }
279 
finish_vector()280 void VectorImpl::finish_vector()
281 {
282     release_storage();
283     mStorage = 0;
284     mCount = 0;
285 }
286 
clear()287 void VectorImpl::clear()
288 {
289     _shrink(0, mCount);
290 }
291 
editItemLocation(size_t index)292 void* VectorImpl::editItemLocation(size_t index)
293 {
294     ALOG_ASSERT(index<capacity(),
295         "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
296         this, (int)index, (int)capacity(), (int)mCount);
297 
298     void* buffer = editArrayImpl();
299     if (buffer)
300         return reinterpret_cast<char*>(buffer) + index*mItemSize;
301     return 0;
302 }
303 
itemLocation(size_t index) const304 const void* VectorImpl::itemLocation(size_t index) const
305 {
306     ALOG_ASSERT(index<capacity(),
307         "[%p] itemLocation: index=%d, capacity=%d, count=%d",
308         this, (int)index, (int)capacity(), (int)mCount);
309 
310     const  void* buffer = arrayImpl();
311     if (buffer)
312         return reinterpret_cast<const char*>(buffer) + index*mItemSize;
313     return 0;
314 }
315 
setCapacity(size_t new_capacity)316 ssize_t VectorImpl::setCapacity(size_t new_capacity)
317 {
318     size_t current_capacity = capacity();
319     ssize_t amount = new_capacity - size();
320     if (amount <= 0) {
321         // we can't reduce the capacity
322         return current_capacity;
323     }
324     SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
325     if (sb) {
326         void* array = sb->data();
327         _do_copy(array, mStorage, size());
328         release_storage();
329         mStorage = const_cast<void*>(array);
330     } else {
331         return NO_MEMORY;
332     }
333     return new_capacity;
334 }
335 
release_storage()336 void VectorImpl::release_storage()
337 {
338     if (mStorage) {
339         const SharedBuffer* sb = SharedBuffer::sharedBuffer(mStorage);
340         if (sb->release(SharedBuffer::eKeepStorage) == 1) {
341             _do_destroy(mStorage, mCount);
342             SharedBuffer::dealloc(sb);
343         }
344     }
345 }
346 
_grow(size_t where,size_t amount)347 void* VectorImpl::_grow(size_t where, size_t amount)
348 {
349 //    ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
350 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
351 
352     ALOG_ASSERT(where <= mCount,
353             "[%p] _grow: where=%d, amount=%d, count=%d",
354             this, (int)where, (int)amount, (int)mCount); // caller already checked
355 
356     const size_t new_size = mCount + amount;
357     if (capacity() < new_size) {
358         const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2);
359 //        ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
360         if ((mStorage) &&
361             (mCount==where) &&
362             (mFlags & HAS_TRIVIAL_COPY) &&
363             (mFlags & HAS_TRIVIAL_DTOR))
364         {
365             const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
366             SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
367             mStorage = sb->data();
368         } else {
369             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
370             if (sb) {
371                 void* array = sb->data();
372                 if (where != 0) {
373                     _do_copy(array, mStorage, where);
374                 }
375                 if (where != mCount) {
376                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
377                     void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
378                     _do_copy(dest, from, mCount-where);
379                 }
380                 release_storage();
381                 mStorage = const_cast<void*>(array);
382             }
383         }
384     } else {
385         void* array = editArrayImpl();
386         if (where != mCount) {
387             const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
388             void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
389             _do_move_forward(to, from, mCount - where);
390         }
391     }
392     mCount = new_size;
393     void* free_space = const_cast<void*>(itemLocation(where));
394     return free_space;
395 }
396 
_shrink(size_t where,size_t amount)397 void VectorImpl::_shrink(size_t where, size_t amount)
398 {
399     if (!mStorage)
400         return;
401 
402 //    ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
403 //        this, (int)where, (int)amount, (int)mCount, (int)capacity());
404 
405     ALOG_ASSERT(where + amount <= mCount,
406             "[%p] _shrink: where=%d, amount=%d, count=%d",
407             this, (int)where, (int)amount, (int)mCount); // caller already checked
408 
409     const size_t new_size = mCount - amount;
410     if (new_size*3 < capacity()) {
411         const size_t new_capacity = max(kMinVectorCapacity, new_size*2);
412 //        ALOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
413         if ((where == new_size) &&
414             (mFlags & HAS_TRIVIAL_COPY) &&
415             (mFlags & HAS_TRIVIAL_DTOR))
416         {
417             const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(mStorage);
418             SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
419             mStorage = sb->data();
420         } else {
421             SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
422             if (sb) {
423                 void* array = sb->data();
424                 if (where != 0) {
425                     _do_copy(array, mStorage, where);
426                 }
427                 if (where != new_size) {
428                     const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
429                     void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
430                     _do_copy(dest, from, new_size - where);
431                 }
432                 release_storage();
433                 mStorage = const_cast<void*>(array);
434             }
435         }
436     } else {
437         void* array = editArrayImpl();
438         void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
439         _do_destroy(to, amount);
440         if (where != new_size) {
441             const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
442             _do_move_backward(to, from, new_size - where);
443         }
444     }
445     mCount = new_size;
446 }
447 
itemSize() const448 size_t VectorImpl::itemSize() const {
449     return mItemSize;
450 }
451 
_do_construct(void * storage,size_t num) const452 void VectorImpl::_do_construct(void* storage, size_t num) const
453 {
454     if (!(mFlags & HAS_TRIVIAL_CTOR)) {
455         do_construct(storage, num);
456     }
457 }
458 
_do_destroy(void * storage,size_t num) const459 void VectorImpl::_do_destroy(void* storage, size_t num) const
460 {
461     if (!(mFlags & HAS_TRIVIAL_DTOR)) {
462         do_destroy(storage, num);
463     }
464 }
465 
_do_copy(void * dest,const void * from,size_t num) const466 void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const
467 {
468     if (!(mFlags & HAS_TRIVIAL_COPY)) {
469         do_copy(dest, from, num);
470     } else {
471         memcpy(dest, from, num*itemSize());
472     }
473 }
474 
_do_splat(void * dest,const void * item,size_t num) const475 void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
476     do_splat(dest, item, num);
477 }
478 
_do_move_forward(void * dest,const void * from,size_t num) const479 void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
480     do_move_forward(dest, from, num);
481 }
482 
_do_move_backward(void * dest,const void * from,size_t num) const483 void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
484     do_move_backward(dest, from, num);
485 }
486 
reservedVectorImpl1()487 void VectorImpl::reservedVectorImpl1() { }
reservedVectorImpl2()488 void VectorImpl::reservedVectorImpl2() { }
reservedVectorImpl3()489 void VectorImpl::reservedVectorImpl3() { }
reservedVectorImpl4()490 void VectorImpl::reservedVectorImpl4() { }
reservedVectorImpl5()491 void VectorImpl::reservedVectorImpl5() { }
reservedVectorImpl6()492 void VectorImpl::reservedVectorImpl6() { }
reservedVectorImpl7()493 void VectorImpl::reservedVectorImpl7() { }
reservedVectorImpl8()494 void VectorImpl::reservedVectorImpl8() { }
495 
496 /*****************************************************************************/
497 
SortedVectorImpl(size_t itemSize,uint32_t flags)498 SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
499     : VectorImpl(itemSize, flags)
500 {
501 }
502 
SortedVectorImpl(const VectorImpl & rhs)503 SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
504 : VectorImpl(rhs)
505 {
506 }
507 
~SortedVectorImpl()508 SortedVectorImpl::~SortedVectorImpl()
509 {
510 }
511 
operator =(const SortedVectorImpl & rhs)512 SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
513 {
514     return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
515 }
516 
indexOf(const void * item) const517 ssize_t SortedVectorImpl::indexOf(const void* item) const
518 {
519     return _indexOrderOf(item);
520 }
521 
orderOf(const void * item) const522 size_t SortedVectorImpl::orderOf(const void* item) const
523 {
524     size_t o;
525     _indexOrderOf(item, &o);
526     return o;
527 }
528 
_indexOrderOf(const void * item,size_t * order) const529 ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
530 {
531     // binary search
532     ssize_t err = NAME_NOT_FOUND;
533     ssize_t l = 0;
534     ssize_t h = size()-1;
535     ssize_t mid;
536     const void* a = arrayImpl();
537     const size_t s = itemSize();
538     while (l <= h) {
539         mid = l + (h - l)/2;
540         const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
541         const int c = do_compare(curr, item);
542         if (c == 0) {
543             err = l = mid;
544             break;
545         } else if (c < 0) {
546             l = mid + 1;
547         } else {
548             h = mid - 1;
549         }
550     }
551     if (order) *order = l;
552     return err;
553 }
554 
add(const void * item)555 ssize_t SortedVectorImpl::add(const void* item)
556 {
557     size_t order;
558     ssize_t index = _indexOrderOf(item, &order);
559     if (index < 0) {
560         index = VectorImpl::insertAt(item, order, 1);
561     } else {
562         index = VectorImpl::replaceAt(item, index);
563     }
564     return index;
565 }
566 
merge(const VectorImpl & vector)567 ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
568 {
569     // naive merge...
570     if (!vector.isEmpty()) {
571         const void* buffer = vector.arrayImpl();
572         const size_t is = itemSize();
573         size_t s = vector.size();
574         for (size_t i=0 ; i<s ; i++) {
575             ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
576             if (err<0) {
577                 return err;
578             }
579         }
580     }
581     return NO_ERROR;
582 }
583 
merge(const SortedVectorImpl & vector)584 ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
585 {
586     // we've merging a sorted vector... nice!
587     ssize_t err = NO_ERROR;
588     if (!vector.isEmpty()) {
589         // first take care of the case where the vectors are sorted together
590         if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
591             err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
592         } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
593             err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
594         } else {
595             // this could be made a little better
596             err = merge(static_cast<const VectorImpl&>(vector));
597         }
598     }
599     return err;
600 }
601 
remove(const void * item)602 ssize_t SortedVectorImpl::remove(const void* item)
603 {
604     ssize_t i = indexOf(item);
605     if (i>=0) {
606         VectorImpl::removeItemsAt(i, 1);
607     }
608     return i;
609 }
610 
reservedSortedVectorImpl1()611 void SortedVectorImpl::reservedSortedVectorImpl1() { };
reservedSortedVectorImpl2()612 void SortedVectorImpl::reservedSortedVectorImpl2() { };
reservedSortedVectorImpl3()613 void SortedVectorImpl::reservedSortedVectorImpl3() { };
reservedSortedVectorImpl4()614 void SortedVectorImpl::reservedSortedVectorImpl4() { };
reservedSortedVectorImpl5()615 void SortedVectorImpl::reservedSortedVectorImpl5() { };
reservedSortedVectorImpl6()616 void SortedVectorImpl::reservedSortedVectorImpl6() { };
reservedSortedVectorImpl7()617 void SortedVectorImpl::reservedSortedVectorImpl7() { };
reservedSortedVectorImpl8()618 void SortedVectorImpl::reservedSortedVectorImpl8() { };
619 
620 
621 /*****************************************************************************/
622 
623 }; // namespace android
624 
625