Changeset 79c9e0f in mainline


Ignore:
Timestamp:
2018-07-05T21:41:21Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5af0bc9
Parents:
eb3c271
git-author:
Dzejrou <dzejrou@…> (2018-04-20 18:00:07)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:21)
Message:

cpp: added list::splice

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/impl/list.hpp

    reb3c271 r79c9e0f  
    11/*
    2  * Copyright (c) 2017 Jaroslav Jindrak
     2 * Copyright (c) 2018 Jaroslav Jindrak
    33 * All rights reserved.
    44 *
     
    9393        {
    9494            public:
    95                 using value_type = typename list<T>::value_type;
    96                 using reference  = typename list<T>::const_reference;
     95                using value_type      = typename list<T>::value_type;
     96                using reference       = typename list<T>::const_reference;
     97                using pointer         = typename list<T>::const_pointer;
     98                using difference_type = typename list<T>::difference_type;
     99                using size_type       = typename list<T>::size_type;
    97100
    98101                using iterator_category = forward_iterator_tag;
     
    172175        {
    173176            public:
    174                 using value_type = typename list<T>::value_type;
    175                 using reference  = typename list<T>::reference;
     177                using value_type      = typename list<T>::value_type;
     178                using reference       = typename list<T>::reference;
     179                using pointer         = typename list<T>::pointer;
     180                using difference_type = typename list<T>::difference_type;
     181                using size_type       = typename list<T>::size_type;
    176182
    177183                using iterator_category = forward_iterator_tag;
     
    342348            }
    343349
    344             list(initializer_list<value_type> init, const allocator_type& alloc)
     350            list(initializer_list<value_type> init, const allocator_type& alloc = allocator_type{})
    345351                : allocator_{alloc}, head_{nullptr}, size_{}
    346352            {
     
    726732            }
    727733
     734            /**
     735             * 23.3.5.5, list operations:
     736             */
     737
     738            void splice(const_iterator position, list& other)
     739            {
     740                if (!head_)
     741                {
     742                    swap(other);
     743                    return;
     744                }
     745
     746                auto other_first = other.head_;
     747                auto other_last = other.get_last_();
     748                auto node = position.node();
     749                auto prev = node->prev;
     750
     751                // Insert a link range.
     752                prev->next = other_first;
     753                other_first->prev = prev;
     754                node->prev = other_last;
     755                other_last->next = node;
     756
     757                size_ += other.size_;
     758
     759                if (node == head_)
     760                    head_ = other_first;
     761                other.head_ = nullptr;
     762                other.size_ = 0;
     763            }
     764
     765            void splice(const_iterator position, list&& other)
     766            {
     767                splice(position, other);
     768            }
     769
     770            void splice(const_iterator position, list& other, const_iterator it)
     771            {
     772                if (&other == this)
     773                    return;
     774
     775                auto node = position.node();
     776                auto target = it.node();
     777
     778                // Unlink from other.
     779                target->prev->next = target->next;
     780                target->next->prev = target->prev;
     781
     782                // Link to us.
     783                node->prev->next = target;
     784                target->prev = node->prev;
     785
     786                node->prev = target;
     787                target->next = node;
     788
     789                --other.size_;
     790                ++size_;
     791
     792                if (it.node() == other.head_)
     793                    other.advance_head_();
     794            }
     795
     796            void splice(const_iterator position, list&& other, const_iterator it)
     797            {
     798                splice(position, other, it);
     799            }
     800
     801            void splice(const_iterator position, list& other,
     802                        const_iterator first, const_iterator last)
     803            {
     804                if (&other == this || other.empty())
     805                    return;
     806
     807                if (first.node() == other.head_ && !last.node())
     808                { // [first, last) is everything in other.
     809                    splice(position, other);
     810                    return;
     811                }
     812
     813                // [first_node, last_node] is the inserted range.
     814                aux::list_node<value_type>* first_node{};
     815                aux::list_node<value_type>* last_node{};
     816
     817                if (first.node() == other.head_)
     818                { // The range is a prefix of other.
     819                    other.head_ = last.node();
     820                    other.head_->prev = first.node()->prev;
     821                    first.node()->prev->next = last.node();
     822
     823                    first_node = first.node();
     824                    last_node = last.node()->prev;
     825                }
     826                else if (!last.node())
     827                { // The range is a suffix of other.
     828                    auto new_last = first.node()->prev;
     829                    auto old_last = other.head_->prev;
     830                    other.head_->prev = new_last;
     831                    new_last->next = other.head_;
     832
     833                    first_node = first.node();
     834                    last_node = old_last;
     835                }
     836                else
     837                { // The range is a subrange of other.
     838                    first_node = first.node();
     839                    last_node = last.node()->prev;
     840
     841                    first_node->prev->next = last.node();
     842                    last.node()->prev = first_node->prev;
     843                }
     844
     845                if (!head_)
     846                { // Assimilate the range.
     847                    head_ = first_node;
     848                    first_node->prev = last_node;
     849                    last_node->next = first_node;
     850                }
     851                else
     852                {
     853                    auto target = position.node();
     854                    target->prev->next = first_node;
     855                    first_node->prev = target->prev;
     856
     857                    target->prev = last_node;
     858                    last_node->next = target;
     859                }
     860
     861                auto count = distance(iterator{first_node}, iterator{last_node});
     862                size_ += count;
     863                other.size_ -= count;
     864            }
     865
     866            void splice(const_iterator position, list&& other,
     867                        const_iterator first, const_iterator last)
     868            {
     869                splice(position, other, first, last);
     870            }
     871
    728872        private:
    729873            allocator_type allocator_;
     
    746890                    return;
    747891
    748                 for (size_type i = size_type{}; i < size_; ++i)
    749                 {
     892                head_->prev->next = nullptr;
     893                while (head_)
     894                {
     895                    auto tmp = head_;
    750896                    head_ = head_->next;
    751                     delete head_->prev;
     897
     898                    delete tmp;
    752899                }
    753900
     
    814961                }
    815962            }
     963
     964            void advance_head_()
     965            {
     966                if (size_ == 1)
     967                {
     968                    head_ = nullptr;
     969                    size_ = 0;
     970                }
     971                else
     972                { // The head_ is deleted outside.
     973                    head_->next->prev = head_->prev;
     974                    head_->prev->next = head_->next;
     975                    head_ = head_->next;
     976                }
     977            }
    816978    };
    817979}
Note: See TracChangeset for help on using the changeset viewer.