361 }; |
375 }; |
362 |
376 |
363 |
377 |
364 |
378 |
365 |
379 |
|
380 /****************************************************************************** |
|
381 * |
|
382 * ITERABLE DOUBLY-LINKED CIRCULAR LIST |
|
383 * |
|
384 ******************************************************************************/ |
|
385 |
|
386 /** |
|
387 @internalComponent |
|
388 |
|
389 An object that forms part of an iterable doubly linked list. |
|
390 |
|
391 SIterDQLink can also be embedded within another object so that that object |
|
392 can form part of the doubly linked list. |
|
393 |
|
394 @see SIterDQ |
|
395 */ |
|
396 struct SIterDQ; |
|
397 struct SIterDQIterator; |
|
398 struct SIterDQLink |
|
399 { |
|
400 |
|
401 /** |
|
402 Default constructor; only defined for debug builds. |
|
403 |
|
404 It initialises the link pointers. |
|
405 */ |
|
406 FORCE_INLINE SIterDQLink() {iNext=iPrev=0;} |
|
407 |
|
408 enum |
|
409 { |
|
410 ENonAddressMask=3u, |
|
411 EIterator=1u, |
|
412 EAnchor=2u, |
|
413 }; |
|
414 |
|
415 FORCE_INLINE SIterDQLink* Next() const |
|
416 { return (SIterDQLink*)(iNext & ~ENonAddressMask); } |
|
417 |
|
418 FORCE_INLINE SIterDQLink* Prev() const |
|
419 { return (SIterDQLink*)(iPrev & ~ENonAddressMask); } |
|
420 |
|
421 FORCE_INLINE TBool IsObject() const |
|
422 { return !(iNext & ENonAddressMask); } |
|
423 |
|
424 FORCE_INLINE TBool IsIterator() const |
|
425 { return iNext & EIterator; } |
|
426 |
|
427 FORCE_INLINE TBool IsAnchor() const |
|
428 { return iNext & EAnchor; } |
|
429 |
|
430 FORCE_INLINE void SetNext(SIterDQLink* aNext) |
|
431 { iNext = (iNext & ENonAddressMask) | (TUintPtr(aNext) & ~ENonAddressMask); } |
|
432 |
|
433 FORCE_INLINE void SetPrev(SIterDQLink* aPrev) |
|
434 { iPrev = (iPrev & ENonAddressMask) | (TUintPtr(aPrev) & ~ENonAddressMask); } |
|
435 |
|
436 /** |
|
437 Removes this link item from the doubly linked list. |
|
438 |
|
439 @return A pointer to this link item. |
|
440 */ |
|
441 FORCE_INLINE SIterDQLink* Deque() |
|
442 { |
|
443 SIterDQLink* next = Next(); |
|
444 SIterDQLink* prev = Prev(); |
|
445 next->SetPrev(prev); |
|
446 prev->SetNext(next); |
|
447 #ifdef _DEBUG |
|
448 SetNext((SIterDQLink*)4); |
|
449 SetPrev((SIterDQLink*)4); |
|
450 #endif |
|
451 return this; |
|
452 } |
|
453 |
|
454 |
|
455 /** |
|
456 Inserts this link item into the list so that it precedes the specified link item. |
|
457 |
|
458 @param aL A pointer to the link item which is to follow this link item. |
|
459 */ |
|
460 FORCE_INLINE void InsertBefore(SIterDQLink* aL) |
|
461 { |
|
462 SIterDQLink* prev = aL->Prev(); |
|
463 SetNext(aL); |
|
464 SetPrev(prev); |
|
465 prev->SetNext(this); |
|
466 aL->SetPrev(this); |
|
467 } |
|
468 |
|
469 |
|
470 /** |
|
471 Inserts this link item into the list so that it follows the specified link item. |
|
472 |
|
473 @param aL A pointer to the link item which is to precede this link item. |
|
474 */ |
|
475 FORCE_INLINE void InsertAfter(SIterDQLink* aL) |
|
476 { |
|
477 SIterDQLink* next = aL->Next(); |
|
478 SetPrev(aL); |
|
479 SetNext(next); |
|
480 next->SetPrev(this); |
|
481 aL->SetNext(this); |
|
482 } |
|
483 |
|
484 |
|
485 /** |
|
486 Tests whether this is the only link item in the list. |
|
487 |
|
488 @return True, if this is the only link item in the list; false, otherwise. |
|
489 */ |
|
490 FORCE_INLINE TBool Alone() const |
|
491 { return (iNext==iPrev); } |
|
492 |
|
493 private: |
|
494 /** |
|
495 Bits 2-31 = Address of the next link item in the list. |
|
496 Bit 0 = 1 for iterator, 0 for object |
|
497 */ |
|
498 TUintPtr iNext; |
|
499 |
|
500 /** |
|
501 Bits 2-31 = Address of the previous link item in the list. |
|
502 Bit 0 = 1 for iterator, 0 for object |
|
503 */ |
|
504 TUintPtr iPrev; |
|
505 |
|
506 friend struct SIterDQ; |
|
507 friend struct SIterDQIterator; |
|
508 }; |
|
509 |
|
510 |
|
511 |
|
512 |
|
513 /** |
|
514 @internalComponent |
|
515 |
|
516 Anchor for an iterable circular doubly linked list of SIterDQLink items. |
|
517 |
|
518 @see SIterDQLink |
|
519 */ |
|
520 struct SIterDQ |
|
521 { |
|
522 |
|
523 /** |
|
524 Default constructor. |
|
525 */ |
|
526 FORCE_INLINE SIterDQ() |
|
527 { iA.iNext = iA.iPrev = TUintPtr(&iA)|SIterDQLink::EAnchor; } |
|
528 |
|
529 |
|
530 /** |
|
531 Moves link items from the specified list onto this list, and clears the specified list |
|
532 |
|
533 @param aQ The source linked list. This list must not be empty. |
|
534 */ |
|
535 inline SIterDQ(SIterDQ* aQ, TInt) // move entries from aQ onto this queue and clear aQ - aQ must not be empty |
|
536 { iA.iNext=aQ->iA.iNext; iA.iPrev=aQ->iA.iPrev; First()->SetPrev(&iA); Last()->SetNext(&iA); new (aQ) SIterDQ; } |
|
537 |
|
538 |
|
539 /** |
|
540 Tests whether this doubly linked list is empty. |
|
541 |
|
542 @return True, if the list is empty; false, otherwise. |
|
543 */ |
|
544 FORCE_INLINE TBool IsEmpty() const |
|
545 { return (iA.iNext &~ SIterDQLink::ENonAddressMask) == TUintPtr(&iA); } |
|
546 |
|
547 |
|
548 /** |
|
549 Gets a pointer to the first item in this doubly linked list. |
|
550 |
|
551 @return A pointer to the first item. |
|
552 */ |
|
553 FORCE_INLINE SIterDQLink* First() const |
|
554 { return iA.Next(); } |
|
555 |
|
556 |
|
557 /** |
|
558 Gets a pointer to the last item in this doubly linked list. |
|
559 |
|
560 @return A pointer to the last item. |
|
561 */ |
|
562 FORCE_INLINE SIterDQLink* Last() const |
|
563 { return iA.Prev(); } |
|
564 |
|
565 |
|
566 /** |
|
567 Adds the specified link item onto the end of this doubly linked list. |
|
568 |
|
569 @param aL A pointer to the link item to be added. |
|
570 */ |
|
571 FORCE_INLINE void Add(SIterDQLink* aL) |
|
572 { |
|
573 aL->InsertBefore(&iA); |
|
574 } |
|
575 |
|
576 |
|
577 /** |
|
578 Adds the specified link item onto the front of this doubly linked list. |
|
579 |
|
580 @param aL A pointer to the link item to be added. |
|
581 */ |
|
582 FORCE_INLINE void AddHead(SIterDQLink* aL) |
|
583 { |
|
584 aL->InsertAfter(&iA); |
|
585 } |
|
586 |
|
587 |
|
588 /** |
|
589 Gets the first link item in the linked list. |
|
590 |
|
591 @return The first link item in the list; NULL, if the list is empty. |
|
592 */ |
|
593 inline SIterDQLink* GetFirst() |
|
594 { if (IsEmpty()) return NULL; else return First()->Deque(); } |
|
595 |
|
596 |
|
597 /** |
|
598 Gets the last link item in the linked list. |
|
599 |
|
600 @return The last link item in the list; NULL, if the list is empty. |
|
601 */ |
|
602 inline SIterDQLink* GetLast() |
|
603 { if (IsEmpty()) return NULL; else return Last()->Deque(); } |
|
604 |
|
605 |
|
606 /** |
|
607 Appends entries from the specified linked list onto this list, and clears |
|
608 the specified link list anchor. |
|
609 |
|
610 @param aQ The source linked list. |
|
611 */ |
|
612 inline void MoveFrom(SIterDQ* aQ) // append entries from aQ onto this queue and clear aQ |
|
613 { if (!aQ->IsEmpty()) |
|
614 { |
|
615 SIterDQLink* last = Last(); // last current |
|
616 SIterDQLink* fx = aQ->First(); // first extra |
|
617 SIterDQLink* lx = aQ->Last(); // last extra |
|
618 last->SetNext(fx); |
|
619 fx->SetPrev(last); |
|
620 iA.SetPrev(lx); |
|
621 lx->SetNext(&iA); |
|
622 new (aQ) SIterDQ; |
|
623 } |
|
624 } |
|
625 |
|
626 private: |
|
627 /** |
|
628 The anchor point for the doubly linked list. |
|
629 */ |
|
630 SIterDQLink iA; |
|
631 }; |
|
632 |
|
633 |
|
634 #ifdef __VC32__ |
|
635 #pragma warning( disable : 4127 ) // conditional expression is constant |
|
636 #endif |
|
637 |
|
638 /** |
|
639 @internalComponent |
|
640 |
|
641 Iterator for an iterable circular doubly linked list of SIterDQLink items. |
|
642 |
|
643 @see SIterDQLink |
|
644 @see SIterDQ |
|
645 */ |
|
646 struct SIterDQIterator : public SIterDQLink |
|
647 { |
|
648 |
|
649 /** |
|
650 Default constructor. |
|
651 |
|
652 Iterator starts out not attached to any queue |
|
653 */ |
|
654 FORCE_INLINE SIterDQIterator() |
|
655 { iNext = iPrev = SIterDQLink::EIterator; } |
|
656 |
|
657 /** |
|
658 Destructor ensures iterator detached before destruction |
|
659 */ |
|
660 FORCE_INLINE ~SIterDQIterator() |
|
661 { |
|
662 #ifdef _DEBUG |
|
663 if (iNext != SIterDQLink::EIterator) { __crash(); } |
|
664 #endif |
|
665 } |
|
666 |
|
667 /** |
|
668 Detach the iterator if it is currently attached to a queue |
|
669 */ |
|
670 FORCE_INLINE void Detach() |
|
671 { if (Next()) {Deque(); SetNext(0);} } |
|
672 |
|
673 /** |
|
674 Attach the iterator to a queue at the beginning. |
|
675 */ |
|
676 FORCE_INLINE void Attach(SIterDQ* aQ) |
|
677 { |
|
678 #ifdef _DEBUG |
|
679 if (iNext != SIterDQLink::EIterator) { __crash(); } |
|
680 #endif |
|
681 aQ->AddHead(this); |
|
682 } |
|
683 |
|
684 /** |
|
685 Step the iterator over the next object. |
|
686 Return KErrNone if we stepped over an object. |
|
687 Return KErrEof if we reached the end of the list. |
|
688 Return KErrGeneral if we stepped over aMaxSteps other iterators. |
|
689 In first case aObj is set to point to the object stepped over. |
|
690 In other cases aObj is set to NULL. |
|
691 */ |
|
692 TInt Step(SIterDQLink*& aObj, TInt aMaxSteps=0); // 0 means use default value |
|
693 |
|
694 }; |
|
695 |
|
696 #ifdef __VC32__ |
|
697 #pragma warning( default : 4127 ) // conditional expression is constant |
|
698 #endif |
|
699 |
|
700 |
|
701 |
|
702 /****************************************************************************** |
|
703 * |
|
704 * ORDERED DOUBLY-LINKED CIRCULAR LIST |
|
705 * |
|
706 ******************************************************************************/ |
|
707 |
366 /** |
708 /** |
367 @publishedPartner |
709 @publishedPartner |
368 @released |
710 @released |
369 |
711 |
370 An object that forms part of a doubly linked list arranged |
712 An object that forms part of a doubly linked list arranged |