259 if (equalsComparer (item, fHead_->fItem)) {
263 Link_* prev =
nullptr;
264 for (Link_* link = fHead_; link !=
nullptr; prev = link, link = link->fNext) {
265 if (equalsComparer (link->fItem, item)) {
267 prev->fNext = link->fNext;
275 template <
typename T>
276 template <
typename EQUALS_COMPARER>
277 bool DoublyLinkedList<T>::Contains (ArgByValueType<T> item, EQUALS_COMPARER&& equalsComparer)
const
279 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
280 for (
const Link_* current = fHead_; current !=
nullptr; current = current->fNext) {
281 if (forward<EQUALS_COMPARER> (equalsComparer) (current->fItem, item)) {
287 template <
typename T>
288 template <invocable<T> FUNCTION>
289 inline void DoublyLinkedList<T>::Apply (FUNCTION&& doToElement)
const
291 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
292 for (
const Link_* i = fHead_; i !=
nullptr; i = i->fNext) {
293 forward<FUNCTION> (doToElement) (i->fItem);
296 template <
typename T>
297 template <
typename FUNCTION>
298 inline auto DoublyLinkedList<T>::Find (FUNCTION&& firstThat)
const -> UnderlyingIteratorRep
300 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
301 for (Link_* i = fHead_; i !=
nullptr; i = i->fNext) {
302 if (forward<FUNCTION> (firstThat) (i->fItem)) {
308 template <
typename T>
312 for (Link_* i = fHead_; i !=
nullptr;) {
320 template <
typename T>
323 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
325 Require (i < size ());
326 const Link_* cur = fHead_;
327 for (; i != 0; cur = cur->fNext, --i) {
333 template <
typename T>
338 Require (i < size ());
340 for (; i != 0; cur = cur->fNext, --i) {
346 template <
typename T>
349 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
355#if qStroika_Foundation_Debug_AssertionsChecked
356 Require (pi->fData_ == movedFrom);
358 auto newI = this->fHead_;
359 [[maybe_unused]]
auto newE =
nullptr;
360 auto oldI = movedFrom->fHead_;
361 [[maybe_unused]]
auto oldE =
nullptr;
362 while (oldI != pi->fCurrent_) {
363 Assert (newI != newE);
364 Assert (oldI != oldE);
367 Assert (newI != newE);
368 Assert (oldI != oldE);
370 Assert (oldI == pi->fCurrent_);
371 pi->fCurrent_ = newI;
372#if qStroika_Foundation_Debug_AssertionsChecked
376 template <
typename T>
377 inline auto DoublyLinkedList<T>::begin () const -> ForwardIterator
379 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
380 return ForwardIterator{
this};
382 template <
typename T>
383 constexpr auto DoublyLinkedList<T>::end () const noexcept -> ForwardIterator
385 return ForwardIterator{};
387 template <
typename T>
390 ForwardIterator next = i;
396 template <
typename T>
400 Require (not i.Done ());
401#if qStroika_Foundation_Debug_AssertionsChecked
402 Require (i.fData_ ==
this);
406 const Link_* victim = i.fCurrent_;
423 if (victim->fPrev ==
nullptr) {
425 Assert (fHead_ == victim);
426 fHead_ = victim->fNext;
427 if (fHead_ ==
nullptr) {
431 Assert (fHead_->fPrev == victim);
432 fHead_->fPrev =
nullptr;
436 Assert (victim->fPrev->fNext == victim);
437 victim->fPrev->fNext = victim->fNext;
439 if (victim->fNext ==
nullptr) {
441 Assert (victim == fTail_);
442 fTail_ = victim->fPrev;
445 Assert (victim->fNext->fPrev == victim);
446 victim->fNext->fPrev = victim->fPrev;
452 template <
typename T>
456 Require (not i.Done ());
457#if qStroika_Foundation_Debug_AssertionsChecked
458 Require (i.fData_ ==
this);
461 const_cast<Link_*
> (i.fCurrent_)->fItem = newValue;
464 template <
typename T>
468#if qStroika_Foundation_Debug_AssertionsChecked
469 Require (i.fData_ ==
this);
475 if (i.fCurrent_ ==
nullptr) {
481 push_back (newValue);
485 Link_* prev = i.fCurrent_->fPrev;
486 if (prev ==
nullptr) {
487 push_front (newValue);
497 Assert (prev->fNext == i.fCurrent_);
498 Link_* iteratorCurLink =
const_cast<Link_*
> (i.fCurrent_);
499 prev->fNext =
new Link_{newValue, prev, iteratorCurLink};
502 iteratorCurLink->fPrev = prev->fNext;
503 Assert (i.fCurrent_->fPrev->fPrev == prev);
508 template <
typename T>
512#if qStroika_Foundation_Debug_AssertionsChecked
513 Require (i.fData_ ==
this);
516 Require (not i.Done ());
518 Assert (fHead_ !=
nullptr);
526 Link_* iteratorCurLink =
const_cast<Link_*
> (i.fCurrent_);
527 Link_* newLink =
new Link_{newValue, iteratorCurLink, iteratorCurLink->fNext};
528 iteratorCurLink->fNext = newLink;
529 if (newLink->fNext !=
nullptr) {
530 newLink->fNext->fPrev = newLink;
532 if (newLink->fNext ==
nullptr) {
536 Assert (newLink->fNext->fPrev == newLink);
540#if qStroika_Foundation_Debug_AssertionsChecked
541 template <
typename T>
544#if qStroika_Foundation_Containers_DataStructures_DoublyLinkedList_IncludeSlowDebugChecks_
545 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
547 if (fHead_ !=
nullptr) {
548 Assert (fHead_->fPrev ==
nullptr);
549 if (fHead_->fNext ==
nullptr) {
550 Assert (fHead_ == fTail_);
553 Assert (fHead_->fNext->fPrev == fHead_);
556 if (fTail_ !=
nullptr) {
557 Assert (fTail_->fNext ==
nullptr);
558 if (fTail_->fPrev ==
nullptr) {
559 Assert (fHead_ == fTail_);
562 Assert (fTail_->fPrev->fNext == fTail_);
565 Assert (fHead_ ==
nullptr or fHead_->fPrev ==
nullptr);
566 Assert (fTail_ ==
nullptr or fTail_->fNext ==
nullptr);
571 size_t forwardCounter = 0;
572 for (Link_* i = fHead_; i !=
nullptr; i = i->fNext) {
573 Assert (i->fNext ==
nullptr or i->fNext->fPrev == i);
576 size_t backwardCounter{};
577 for (Link_* i = fTail_; i !=
nullptr; i = i->fPrev) {
578 Assert (i->fPrev ==
nullptr or i->fPrev->fNext == i);
581 Assert (forwardCounter == backwardCounter);
590 template <
typename T>
591 constexpr DoublyLinkedList<T>::ForwardIterator::ForwardIterator ([[maybe_unused]]
const DoublyLinkedList* data, UnderlyingIteratorRep startAt) noexcept
593#if qStroika_Foundation_Debug_AssertionsChecked
598 template <
typename T>
599 constexpr DoublyLinkedList<T>::ForwardIterator::ForwardIterator (
const DoublyLinkedList* data) noexcept
603 template <
typename T>
604 inline void DoublyLinkedList<T>::ForwardIterator::Invariant () const noexcept
606#if qStroika_Foundation_Debug_AssertionsChecked
610 template <
typename T>
611 inline DoublyLinkedList<T>::ForwardIterator::operator bool ()
const
615 template <
typename T>
616 inline bool DoublyLinkedList<T>::ForwardIterator::Done () const noexcept
618#if qStroika_Foundation_Debug_AssertionsChecked
619 if (fData_ !=
nullptr) {
620 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
624 return fCurrent_ ==
nullptr;
626 template <
typename T>
627 inline auto DoublyLinkedList<T>::ForwardIterator::operator++ () noexcept -> ForwardIterator&
629 Require (not Done ());
631 Assert (fCurrent_ !=
nullptr);
632 fCurrent_ = fCurrent_->fNext;
636 template <
typename T>
637 inline auto DoublyLinkedList<T>::ForwardIterator::operator++ (
int)
noexcept -> ForwardIterator
639 ForwardIterator result = *
this;
643 template <
typename T>
644 inline const T& DoublyLinkedList<T>::ForwardIterator::operator* ()
const
646#if qStroika_Foundation_Debug_AssertionsChecked
648 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
650 Require (not Done ());
653 return fCurrent_->fItem;
655 template <
typename T>
656 inline const T* DoublyLinkedList<T>::ForwardIterator::operator->()
const
658#if qStroika_Foundation_Debug_AssertionsChecked
660 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
662 Require (not Done ());
665 return &fCurrent_->fItem;
667 template <
typename T>
668 size_t DoublyLinkedList<T>::ForwardIterator::CurrentIndex (
const DoublyLinkedList* data)
const
670 Require (not Done ());
671#if qStroika_Foundation_Debug_AssertionsChecked
672 Require (data == fData_);
677 for (
const Link_* l = data->fHead_;; l = l->fNext, ++i) {
679 if (l == fCurrent_) [[unlikely]] {
686 template <
typename T>
687 inline auto DoublyLinkedList<T>::ForwardIterator::GetUnderlyingIteratorRep () const -> UnderlyingIteratorRep
691 template <
typename T>
692 inline void DoublyLinkedList<T>::ForwardIterator::SetUnderlyingIteratorRep (UnderlyingIteratorRep l)
694#if qStroika_Foundation_Debug_AssertionsChecked
695 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
701 template <
typename T>
702 constexpr void DoublyLinkedList<T>::ForwardIterator::AssertDataMatches ([[maybe_unused]]
const DoublyLinkedList* data)
const
704#if qStroika_Foundation_Debug_AssertionsChecked
705 Require (data == fData_);
708 template <
typename T>
709 inline bool DoublyLinkedList<T>::ForwardIterator::operator== (
const ForwardIterator& rhs)
const
711 return fCurrent_ == rhs.fCurrent_;
713#if qStroika_Foundation_Debug_AssertionsChecked
714 template <
typename T>
715 void DoublyLinkedList<T>::ForwardIterator::Invariant_ () const noexcept