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