261 Link_* prev =
nullptr;
262 for (Link_* link = fHead_; link !=
nullptr; prev = link, link = link->fNext) {
263 if (equalsComparer (link->fItem, item)) {
265 prev->fNext = link->fNext;
273 template <
typename T>
274 template <
typename EQUALS_COMPARER>
275 bool DoublyLinkedList<T>::Contains (ArgByValueType<T> item, EQUALS_COMPARER&& equalsComparer)
const
277 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
278 for (
const Link_* current = fHead_; current !=
nullptr; current = current->fNext) {
279 if (forward<EQUALS_COMPARER> (equalsComparer) (current->fItem, item)) {
285 template <
typename T>
286 template <invocable<T> FUNCTION>
287 inline void DoublyLinkedList<T>::Apply (FUNCTION&& doToElement)
const
289 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
290 for (
const Link_* i = fHead_; i !=
nullptr; i = i->fNext) {
291 forward<FUNCTION> (doToElement) (i->fItem);
294 template <
typename T>
295 template <
typename FUNCTION>
296 inline auto DoublyLinkedList<T>::Find (FUNCTION&& firstThat)
const -> UnderlyingIteratorRep
298 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
299 for (Link_* i = fHead_; i !=
nullptr; i = i->fNext) {
300 if (forward<FUNCTION> (firstThat) (i->fItem)) {
306 template <
typename T>
310 for (Link_* i = fHead_; i !=
nullptr;) {
318 template <
typename T>
321 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
323 Require (i < size ());
324 const Link_* cur = fHead_;
325 for (; i != 0; cur = cur->fNext, --i) {
331 template <
typename T>
336 Require (i < size ());
338 for (; i != 0; cur = cur->fNext, --i) {
344 template <
typename T>
347 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
353#if qStroika_Foundation_Debug_AssertionsChecked
354 Require (pi->fData_ == movedFrom);
356 auto newI = this->fHead_;
357 [[maybe_unused]]
auto newE =
nullptr;
358 auto oldI = movedFrom->fHead_;
359 [[maybe_unused]]
auto oldE =
nullptr;
360 while (oldI != pi->fCurrent_) {
361 Assert (newI != newE);
362 Assert (oldI != oldE);
365 Assert (newI != newE);
366 Assert (oldI != oldE);
368 Assert (oldI == pi->fCurrent_);
369 pi->fCurrent_ = newI;
370#if qStroika_Foundation_Debug_AssertionsChecked
374 template <
typename T>
375 inline auto DoublyLinkedList<T>::begin () const -> ForwardIterator
377 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
378 return ForwardIterator{
this};
380 template <
typename T>
381 constexpr auto DoublyLinkedList<T>::end () const noexcept -> ForwardIterator
383 return ForwardIterator{};
385 template <
typename T>
388 ForwardIterator next = i;
394 template <
typename T>
398 Require (not i.Done ());
399#if qStroika_Foundation_Debug_AssertionsChecked
400 Require (i.fData_ ==
this);
404 const Link_* victim = i.fCurrent_;
421 if (victim->fPrev ==
nullptr) {
423 Assert (fHead_ == victim);
424 fHead_ = victim->fNext;
425 if (fHead_ ==
nullptr) {
429 Assert (fHead_->fPrev == victim);
430 fHead_->fPrev =
nullptr;
434 Assert (victim->fPrev->fNext == victim);
435 victim->fPrev->fNext = victim->fNext;
437 if (victim->fNext ==
nullptr) {
439 Assert (victim == fTail_);
440 fTail_ = victim->fPrev;
443 Assert (victim->fNext->fPrev == victim);
444 victim->fNext->fPrev = victim->fPrev;
450 template <
typename T>
454 Require (not i.Done ());
455#if qStroika_Foundation_Debug_AssertionsChecked
456 Require (i.fData_ ==
this);
459 const_cast<Link_*
> (i.fCurrent_)->fItem = newValue;
462 template <
typename T>
466#if qStroika_Foundation_Debug_AssertionsChecked
467 Require (i.fData_ ==
this);
473 if (i.fCurrent_ ==
nullptr) {
479 push_back (newValue);
483 Link_* prev = i.fCurrent_->fPrev;
484 if (prev ==
nullptr) {
485 push_front (newValue);
495 Assert (prev->fNext == i.fCurrent_);
496 Link_* iteratorCurLink =
const_cast<Link_*
> (i.fCurrent_);
497 prev->fNext =
new Link_{newValue, prev, iteratorCurLink};
500 iteratorCurLink->fPrev = prev->fNext;
501 Assert (i.fCurrent_->fPrev->fPrev == prev);
506 template <
typename T>
510#if qStroika_Foundation_Debug_AssertionsChecked
511 Require (i.fData_ ==
this);
514 Require (not i.Done ());
516 Assert (fHead_ !=
nullptr);
524 Link_* iteratorCurLink =
const_cast<Link_*
> (i.fCurrent_);
525 Link_* newLink =
new Link_{newValue, iteratorCurLink, iteratorCurLink->fNext};
526 iteratorCurLink->fNext = newLink;
527 if (newLink->fNext !=
nullptr) {
528 newLink->fNext->fPrev = newLink;
530 if (newLink->fNext ==
nullptr) {
534 Assert (newLink->fNext->fPrev == newLink);
538#if qStroika_Foundation_Debug_AssertionsChecked
539 template <
typename T>
542#if qStroika_Foundation_Containers_DataStructures_DoublyLinkedList_IncludeSlowDebugChecks_
543 AssertExternallySynchronizedMutex::ReadContext declareContext{*
this};
545 if (fHead_ !=
nullptr) {
546 Assert (fHead_->fPrev ==
nullptr);
547 if (fHead_->fNext ==
nullptr) {
548 Assert (fHead_ == fTail_);
551 Assert (fHead_->fNext->fPrev == fHead_);
554 if (fTail_ !=
nullptr) {
555 Assert (fTail_->fNext ==
nullptr);
556 if (fTail_->fPrev ==
nullptr) {
557 Assert (fHead_ == fTail_);
560 Assert (fTail_->fPrev->fNext == fTail_);
563 Assert (fHead_ ==
nullptr or fHead_->fPrev ==
nullptr);
564 Assert (fTail_ ==
nullptr or fTail_->fNext ==
nullptr);
569 size_t forwardCounter = 0;
570 for (Link_* i = fHead_; i !=
nullptr; i = i->fNext) {
571 Assert (i->fNext ==
nullptr or i->fNext->fPrev == i);
574 size_t backwardCounter{};
575 for (Link_* i = fTail_; i !=
nullptr; i = i->fPrev) {
576 Assert (i->fPrev ==
nullptr or i->fPrev->fNext == i);
579 Assert (forwardCounter == backwardCounter);
588 template <
typename T>
589 constexpr DoublyLinkedList<T>::ForwardIterator::ForwardIterator ([[maybe_unused]]
const DoublyLinkedList* data, UnderlyingIteratorRep startAt) noexcept
591#if qStroika_Foundation_Debug_AssertionsChecked
596 template <
typename T>
597 constexpr DoublyLinkedList<T>::ForwardIterator::ForwardIterator (
const DoublyLinkedList* data) noexcept
601 template <
typename T>
602 inline void DoublyLinkedList<T>::ForwardIterator::Invariant () const noexcept
604#if qStroika_Foundation_Debug_AssertionsChecked
608 template <
typename T>
609 inline DoublyLinkedList<T>::ForwardIterator::operator bool ()
const
613 template <
typename T>
614 inline bool DoublyLinkedList<T>::ForwardIterator::Done () const noexcept
616#if qStroika_Foundation_Debug_AssertionsChecked
617 if (fData_ !=
nullptr) {
618 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
622 return fCurrent_ ==
nullptr;
624 template <
typename T>
625 inline auto DoublyLinkedList<T>::ForwardIterator::operator++ () noexcept -> ForwardIterator&
627 Require (not Done ());
629 Assert (fCurrent_ !=
nullptr);
630 fCurrent_ = fCurrent_->fNext;
634 template <
typename T>
635 inline auto DoublyLinkedList<T>::ForwardIterator::operator++ (
int)
noexcept -> ForwardIterator
637 ForwardIterator result = *
this;
641 template <
typename T>
642 inline const T& DoublyLinkedList<T>::ForwardIterator::operator* ()
const
644#if qStroika_Foundation_Debug_AssertionsChecked
646 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
648 Require (not Done ());
651 return fCurrent_->fItem;
653 template <
typename T>
654 inline const T* DoublyLinkedList<T>::ForwardIterator::operator->()
const
656#if qStroika_Foundation_Debug_AssertionsChecked
658 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
660 Require (not Done ());
663 return &fCurrent_->fItem;
665 template <
typename T>
666 size_t DoublyLinkedList<T>::ForwardIterator::CurrentIndex (
const DoublyLinkedList* data)
const
668 Require (not Done ());
669#if qStroika_Foundation_Debug_AssertionsChecked
670 Require (data == fData_);
675 for (
const Link_* l = data->fHead_;; l = l->fNext, ++i) {
677 if (l == fCurrent_) [[unlikely]] {
684 template <
typename T>
685 inline auto DoublyLinkedList<T>::ForwardIterator::GetUnderlyingIteratorRep () const -> UnderlyingIteratorRep
689 template <
typename T>
690 inline void DoublyLinkedList<T>::ForwardIterator::SetUnderlyingIteratorRep (UnderlyingIteratorRep l)
692#if qStroika_Foundation_Debug_AssertionsChecked
693 AssertExternallySynchronizedMutex::ReadContext declareContext{*fData_};
699 template <
typename T>
700 constexpr void DoublyLinkedList<T>::ForwardIterator::AssertDataMatches ([[maybe_unused]]
const DoublyLinkedList* data)
const
702#if qStroika_Foundation_Debug_AssertionsChecked
703 Require (data == fData_);
706 template <
typename T>
707 inline bool DoublyLinkedList<T>::ForwardIterator::operator== (
const ForwardIterator& rhs)
const
709 return fCurrent_ == rhs.fCurrent_;
711#if qStroika_Foundation_Debug_AssertionsChecked
712 template <
typename T>
713 void DoublyLinkedList<T>::ForwardIterator::Invariant_ () const noexcept