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