Home | History | Annotate | Download | only in utils
      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 
     37 static inline size_t max(size_t a, size_t b) {
     38     return a>b ? a : b;
     39 }
     40 
     41 // ----------------------------------------------------------------------------
     42 
     43 VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
     44     : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
     45 {
     46 }
     47 
     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 
     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 
     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 
     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 
    101 size_t VectorImpl::capacity() const
    102 {
    103     if (mStorage) {
    104         return SharedBuffer::sharedBuffer(mStorage)->size() / mItemSize;
    105     }
    106     return 0;
    107 }
    108 
    109 ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
    110 {
    111     return insertArrayAt(vector.arrayImpl(), index, vector.size());
    112 }
    113 
    114 ssize_t VectorImpl::appendVector(const VectorImpl& vector)
    115 {
    116     return insertVectorAt(vector, size());
    117 }
    118 
    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 
    130 ssize_t VectorImpl::appendArray(const void* array, size_t length)
    131 {
    132     return insertArrayAt(array, size(), length);
    133 }
    134 
    135 ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
    136 {
    137     return insertAt(0, index, numItems);
    138 }
    139 
    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 
    155 static int sortProxy(const void* lhs, const void* rhs, void* func)
    156 {
    157     return (*(VectorImpl::compar_t)func)(lhs, rhs);
    158 }
    159 
    160 status_t VectorImpl::sort(VectorImpl::compar_t cmp)
    161 {
    162     return sort(sortProxy, (void*)cmp);
    163 }
    164 
    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 
    218 void VectorImpl::pop()
    219 {
    220     if (size())
    221         removeItemsAt(size()-1, 1);
    222 }
    223 
    224 void VectorImpl::push()
    225 {
    226     push(0);
    227 }
    228 
    229 void VectorImpl::push(const void* item)
    230 {
    231     insertAt(item, size());
    232 }
    233 
    234 ssize_t VectorImpl::add()
    235 {
    236     return add(0);
    237 }
    238 
    239 ssize_t VectorImpl::add(const void* item)
    240 {
    241     return insertAt(item, size());
    242 }
    243 
    244 ssize_t VectorImpl::replaceAt(size_t index)
    245 {
    246     return replaceAt(0, index);
    247 }
    248 
    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 
    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 
    280 void VectorImpl::finish_vector()
    281 {
    282     release_storage();
    283     mStorage = 0;
    284     mCount = 0;
    285 }
    286 
    287 void VectorImpl::clear()
    288 {
    289     _shrink(0, mCount);
    290 }
    291 
    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 
    304 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 
    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 
    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 
    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 
    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 
    448 size_t VectorImpl::itemSize() const {
    449     return mItemSize;
    450 }
    451 
    452 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 
    459 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 
    466 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 
    475 void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
    476     do_splat(dest, item, num);
    477 }
    478 
    479 void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
    480     do_move_forward(dest, from, num);
    481 }
    482 
    483 void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
    484     do_move_backward(dest, from, num);
    485 }
    486 
    487 void VectorImpl::reservedVectorImpl1() { }
    488 void VectorImpl::reservedVectorImpl2() { }
    489 void VectorImpl::reservedVectorImpl3() { }
    490 void VectorImpl::reservedVectorImpl4() { }
    491 void VectorImpl::reservedVectorImpl5() { }
    492 void VectorImpl::reservedVectorImpl6() { }
    493 void VectorImpl::reservedVectorImpl7() { }
    494 void VectorImpl::reservedVectorImpl8() { }
    495 
    496 /*****************************************************************************/
    497 
    498 SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
    499     : VectorImpl(itemSize, flags)
    500 {
    501 }
    502 
    503 SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
    504 : VectorImpl(rhs)
    505 {
    506 }
    507 
    508 SortedVectorImpl::~SortedVectorImpl()
    509 {
    510 }
    511 
    512 SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
    513 {
    514     return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
    515 }
    516 
    517 ssize_t SortedVectorImpl::indexOf(const void* item) const
    518 {
    519     return _indexOrderOf(item);
    520 }
    521 
    522 size_t SortedVectorImpl::orderOf(const void* item) const
    523 {
    524     size_t o;
    525     _indexOrderOf(item, &o);
    526     return o;
    527 }
    528 
    529 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 
    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 
    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 
    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 
    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 
    611 void SortedVectorImpl::reservedSortedVectorImpl1() { };
    612 void SortedVectorImpl::reservedSortedVectorImpl2() { };
    613 void SortedVectorImpl::reservedSortedVectorImpl3() { };
    614 void SortedVectorImpl::reservedSortedVectorImpl4() { };
    615 void SortedVectorImpl::reservedSortedVectorImpl5() { };
    616 void SortedVectorImpl::reservedSortedVectorImpl6() { };
    617 void SortedVectorImpl::reservedSortedVectorImpl7() { };
    618 void SortedVectorImpl::reservedSortedVectorImpl8() { };
    619 
    620 
    621 /*****************************************************************************/
    622 
    623 }; // namespace android
    624 
    625