OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 T* buffer() { return m_buffer; } | 304 T* buffer() { return m_buffer; } |
305 const T* buffer() const { return m_buffer; } | 305 const T* buffer() const { return m_buffer; } |
306 size_t capacity() const { return m_capacity; } | 306 size_t capacity() const { return m_capacity; } |
307 | 307 |
308 void clearUnusedSlots(T* from, T* to) | 308 void clearUnusedSlots(T* from, T* to) |
309 { | 309 { |
310 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value), T>::clear(f rom, to); | 310 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value), T>::clear(f rom, to); |
311 } | 311 } |
312 | 312 |
313 protected: | 313 protected: |
314 static const size_t sizeFieldSize = sizeof(unsigned) * 2 > sizeof(double ) ? sizeof(unsigned) * 2 : sizeof(double); | |
Mads Ager (chromium)
2014/07/18 11:03:14
I can't find any usages of this?
Erik Corry
2014/07/22 15:49:26
Removed.
| |
315 | |
314 VectorBufferBase() | 316 VectorBufferBase() |
315 : m_buffer(0) | 317 : m_buffer(0) |
316 , m_capacity(0) | 318 , m_capacity(0) |
317 { | 319 { |
318 } | 320 } |
319 | 321 |
320 VectorBufferBase(T* buffer, size_t capacity) | 322 VectorBufferBase(T* buffer, size_t capacity) |
321 : m_buffer(buffer) | 323 : m_buffer(buffer) |
322 , m_capacity(capacity) | 324 , m_capacity(capacity) |
323 { | 325 { |
324 } | 326 } |
325 | 327 |
328 // Ends are exclusive and if they point at the same element as their | |
329 // start then the range is empty. The end can point one above the last | |
330 // element in the capacity (this only happens for Vector, not for | |
331 // Deque). | |
332 struct Range { | |
333 Range(unsigned s = 0, unsigned e = 0) | |
334 : start(s) | |
335 , end(e) | |
336 { | |
337 } | |
338 | |
339 bool IsEmpty() { return start == end; } | |
340 | |
341 unsigned start; | |
342 unsigned end; | |
343 }; | |
344 | |
345 // Takes a range, which may wrap around at capacity and | |
346 // decomposes it into 0, 1, or 2 ranges, returning a pointer to the | |
347 // element past the last one. | |
348 Range* findRanges(Range* buffer, const Range in, unsigned capacity) | |
349 { | |
350 if (in.end > in.start) { | |
351 *buffer++ = in; | |
352 } else if (in.end < in.start) { | |
353 if (in.end) | |
354 *buffer++ = Range(0, in.end); | |
355 ASSERT(in.start != capacity); | |
356 *buffer++ = Range(in.start, capacity); | |
357 } | |
358 return buffer; | |
359 } | |
360 | |
326 T* m_buffer; | 361 T* m_buffer; |
327 unsigned m_capacity; | 362 unsigned m_capacity; |
328 unsigned m_size; | |
329 }; | 363 }; |
330 | 364 |
331 template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllo cator> | 365 template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllo cator> |
332 class VectorBuffer; | 366 class VectorBuffer; |
333 | 367 |
334 template<typename T, typename Allocator> | 368 template<typename T, typename Allocator> |
335 class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocato r> { | 369 class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocato r> { |
336 private: | 370 private: |
337 typedef VectorBufferBase<T, Allocator> Base; | 371 typedef VectorBufferBase<T, Allocator> Base; |
372 | |
373 protected: | |
374 typedef typename Base::Range Range; | |
375 | |
338 public: | 376 public: |
339 VectorBuffer() | 377 VectorBuffer() |
340 { | 378 { |
341 } | 379 } |
342 | 380 |
343 VectorBuffer(size_t capacity) | 381 VectorBuffer(size_t capacity) |
344 { | 382 { |
345 // Calling malloc(0) might take a lock and may actually do an | 383 // Calling malloc(0) might take a lock and may actually do an |
346 // allocation on some systems. | 384 // allocation on some systems. |
347 if (capacity) | 385 if (capacity) |
(...skipping 10 matching lines...) Expand all Loading... | |
358 { | 396 { |
359 Allocator::backingFree(bufferToDeallocate); | 397 Allocator::backingFree(bufferToDeallocate); |
360 } | 398 } |
361 | 399 |
362 void resetBufferPointer() | 400 void resetBufferPointer() |
363 { | 401 { |
364 m_buffer = 0; | 402 m_buffer = 0; |
365 m_capacity = 0; | 403 m_capacity = 0; |
366 } | 404 } |
367 | 405 |
368 void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other) | 406 void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other, Range, Range ) |
369 { | 407 { |
370 std::swap(m_buffer, other.m_buffer); | 408 std::swap(m_buffer, other.m_buffer); |
371 std::swap(m_capacity, other.m_capacity); | 409 std::swap(m_capacity, other.m_capacity); |
372 } | 410 } |
373 | 411 |
374 using Base::allocateBuffer; | 412 using Base::allocateBuffer; |
375 using Base::allocationSize; | 413 using Base::allocationSize; |
376 | 414 |
377 using Base::buffer; | 415 using Base::buffer; |
378 using Base::capacity; | 416 using Base::capacity; |
417 using Base::findRanges; | |
379 | 418 |
380 using Base::clearUnusedSlots; | 419 using Base::clearUnusedSlots; |
381 | 420 |
382 bool hasOutOfLineBuffer() const | 421 bool hasOutOfLineBuffer() const |
383 { | 422 { |
384 // When inlineCapacity is 0 we have an out of line buffer if we have a buffer. | 423 // When inlineCapacity is 0 we have an out of line buffer if we have a buffer. |
385 return buffer(); | 424 return buffer(); |
386 } | 425 } |
387 | 426 |
388 protected: | |
389 using Base::m_size; | |
390 | |
391 private: | 427 private: |
392 using Base::m_buffer; | 428 using Base::m_buffer; |
393 using Base::m_capacity; | 429 using Base::m_capacity; |
394 }; | 430 }; |
395 | 431 |
396 template<typename T, size_t inlineCapacity, typename Allocator> | 432 template<typename T, size_t inlineCapacity, typename Allocator> |
397 class VectorBuffer : protected VectorBufferBase<T, Allocator> { | 433 class VectorBuffer : protected VectorBufferBase<T, Allocator> { |
398 WTF_MAKE_NONCOPYABLE(VectorBuffer); | 434 WTF_MAKE_NONCOPYABLE(VectorBuffer); |
399 private: | 435 private: |
400 typedef VectorBufferBase<T, Allocator> Base; | 436 typedef VectorBufferBase<T, Allocator> Base; |
437 | |
438 protected: | |
439 typedef typename Base::Range Range; | |
440 | |
401 public: | 441 public: |
402 VectorBuffer() | 442 VectorBuffer() |
403 : Base(inlineBuffer(), inlineCapacity) | 443 : Base(inlineBuffer(), inlineCapacity) |
404 { | 444 { |
405 } | 445 } |
406 | 446 |
407 VectorBuffer(size_t capacity) | 447 VectorBuffer(size_t capacity) |
408 : Base(inlineBuffer(), inlineCapacity) | 448 : Base(inlineBuffer(), inlineCapacity) |
409 { | 449 { |
410 if (capacity > inlineCapacity) | 450 if (capacity > inlineCapacity) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 resetBufferPointer(); | 483 resetBufferPointer(); |
444 } | 484 } |
445 | 485 |
446 size_t allocationSize(size_t capacity) const | 486 size_t allocationSize(size_t capacity) const |
447 { | 487 { |
448 if (capacity <= inlineCapacity) | 488 if (capacity <= inlineCapacity) |
449 return m_inlineBufferSize; | 489 return m_inlineBufferSize; |
450 return Base::allocationSize(capacity); | 490 return Base::allocationSize(capacity); |
451 } | 491 } |
452 | 492 |
453 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other) | 493 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other, Range thisRange, Range otherRange) |
Ken Russell (switch to Gerrit)
2014/07/21 20:44:09
What are the invariants of this method? What does
Erik Corry
2014/07/22 15:49:26
There's no problem with the ranges having a differ
| |
454 { | 494 { |
455 typedef VectorTypeOperations<T> TypeOperations; | 495 typedef VectorTypeOperations<T> TypeOperations; |
456 | 496 |
457 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuff er()) { | 497 Range thisRanges[2]; |
458 ASSERT(m_capacity == other.m_capacity); | 498 Range otherRanges[2]; |
459 if (m_size > other.m_size) { | 499 Range* thisRangePtr = thisRanges; |
460 TypeOperations::swap(inlineBuffer(), inlineBuffer() + other. m_size, other.inlineBuffer()); | 500 Range* otherRangePtr = otherRanges; |
461 TypeOperations::move(inlineBuffer() + other.m_size, inlineBu ffer() + m_size, other.inlineBuffer() + other.m_size); | 501 |
502 std::swap(m_capacity, other.m_capacity); | |
503 if (buffer() != inlineBuffer() && other.buffer() != other.inlineBuff er()) { | |
504 std::swap(m_buffer, other.m_buffer); | |
505 } else { | |
Ken Russell (switch to Gerrit)
2014/07/21 20:44:09
I can't in good faith review this method. It isn't
Erik Corry
2014/07/22 15:49:26
I managed to simplify this function quite a bit, w
| |
506 T* otherBuffer = other.m_buffer; | |
507 if (buffer() == inlineBuffer()) { | |
508 thisRangePtr = findRanges(thisRanges, thisRange, inlineCapac ity); | |
462 } else { | 509 } else { |
463 TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size , other.inlineBuffer()); | 510 other.m_buffer = m_buffer; |
464 TypeOperations::move(other.inlineBuffer() + m_size, other.in lineBuffer() + other.m_size, inlineBuffer() + m_size); | 511 m_buffer = inlineBuffer(); |
465 } | 512 } |
466 } else if (buffer() == inlineBuffer()) { | 513 if (otherBuffer == other.inlineBuffer()) { |
467 m_buffer = other.m_buffer; | 514 otherRangePtr = findRanges(otherRanges, otherRange, inlineCa pacity); |
468 other.m_buffer = other.inlineBuffer(); | 515 } else { |
469 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, ot her.inlineBuffer()); | 516 m_buffer = otherBuffer; |
470 std::swap(m_capacity, other.m_capacity); | 517 other.m_buffer = other.inlineBuffer(); |
471 } else if (other.buffer() == other.inlineBuffer()) { | 518 } |
472 other.m_buffer = m_buffer; | 519 } |
473 m_buffer = inlineBuffer(); | 520 |
474 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_size, inlineBuffer()); | 521 while (thisRangePtr != thisRanges || otherRangePtr != otherRanges) { |
475 std::swap(m_capacity, other.m_capacity); | 522 if (thisRangePtr == thisRanges) { |
476 } else { | 523 // Ran out of ranges in this: process a range in the other. |
477 std::swap(m_buffer, other.m_buffer); | 524 Range otherRange = *--otherRangePtr; |
478 std::swap(m_capacity, other.m_capacity); | 525 TypeOperations::move(other.inlineBuffer() + otherRange.start , other.inlineBuffer() + otherRange.end, inlineBuffer() + otherRange.start); |
526 continue; | |
527 } | |
528 if (otherRangePtr == otherRanges) { | |
529 // Ran out of ranges in the other: process a range in this. | |
530 Range thisRange = *--thisRangePtr; | |
531 TypeOperations::move(inlineBuffer() + thisRange.start, inlin eBuffer() + thisRange.end, other.inlineBuffer() + thisRange.start); | |
532 continue; | |
533 } | |
534 // We have a rightmost range in both. Find out which extends fur thest to the right. | |
535 Range otherRange = *--otherRangePtr; | |
536 Range thisRange = *--thisRangePtr; | |
537 if (otherRange.end == thisRange.end) { | |
538 // They end together: Find the start of the overlap. | |
539 unsigned startOfOverlap = std::max(thisRange.start, otherRan ge.start); | |
540 TypeOperations::swap(inlineBuffer() + startOfOverlap, inline Buffer() + thisRange.end, other.inlineBuffer() + startOfOverlap); | |
541 if (otherRange.start == thisRange.start) | |
542 continue; // Common left edge - we are done with these e ntries. | |
543 if (otherRange.start < thisRange.start) { | |
544 // The other extends further to the left, make a new ran ge. | |
545 *otherRangePtr++ = Range(otherRange.start, thisRange.sta rt); | |
Ken Russell (switch to Gerrit)
2014/07/21 20:44:09
Where is the guarantee that the new range being pu
Erik Corry
2014/07/22 15:49:26
There's no restriction on the ranges pushed on the
| |
546 continue; | |
547 } | |
548 // This extends further to the left, make a new range. | |
549 *thisRangePtr++ = Range(thisRange.start, otherRange.start); | |
550 continue; | |
551 } | |
552 if (otherRange.end > thisRange.end) { | |
553 // Other one hangs over the edge. | |
554 unsigned startOfOverhang = std::max(otherRange.start, thisRa nge.end); | |
555 TypeOperations::move(other.inlineBuffer() + startOfOverhang, other.inlineBuffer() + otherRange.end, inlineBuffer() + startOfOverhang); | |
556 if (otherRange.start != startOfOverhang) | |
557 *otherRangePtr++ = Range(otherRange.start, startOfOverha ng); | |
558 *thisRangePtr++ = thisRange; | |
559 continue; | |
560 } | |
561 ASSERT(thisRange.end > otherRange.end); | |
562 // This one hangs over the edge. | |
563 unsigned startOfOverhang = std::max(thisRange.start, otherRange. end); | |
564 TypeOperations::move(inlineBuffer() + startOfOverhang, inlineBuf fer() + thisRange.end, other.inlineBuffer() + startOfOverhang); | |
565 if (thisRange.start != startOfOverhang) | |
566 *thisRangePtr++ = Range(thisRange.start, startOfOverhang); | |
567 *otherRangePtr++ = otherRange; | |
479 } | 568 } |
480 } | 569 } |
481 | 570 |
482 using Base::buffer; | 571 using Base::buffer; |
483 using Base::capacity; | 572 using Base::capacity; |
573 using Base::findRanges; | |
484 | 574 |
485 bool hasOutOfLineBuffer() const | 575 bool hasOutOfLineBuffer() const |
486 { | 576 { |
487 return buffer() && buffer() != inlineBuffer(); | 577 return buffer() && buffer() != inlineBuffer(); |
488 } | 578 } |
489 | 579 |
490 protected: | |
491 using Base::m_size; | |
492 | |
493 private: | 580 private: |
494 using Base::m_buffer; | 581 using Base::m_buffer; |
495 using Base::m_capacity; | 582 using Base::m_capacity; |
496 | 583 |
497 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); | 584 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); |
498 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe r); } | 585 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe r); } |
499 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_ inlineBuffer.buffer); } | 586 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_ inlineBuffer.buffer); } |
500 | 587 |
501 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; | 588 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
502 template<typename U, size_t inlineBuffer, typename V> | 589 template<typename U, size_t inlineBuffer, typename V> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
543 | 630 |
544 template<typename Derived, typename Elements> | 631 template<typename Derived, typename Elements> |
545 class VectorDestructorBase<Derived, Elements, true, true> : public HeapVecto rWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruct ion> { }; | 632 class VectorDestructorBase<Derived, Elements, true, true> : public HeapVecto rWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruct ion> { }; |
546 | 633 |
547 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default Allocator> | 634 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default Allocator> |
548 class Vector : private VectorBuffer<T, inlineCapacity, Allocator>, public Ve ctorDestructorBase<Vector<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0) , Allocator::isGarbageCollected> { | 635 class Vector : private VectorBuffer<T, inlineCapacity, Allocator>, public Ve ctorDestructorBase<Vector<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0) , Allocator::isGarbageCollected> { |
549 WTF_USE_ALLOCATOR(Vector, Allocator); | 636 WTF_USE_ALLOCATOR(Vector, Allocator); |
550 private: | 637 private: |
551 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; | 638 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; |
552 typedef VectorTypeOperations<T> TypeOperations; | 639 typedef VectorTypeOperations<T> TypeOperations; |
640 typedef typename Base::Range Range; | |
553 | 641 |
554 public: | 642 public: |
555 typedef T ValueType; | 643 typedef T ValueType; |
556 | 644 |
557 typedef T* iterator; | 645 typedef T* iterator; |
558 typedef const T* const_iterator; | 646 typedef const T* const_iterator; |
559 typedef std::reverse_iterator<iterator> reverse_iterator; | 647 typedef std::reverse_iterator<iterator> reverse_iterator; |
560 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 648 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
561 | 649 |
562 Vector() | 650 Vector() |
651 : m_size(0) | |
563 { | 652 { |
564 // Unused slots are initialized to zero so that the visitor and the | 653 // Unused slots are initialized to zero so that the visitor and the |
565 // finalizer can visit them safely. canInitializeWithMemset tells us | 654 // finalizer can visit them safely. canInitializeWithMemset tells us |
566 // that the class does not expect matching constructor and | 655 // that the class does not expect matching constructor and |
567 // destructor calls as long as the memory is zeroed. | 656 // destructor calls as long as the memory is zeroed. |
568 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); | 657 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); |
569 COMPILE_ASSERT(!WTF::IsPolymorphic<T>::value || !VectorTraits<T>::ca nInitializeWithMemset, CantInitializeWithMemsetIfThereIsAVtable); | 658 COMPILE_ASSERT(!WTF::IsPolymorphic<T>::value || !VectorTraits<T>::ca nInitializeWithMemset, CantInitializeWithMemsetIfThereIsAVtable); |
570 m_size = 0; | |
571 } | 659 } |
572 | 660 |
573 explicit Vector(size_t size) | 661 explicit Vector(size_t size) |
574 : Base(size) | 662 : Base(size) |
575 { | 663 { |
664 setSize(size); | |
576 // Unused slots are initialized to zero so that the visitor and the | 665 // Unused slots are initialized to zero so that the visitor and the |
577 // finalizer can visit them safely. canInitializeWithMemset tells us | 666 // finalizer can visit them safely. canInitializeWithMemset tells us |
578 // that the class does not expect matching constructor and | 667 // that the class does not expect matching constructor and |
579 // destructor calls as long as the memory is zeroed. | 668 // destructor calls as long as the memory is zeroed. |
580 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); | 669 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); |
581 m_size = size; | |
582 TypeOperations::initialize(begin(), end()); | 670 TypeOperations::initialize(begin(), end()); |
583 } | 671 } |
584 | 672 |
585 // Off-GC-heap vectors: Destructor should be called. | 673 // Off-GC-heap vectors: Destructor should be called. |
586 // On-GC-heap vectors: Destructor should be called for inline buffers | 674 // On-GC-heap vectors: Destructor should be called for inline buffers |
587 // (if any) but destructor shouldn't be called for vector backing since | 675 // (if any) but destructor shouldn't be called for vector backing since |
588 // it is managed by the traced GC heap. | 676 // it is managed by the traced GC heap. |
589 void finalize() | 677 void finalize() |
590 { | 678 { |
591 if (!inlineCapacity) { | 679 if (!inlineCapacity) { |
592 if (LIKELY(!Base::buffer())) | 680 if (LIKELY(!Base::buffer())) |
593 return; | 681 return; |
594 } | 682 } |
595 if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOu tOfLineBuffer())) { | 683 if (LIKELY(size()) && !(Allocator::isGarbageCollected && this->hasOu tOfLineBuffer())) { |
596 TypeOperations::destruct(begin(), end()); | 684 TypeOperations::destruct(begin(), end()); |
597 m_size = 0; // Partial protection against use-after-free. | 685 setSize(0); // Partial protection against use-after-free. |
598 } | 686 } |
599 | 687 |
600 Base::destruct(); | 688 Base::destruct(); |
601 } | 689 } |
602 | 690 |
603 void finalizeGarbageCollectedObject() | 691 void finalizeGarbageCollectedObject() |
604 { | 692 { |
605 finalize(); | 693 finalize(); |
606 } | 694 } |
607 | 695 |
608 Vector(const Vector&); | 696 Vector(const Vector&); |
609 template<size_t otherCapacity> | 697 template<size_t otherInlineCapacity> |
610 explicit Vector(const Vector<T, otherCapacity, Allocator>&); | 698 explicit Vector(const Vector<T, otherInlineCapacity, Allocator>&); |
611 | 699 |
612 Vector& operator=(const Vector&); | 700 Vector& operator=(const Vector&); |
613 template<size_t otherCapacity> | 701 template<size_t otherInlineCapacity> |
614 Vector& operator=(const Vector<T, otherCapacity, Allocator>&); | 702 Vector& operator=(const Vector<T, otherInlineCapacity, Allocator>&); |
615 | 703 |
616 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) | 704 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) |
617 Vector(Vector&&); | 705 Vector(Vector&&); |
618 Vector& operator=(Vector&&); | 706 Vector& operator=(Vector&&); |
619 #endif | 707 #endif |
620 | 708 |
621 size_t size() const { return m_size; } | |
622 size_t capacity() const { return Base::capacity(); } | 709 size_t capacity() const { return Base::capacity(); } |
623 bool isEmpty() const { return !size(); } | 710 bool isEmpty() const { return !size(); } |
624 | 711 |
625 T& at(size_t i) | 712 T& at(size_t i) |
626 { | 713 { |
627 RELEASE_ASSERT(i < size()); | 714 RELEASE_ASSERT(i < size()); |
628 return Base::buffer()[i]; | 715 return Base::buffer()[i]; |
629 } | 716 } |
630 const T& at(size_t i) const | 717 const T& at(size_t i) const |
631 { | 718 { |
632 RELEASE_ASSERT(i < size()); | 719 RELEASE_ASSERT(i < size()); |
633 return Base::buffer()[i]; | 720 return Base::buffer()[i]; |
634 } | 721 } |
635 | 722 |
636 T& operator[](size_t i) { return at(i); } | 723 T& operator[](size_t i) { return at(i); } |
637 const T& operator[](size_t i) const { return at(i); } | 724 const T& operator[](size_t i) const { return at(i); } |
638 | 725 |
639 T* data() { return Base::buffer(); } | 726 T* data() { return Base::buffer(); } |
640 const T* data() const { return Base::buffer(); } | 727 const T* data() const { return Base::buffer(); } |
641 | 728 |
642 iterator begin() { return data(); } | 729 iterator begin() { return data(); } |
643 iterator end() { return begin() + m_size; } | 730 iterator end() { return begin() + size(); } |
644 const_iterator begin() const { return data(); } | 731 const_iterator begin() const { return data(); } |
645 const_iterator end() const { return begin() + m_size; } | 732 const_iterator end() const { return begin() + size(); } |
646 | 733 |
647 reverse_iterator rbegin() { return reverse_iterator(end()); } | 734 reverse_iterator rbegin() { return reverse_iterator(end()); } |
648 reverse_iterator rend() { return reverse_iterator(begin()); } | 735 reverse_iterator rend() { return reverse_iterator(begin()); } |
649 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } | 736 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } |
650 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } | 737 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } |
651 | 738 |
652 T& first() { return at(0); } | 739 T& first() { return at(0); } |
653 const T& first() const { return at(0); } | 740 const T& first() const { return at(0); } |
654 T& last() { return at(size() - 1); } | 741 T& last() { return at(size() - 1); } |
655 const T& last() const { return at(size() - 1); } | 742 const T& last() const { return at(size() - 1); } |
(...skipping 12 matching lines...) Expand all Loading... | |
668 { | 755 { |
669 if (size() * 2 < capacity()) | 756 if (size() * 2 < capacity()) |
670 shrinkCapacity(size() + size() / 4 + 1); | 757 shrinkCapacity(size() + size() / 4 + 1); |
671 } | 758 } |
672 | 759 |
673 void clear() { shrinkCapacity(0); } | 760 void clear() { shrinkCapacity(0); } |
674 | 761 |
675 template<typename U> void append(const U*, size_t); | 762 template<typename U> void append(const U*, size_t); |
676 template<typename U> void append(const U&); | 763 template<typename U> void append(const U&); |
677 template<typename U> void uncheckedAppend(const U& val); | 764 template<typename U> void uncheckedAppend(const U& val); |
678 template<typename U, size_t otherCapacity, typename V> void appendVector (const Vector<U, otherCapacity, V>&); | 765 template<typename U, size_t otherInlineCapacity, typename V> void append Vector(const Vector<U, otherInlineCapacity, V>&); |
679 | 766 |
680 template<typename U> void insert(size_t position, const U*, size_t); | 767 template<typename U> void insert(size_t position, const U*, size_t); |
681 template<typename U> void insert(size_t position, const U&); | 768 template<typename U> void insert(size_t position, const U&); |
682 template<typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&); | 769 template<typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&); |
683 | 770 |
684 template<typename U> void prepend(const U*, size_t); | 771 template<typename U> void prepend(const U*, size_t); |
685 template<typename U> void prepend(const U&); | 772 template<typename U> void prepend(const U&); |
686 template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&); | 773 template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&); |
687 | 774 |
688 void remove(size_t position); | 775 void remove(size_t position); |
689 void remove(size_t position, size_t length); | 776 void remove(size_t position, size_t length); |
690 | 777 |
691 void removeLast() | 778 void removeLast() |
692 { | 779 { |
693 ASSERT(!isEmpty()); | 780 ASSERT(!isEmpty()); |
694 shrink(size() - 1); | 781 shrink(size() - 1); |
695 } | 782 } |
696 | 783 |
697 Vector(size_t size, const T& val) | 784 Vector(size_t size, const T& val) |
698 : Base(size) | 785 : Base(size) |
699 { | 786 { |
700 m_size = size; | 787 setSize(size); |
701 TypeOperations::uninitializedFill(begin(), end(), val); | 788 TypeOperations::uninitializedFill(begin(), end(), val); |
702 } | 789 } |
703 | 790 |
704 void fill(const T&, size_t); | 791 void fill(const T&, size_t); |
705 void fill(const T& val) { fill(val, size()); } | 792 void fill(const T& val) { fill(val, size()); } |
706 | 793 |
707 template<typename Iterator> void appendRange(Iterator start, Iterator en d); | 794 template<typename Iterator> void appendRange(Iterator start, Iterator en d); |
708 | 795 |
709 void swap(Vector& other) | 796 void swap(Vector& other); |
710 { | |
711 Base::swapVectorBuffer(other); | |
712 std::swap(m_size, other.m_size); | |
713 } | |
714 | 797 |
715 void reverse(); | 798 void reverse(); |
716 | 799 |
717 void trace(typename Allocator::Visitor*); | 800 void trace(typename Allocator::Visitor*); |
718 | 801 |
802 size_t size() const { return m_size; } | |
719 private: | 803 private: |
720 void expandCapacity(size_t newMinCapacity); | 804 void expandCapacity(size_t newMinCapacity); |
721 const T* expandCapacity(size_t newMinCapacity, const T*); | 805 const T* expandCapacity(size_t newMinCapacity, const T*); |
722 template<typename U> U* expandCapacity(size_t newMinCapacity, U*); | 806 template<typename U> U* expandCapacity(size_t newMinCapacity, U*); |
723 void shrinkCapacity(size_t newCapacity); | 807 void shrinkCapacity(size_t newCapacity); |
724 template<typename U> void appendSlowCase(const U&); | 808 template<typename U> void appendSlowCase(const U&); |
725 | 809 |
726 using Base::m_size; | 810 void setSize(unsigned size) |
811 { | |
812 m_size = size; | |
813 } | |
814 | |
815 unsigned m_size; | |
816 | |
727 using Base::buffer; | 817 using Base::buffer; |
728 using Base::capacity; | 818 using Base::capacity; |
729 using Base::swapVectorBuffer; | |
730 using Base::allocateBuffer; | 819 using Base::allocateBuffer; |
731 using Base::allocationSize; | 820 using Base::allocationSize; |
732 using Base::clearUnusedSlots; | 821 using Base::clearUnusedSlots; |
822 using Base::hasOutOfLineBuffer; | |
823 | |
824 friend class VectorBuffer<T, inlineCapacity, Allocator>; | |
Mads Ager (chromium)
2014/07/18 11:03:14
Do you need this friend declaration?
Erik Corry
2014/07/22 15:49:26
Removed.
| |
733 }; | 825 }; |
734 | 826 |
735 template<typename T, size_t inlineCapacity, typename Allocator> | 827 template<typename T, size_t inlineCapacity, typename Allocator> |
828 void Vector<T, inlineCapacity, Allocator>::swap(Vector<T, inlineCapacity, Al locator>& other) | |
829 { | |
830 Base::swapVectorBuffer(other, Range(0, m_size), Range(0, other.m_size)); | |
831 std::swap(m_size, other.m_size); | |
832 } | |
833 | |
834 template<typename T, size_t inlineCapacity, typename Allocator> | |
736 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) | 835 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) |
737 : Base(other.capacity()) | 836 : Base(other.capacity()) |
738 { | 837 { |
739 m_size = other.size(); | 838 setSize(other.size()); |
740 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 839 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
741 } | 840 } |
742 | 841 |
743 template<typename T, size_t inlineCapacity, typename Allocator> | 842 template<typename T, size_t inlineCapacity, typename Allocator> |
744 template<size_t otherCapacity> | 843 template<size_t otherInlineCapacity> |
745 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allocator>& other) | 844 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherInlineCapa city, Allocator>& other) |
746 : Base(other.capacity()) | 845 : Base(other.capacity()) |
747 { | 846 { |
748 m_size = other.size(); | 847 setSize(other.size()); |
749 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 848 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
750 } | 849 } |
751 | 850 |
752 template<typename T, size_t inlineCapacity, typename Allocator> | 851 template<typename T, size_t inlineCapacity, typename Allocator> |
753 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, inlineCapacity, Allocator>& other) | 852 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, inlineCapacity, Allocator>& other) |
754 { | 853 { |
755 if (UNLIKELY(&other == this)) | 854 if (UNLIKELY(&other == this)) |
756 return *this; | 855 return *this; |
757 | 856 |
758 if (size() > other.size()) | 857 if (size() > other.size()) |
759 shrink(other.size()); | 858 shrink(other.size()); |
760 else if (other.size() > capacity()) { | 859 else if (other.size() > capacity()) { |
761 clear(); | 860 clear(); |
762 reserveCapacity(other.size()); | 861 reserveCapacity(other.size()); |
763 ASSERT(begin()); | 862 ASSERT(begin()); |
764 } | 863 } |
765 | 864 |
766 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last | 865 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last |
767 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL | 866 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
768 if (!begin()) | 867 if (!begin()) |
769 return *this; | 868 return *this; |
770 #endif | 869 #endif |
771 | 870 |
772 std::copy(other.begin(), other.begin() + size(), begin()); | 871 std::copy(other.begin(), other.begin() + size(), begin()); |
773 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); | 872 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); |
774 m_size = other.size(); | 873 setSize(other.size()); |
775 | 874 |
776 return *this; | 875 return *this; |
777 } | 876 } |
778 | 877 |
779 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } | 878 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } |
780 | 879 |
781 template<typename T, size_t inlineCapacity, typename Allocator> | 880 template<typename T, size_t inlineCapacity, typename Allocator> |
782 template<size_t otherCapacity> | 881 template<size_t otherInlineCapacity> |
783 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, otherCapacity, Allocator>& other) | 882 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, otherInlineCapacity, Allocator>& other) |
784 { | 883 { |
785 // If the inline capacities match, we should call the more specific | 884 // If the inline capacities match, we should call the more specific |
786 // template. If the inline capacities don't match, the two objects | 885 // template. If the inline capacities don't match, the two objects |
787 // shouldn't be allocated the same address. | 886 // shouldn't be allocated the same address. |
788 ASSERT(!typelessPointersAreEqual(&other, this)); | 887 ASSERT(!typelessPointersAreEqual(&other, this)); |
789 | 888 |
790 if (size() > other.size()) | 889 if (size() > other.size()) |
791 shrink(other.size()); | 890 shrink(other.size()); |
792 else if (other.size() > capacity()) { | 891 else if (other.size() > capacity()) { |
793 clear(); | 892 clear(); |
794 reserveCapacity(other.size()); | 893 reserveCapacity(other.size()); |
795 ASSERT(begin()); | 894 ASSERT(begin()); |
796 } | 895 } |
797 | 896 |
798 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last | 897 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last |
799 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL | 898 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
800 if (!begin()) | 899 if (!begin()) |
801 return *this; | 900 return *this; |
802 #endif | 901 #endif |
803 | 902 |
804 std::copy(other.begin(), other.begin() + size(), begin()); | 903 std::copy(other.begin(), other.begin() + size(), begin()); |
805 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); | 904 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); |
806 m_size = other.size(); | 905 setSize(other.size()); |
807 | 906 |
808 return *this; | 907 return *this; |
809 } | 908 } |
810 | 909 |
811 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) | 910 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) |
812 template<typename T, size_t inlineCapacity, typename Allocator> | 911 template<typename T, size_t inlineCapacity, typename Allocator> |
813 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Alloc ator>&& other) | 912 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Alloc ator>&& other) |
814 { | 913 { |
815 m_size = 0; | 914 setSize(0); |
816 // It's a little weird to implement a move constructor using swap but th is way we | 915 // It's a little weird to implement a move constructor using swap but th is way we |
817 // don't have to add a move constructor to VectorBuffer. | 916 // don't have to add a move constructor to VectorBuffer. |
818 swap(other); | 917 swap(other); |
819 } | 918 } |
820 | 919 |
821 template<typename T, size_t inlineCapacity, typename Allocator> | 920 template<typename T, size_t inlineCapacity, typename Allocator> |
822 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(Vector<T, inlineCapacity, Allocator>&& other) | 921 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(Vector<T, inlineCapacity, Allocator>&& other) |
823 { | 922 { |
824 swap(other); | 923 swap(other); |
825 return *this; | 924 return *this; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
866 if (size() > newSize) | 965 if (size() > newSize) |
867 shrink(newSize); | 966 shrink(newSize); |
868 else if (newSize > capacity()) { | 967 else if (newSize > capacity()) { |
869 clear(); | 968 clear(); |
870 reserveCapacity(newSize); | 969 reserveCapacity(newSize); |
871 ASSERT(begin()); | 970 ASSERT(begin()); |
872 } | 971 } |
873 | 972 |
874 std::fill(begin(), end(), val); | 973 std::fill(begin(), end(), val); |
875 TypeOperations::uninitializedFill(end(), begin() + newSize, val); | 974 TypeOperations::uninitializedFill(end(), begin() + newSize, val); |
876 m_size = newSize; | 975 setSize(newSize); |
877 } | 976 } |
878 | 977 |
879 template<typename T, size_t inlineCapacity, typename Allocator> | 978 template<typename T, size_t inlineCapacity, typename Allocator> |
880 template<typename Iterator> | 979 template<typename Iterator> |
881 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Itera tor end) | 980 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Itera tor end) |
882 { | 981 { |
883 for (Iterator it = start; it != end; ++it) | 982 for (Iterator it = start; it != end; ++it) |
884 append(*it); | 983 append(*it); |
885 } | 984 } |
886 | 985 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
919 } | 1018 } |
920 | 1019 |
921 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1020 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
922 inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMin Capacity, U* ptr) | 1021 inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMin Capacity, U* ptr) |
923 { | 1022 { |
924 expandCapacity(newMinCapacity); | 1023 expandCapacity(newMinCapacity); |
925 return ptr; | 1024 return ptr; |
926 } | 1025 } |
927 | 1026 |
928 template<typename T, size_t inlineCapacity, typename Allocator> | 1027 template<typename T, size_t inlineCapacity, typename Allocator> |
929 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size) | 1028 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t sizeArg) |
930 { | 1029 { |
931 if (size <= m_size) | 1030 if (sizeArg <= size()) |
932 TypeOperations::destruct(begin() + size, end()); | 1031 TypeOperations::destruct(begin() + sizeArg, end()); |
933 else { | 1032 else { |
934 if (size > capacity()) | 1033 if (sizeArg > capacity()) |
935 expandCapacity(size); | 1034 expandCapacity(sizeArg); |
936 TypeOperations::initialize(end(), begin() + size); | 1035 TypeOperations::initialize(end(), begin() + sizeArg); |
937 } | 1036 } |
938 | 1037 |
939 m_size = size; | 1038 setSize(sizeArg); |
940 } | 1039 } |
941 | 1040 |
942 template<typename T, size_t inlineCapacity, typename Allocator> | 1041 template<typename T, size_t inlineCapacity, typename Allocator> |
943 void Vector<T, inlineCapacity, Allocator>::shrink(size_t size) | 1042 void Vector<T, inlineCapacity, Allocator>::shrink(size_t sizeArg) |
944 { | 1043 { |
945 ASSERT(size <= m_size); | 1044 ASSERT(sizeArg <= size()); |
946 TypeOperations::destruct(begin() + size, end()); | 1045 TypeOperations::destruct(begin() + sizeArg, end()); |
947 clearUnusedSlots(begin() + size, end()); | 1046 clearUnusedSlots(begin() + sizeArg, end()); |
948 m_size = size; | 1047 setSize(sizeArg); |
949 } | 1048 } |
950 | 1049 |
951 template<typename T, size_t inlineCapacity, typename Allocator> | 1050 template<typename T, size_t inlineCapacity, typename Allocator> |
952 void Vector<T, inlineCapacity, Allocator>::grow(size_t size) | 1051 void Vector<T, inlineCapacity, Allocator>::grow(size_t sizeArg) |
953 { | 1052 { |
954 ASSERT(size >= m_size); | 1053 ASSERT(sizeArg >= size()); |
955 if (size > capacity()) | 1054 if (sizeArg > capacity()) |
956 expandCapacity(size); | 1055 expandCapacity(sizeArg); |
957 TypeOperations::initialize(end(), begin() + size); | 1056 TypeOperations::initialize(end(), begin() + sizeArg); |
958 m_size = size; | 1057 setSize(sizeArg); |
959 } | 1058 } |
960 | 1059 |
961 template<typename T, size_t inlineCapacity, typename Allocator> | 1060 template<typename T, size_t inlineCapacity, typename Allocator> |
962 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacit y) | 1061 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacit y) |
963 { | 1062 { |
964 if (UNLIKELY(newCapacity <= capacity())) | 1063 if (UNLIKELY(newCapacity <= capacity())) |
965 return; | 1064 return; |
966 T* oldBuffer = begin(); | 1065 T* oldBuffer = begin(); |
967 T* oldEnd = end(); | 1066 T* oldEnd = end(); |
968 Base::allocateBuffer(newCapacity); | 1067 Base::allocateBuffer(newCapacity); |
969 TypeOperations::move(oldBuffer, oldEnd, begin()); | 1068 TypeOperations::move(oldBuffer, oldEnd, begin()); |
970 Base::deallocateBuffer(oldBuffer); | 1069 Base::deallocateBuffer(oldBuffer); |
971 } | 1070 } |
972 | 1071 |
973 template<typename T, size_t inlineCapacity, typename Allocator> | 1072 template<typename T, size_t inlineCapacity, typename Allocator> |
974 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz e_t initialCapacity) | 1073 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz e_t initialCapacity) |
975 { | 1074 { |
976 ASSERT(!m_size); | 1075 ASSERT(!size()); |
977 ASSERT(capacity() == inlineCapacity); | 1076 ASSERT(capacity() == inlineCapacity); |
978 if (initialCapacity > inlineCapacity) | 1077 if (initialCapacity > inlineCapacity) |
979 Base::allocateBuffer(initialCapacity); | 1078 Base::allocateBuffer(initialCapacity); |
980 } | 1079 } |
981 | 1080 |
982 template<typename T, size_t inlineCapacity, typename Allocator> | 1081 template<typename T, size_t inlineCapacity, typename Allocator> |
983 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity ) | 1082 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity ) |
984 { | 1083 { |
985 if (newCapacity >= capacity()) | 1084 if (newCapacity >= capacity()) |
986 return; | 1085 return; |
(...skipping 18 matching lines...) Expand all Loading... | |
1005 Base::deallocateBuffer(oldBuffer); | 1104 Base::deallocateBuffer(oldBuffer); |
1006 } | 1105 } |
1007 | 1106 |
1008 // Templatizing these is better than just letting the conversion happen impl icitly, | 1107 // Templatizing these is better than just letting the conversion happen impl icitly, |
1009 // because for instance it allows a PassRefPtr to be appended to a RefPtr ve ctor | 1108 // because for instance it allows a PassRefPtr to be appended to a RefPtr ve ctor |
1010 // without refcount thrash. | 1109 // without refcount thrash. |
1011 | 1110 |
1012 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1111 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1013 void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t data Size) | 1112 void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t data Size) |
1014 { | 1113 { |
1015 size_t newSize = m_size + dataSize; | 1114 size_t newSize = size() + dataSize; |
1016 if (newSize > capacity()) { | 1115 if (newSize > capacity()) { |
1017 data = expandCapacity(newSize, data); | 1116 data = expandCapacity(newSize, data); |
1018 ASSERT(begin()); | 1117 ASSERT(begin()); |
1019 } | 1118 } |
1020 RELEASE_ASSERT(newSize >= m_size); | 1119 RELEASE_ASSERT(newSize >= size()); |
1021 T* dest = end(); | 1120 T* dest = end(); |
1022 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], dest); | 1121 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], dest); |
1023 m_size = newSize; | 1122 setSize(newSize); |
1024 } | 1123 } |
1025 | 1124 |
1026 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1125 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1027 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val ) | 1126 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val ) |
1028 { | 1127 { |
1029 if (LIKELY(size() != capacity())) { | 1128 if (LIKELY(size() != capacity())) { |
1030 new (NotNull, end()) T(val); | 1129 new (NotNull, end()) T(val); |
1031 ++m_size; | 1130 setSize(size() + 1); |
1032 return; | 1131 return; |
1033 } | 1132 } |
1034 | 1133 |
1035 appendSlowCase(val); | 1134 appendSlowCase(val); |
1036 } | 1135 } |
1037 | 1136 |
1038 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1137 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1039 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val) | 1138 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val) |
1040 { | 1139 { |
1041 ASSERT(size() == capacity()); | 1140 ASSERT(size() == capacity()); |
1042 | 1141 |
1043 const U* ptr = &val; | 1142 const U* ptr = &val; |
1044 ptr = expandCapacity(size() + 1, ptr); | 1143 ptr = expandCapacity(size() + 1, ptr); |
1045 ASSERT(begin()); | 1144 ASSERT(begin()); |
1046 | 1145 |
1047 new (NotNull, end()) T(*ptr); | 1146 new (NotNull, end()) T(*ptr); |
1048 ++m_size; | 1147 setSize(size() + 1); |
1049 } | 1148 } |
1050 | 1149 |
1051 // This version of append saves a branch in the case where you know that the | 1150 // This version of append saves a branch in the case where you know that the |
1052 // vector's capacity is large enough for the append to succeed. | 1151 // vector's capacity is large enough for the append to succeed. |
1053 | 1152 |
1054 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1153 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1055 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(con st U& val) | 1154 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(con st U& val) |
1056 { | 1155 { |
1057 ASSERT(size() < capacity()); | 1156 ASSERT(size() < capacity()); |
1058 const U* ptr = &val; | 1157 const U* ptr = &val; |
1059 new (NotNull, end()) T(*ptr); | 1158 new (NotNull, end()) T(*ptr); |
1060 ++m_size; | 1159 setSize(size() + 1); |
1061 } | 1160 } |
1062 | 1161 |
1063 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t otherCapacity, typename OtherAllocator> | 1162 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t otherInlineCapacity, typename OtherAllocator> |
1064 inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector< U, otherCapacity, OtherAllocator>& val) | 1163 inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector< U, otherInlineCapacity, OtherAllocator>& val) |
1065 { | 1164 { |
1066 append(val.begin(), val.size()); | 1165 append(val.begin(), val.size()); |
1067 } | 1166 } |
1068 | 1167 |
1069 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1168 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1070 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize) | 1169 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize) |
1071 { | 1170 { |
1072 RELEASE_ASSERT(position <= size()); | 1171 RELEASE_ASSERT(position <= size()); |
1073 size_t newSize = m_size + dataSize; | 1172 size_t newSize = size() + dataSize; |
1074 if (newSize > capacity()) { | 1173 if (newSize > capacity()) { |
1075 data = expandCapacity(newSize, data); | 1174 data = expandCapacity(newSize, data); |
1076 ASSERT(begin()); | 1175 ASSERT(begin()); |
1077 } | 1176 } |
1078 RELEASE_ASSERT(newSize >= m_size); | 1177 RELEASE_ASSERT(newSize >= size()); |
1079 T* spot = begin() + position; | 1178 T* spot = begin() + position; |
1080 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); | 1179 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); |
1081 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], spot); | 1180 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], spot); |
1082 m_size = newSize; | 1181 setSize(newSize); |
1083 } | 1182 } |
1084 | 1183 |
1085 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1184 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1086 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst U& val) | 1185 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst U& val) |
1087 { | 1186 { |
1088 RELEASE_ASSERT(position <= size()); | 1187 RELEASE_ASSERT(position <= size()); |
1089 const U* data = &val; | 1188 const U* data = &val; |
1090 if (size() == capacity()) { | 1189 if (size() == capacity()) { |
1091 data = expandCapacity(size() + 1, data); | 1190 data = expandCapacity(size() + 1, data); |
1092 ASSERT(begin()); | 1191 ASSERT(begin()); |
1093 } | 1192 } |
1094 T* spot = begin() + position; | 1193 T* spot = begin() + position; |
1095 TypeOperations::moveOverlapping(spot, end(), spot + 1); | 1194 TypeOperations::moveOverlapping(spot, end(), spot + 1); |
1096 new (NotNull, spot) T(*data); | 1195 new (NotNull, spot) T(*data); |
1097 ++m_size; | 1196 setSize(size() + 1); |
1098 } | 1197 } |
1099 | 1198 |
1100 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t c, typename OtherAllocator> | 1199 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t c, typename OtherAllocator> |
1101 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst Vector<U, c, OtherAllocator>& val) | 1200 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst Vector<U, c, OtherAllocator>& val) |
1102 { | 1201 { |
1103 insert(position, val.begin(), val.size()); | 1202 insert(position, val.begin(), val.size()); |
1104 } | 1203 } |
1105 | 1204 |
1106 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1205 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1107 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dat aSize) | 1206 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dat aSize) |
(...skipping 14 matching lines...) Expand all Loading... | |
1122 } | 1221 } |
1123 | 1222 |
1124 template<typename T, size_t inlineCapacity, typename Allocator> | 1223 template<typename T, size_t inlineCapacity, typename Allocator> |
1125 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) | 1224 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) |
1126 { | 1225 { |
1127 RELEASE_ASSERT(position < size()); | 1226 RELEASE_ASSERT(position < size()); |
1128 T* spot = begin() + position; | 1227 T* spot = begin() + position; |
1129 spot->~T(); | 1228 spot->~T(); |
1130 TypeOperations::moveOverlapping(spot + 1, end(), spot); | 1229 TypeOperations::moveOverlapping(spot + 1, end(), spot); |
1131 clearUnusedSlots(end() - 1, end()); | 1230 clearUnusedSlots(end() - 1, end()); |
1132 --m_size; | 1231 setSize(size() - 1); |
1133 } | 1232 } |
1134 | 1233 |
1135 template<typename T, size_t inlineCapacity, typename Allocator> | 1234 template<typename T, size_t inlineCapacity, typename Allocator> |
1136 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, si ze_t length) | 1235 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, si ze_t length) |
1137 { | 1236 { |
1138 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); | 1237 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); |
1139 RELEASE_ASSERT(position + length <= size()); | 1238 RELEASE_ASSERT(position + length <= size()); |
1140 T* beginSpot = begin() + position; | 1239 T* beginSpot = begin() + position; |
1141 T* endSpot = beginSpot + length; | 1240 T* endSpot = beginSpot + length; |
1142 TypeOperations::destruct(beginSpot, endSpot); | 1241 TypeOperations::destruct(beginSpot, endSpot); |
1143 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); | 1242 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); |
1144 clearUnusedSlots(end() - length, end()); | 1243 clearUnusedSlots(end() - length, end()); |
1145 m_size -= length; | 1244 setSize(size() - length); |
1146 } | 1245 } |
1147 | 1246 |
1148 template<typename T, size_t inlineCapacity, typename Allocator> | 1247 template<typename T, size_t inlineCapacity, typename Allocator> |
1149 inline void Vector<T, inlineCapacity, Allocator>::reverse() | 1248 inline void Vector<T, inlineCapacity, Allocator>::reverse() |
1150 { | 1249 { |
1151 for (size_t i = 0; i < m_size / 2; ++i) | 1250 for (size_t i = 0; i < size() / 2; ++i) |
1152 std::swap(at(i), at(m_size - 1 - i)); | 1251 std::swap(at(i), at(size() - 1 - i)); |
1153 } | 1252 } |
1154 | 1253 |
1155 template<typename T, size_t inlineCapacity, typename Allocator> | 1254 template<typename T, size_t inlineCapacity, typename Allocator> |
1156 void deleteAllValues(const Vector<T, inlineCapacity, Allocator>& collection) | 1255 void deleteAllValues(const Vector<T, inlineCapacity, Allocator>& collection) |
1157 { | 1256 { |
1158 typedef typename Vector<T, inlineCapacity, Allocator>::const_iterator it erator; | 1257 typedef typename Vector<T, inlineCapacity, Allocator>::const_iterator it erator; |
1159 iterator end = collection.end(); | 1258 iterator end = collection.end(); |
1160 for (iterator it = collection.begin(); it != end; ++it) | 1259 for (iterator it = collection.begin(); it != end; ++it) |
1161 delete *it; | 1260 delete *it; |
1162 } | 1261 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1203 struct NeedsTracing<Vector<T, N> > { | 1302 struct NeedsTracing<Vector<T, N> > { |
1204 static const bool value = false; | 1303 static const bool value = false; |
1205 }; | 1304 }; |
1206 #endif | 1305 #endif |
1207 | 1306 |
1208 } // namespace WTF | 1307 } // namespace WTF |
1209 | 1308 |
1210 using WTF::Vector; | 1309 using WTF::Vector; |
1211 | 1310 |
1212 #endif // WTF_Vector_h | 1311 #endif // WTF_Vector_h |
OLD | NEW |