Changeset c71c171 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:
73066e61
Parents:
de53138
git-author:
Dzejrou <dzejrou@…> (2018-04-20 00:18:51)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:21)
Message:

cpp: added constructors, assignments and basic modifiers to std::list

File:
1 edited

Legend:

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

    rde53138 rc71c171  
    3030#define LIBCPP_LIST
    3131
     32#include <cstdlib>
    3233#include <iterator>
    3334#include <memory>
    3435#include <utility>
    3536
    36 namespace cpp
     37namespace std
    3738{
     39    template<class T, class Allocator = allocator<T>>
     40    class list;
     41
    3842    namespace aux
    3943    {
     
    4448            list_node* next;
    4549            list_node* prev;
     50
     51            template<class... Args>
     52            list_node(Args&&... args)
     53                : value{forward<Args>(args)...},
     54                  next{this}, prev{this}
     55            {
     56                next = this;
     57                prev = this;
     58            }
     59
     60            list_node(const T& val)
     61                : value{val}, next{this}, prev{this}
     62            {
     63                next = this;
     64                prev = this;
     65            }
     66
     67            list_node(T&& val)
     68                : value{forward<T>(val)}, next{}, prev{}
     69            {
     70                next = this;
     71                prev = this;
     72            }
     73
     74            void append(list_node* node)
     75            {
     76                node->next = next;
     77                node->prev = this;
     78                next->prev = node;
     79                next = node;
     80            }
     81
     82            void prepend(list_node* node)
     83            {
     84                node->next = this;
     85                node->prev = prev;
     86                prev->next = node;
     87                prev = node;
     88            }
    4689        };
     90
     91        template<class T>
     92        class list_const_iterator;
     93
     94        template<class T>
     95        class list_iterator
     96        {
     97            public:
     98                using reference = typename list<T>::reference;
     99
     100                list_iterator(list_node<T>* node = nullptr)
     101                    : current_{node}
     102                { /* DUMMY BODY */ }
     103
     104                reference operator*()
     105                {
     106                    return current_->value;
     107                }
     108
     109                list_iterator& operator++()
     110                {
     111                    if (current_)
     112                        current_ = current_->next;
     113
     114                    return *this;
     115                }
     116
     117                list_iterator operator++(int)
     118                {
     119                    auto bckp = current_;
     120
     121                    if (current_)
     122                        current_ = current_->next;
     123
     124                    return list_iterator{bckp};
     125                }
     126
     127                list_iterator& operator--()
     128                {
     129                    if (current_)
     130                        current_ = current_->prev;
     131
     132                    return *this;
     133                }
     134
     135                list_iterator operator--(int)
     136                {
     137                    auto bckp = current_;
     138
     139                    if (current_)
     140                        current_ = current_->prev;
     141
     142                    return list_iterator{bckp};
     143                }
     144
     145                list_node<T>* node()
     146                {
     147                    return current_;
     148                }
     149
     150            private:
     151                list_node<T>* current_;
     152        };
     153
     154        // TODO: const iterator, iterator must be convertible to const iterator
    47155    }
    48156
     
    51159     */
    52160
    53     template<class T, class Allocator = allocator<T>>
     161    template<class T, class Allocator>
    54162    class list
    55163    {
     
    57165            using value_type      = T;
    58166            using reference       = value_type&;
    59             using const_reference = value_type&;
     167            using const_reference = const value_type&;
    60168            using allocator_type  = Allocator;
    61169
    62             using iterator        = void;
    63             using const_iterator  = void;
    64             using size_type       = void;
    65             using difference_type = void;
     170            using iterator        = aux::list_iterator<value_type>;
     171            using const_iterator  = aux::list_const_iterator<value_type>;
     172            using size_type       = size_t;
     173            using difference_type = ptrdiff_t;
    66174
    67175            using pointer       = typename allocator_traits<allocator_type>::pointer;
     
    69177
    70178            using reverse_iterator       = std::reverse_iterator<iterator>;
    71             using const_reverse_iterator = std::const_reverse_iterator<iterator>;
     179            using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    72180
    73181            /**
     
    80188
    81189            explicit list(const allocator_type& alloc)
    82                 : allocator_{alloc}, head_{nullptr}
     190                : allocator_{alloc}, head_{nullptr}, size_{}
    83191            { /* DUMMY BODY */ }
    84192
    85193            explicit list(size_type n, const allocator_type& alloc = allocator_type{})
    86                 : allocator_{alloc}, head_{nullptr}
    87             {
    88                 for (size_type i = 0; i < n; ++i)
    89                 {
    90                     auto node = append_new_();
    91                     allocator_.construct(&node->value);
    92                 }
     194                : allocator_{alloc}, head_{nullptr}, size_{}
     195            {
     196                init_(
     197                    aux::insert_iterator<value_type>{value_type{}},
     198                    aux::insert_iterator<value_type>{size_}
     199                );
    93200            }
    94201
    95202            list(size_type n, const value_type& val,
    96203                 const allocator_type& alloc = allocator_type{})
    97                 : allocator_{alloc}, head_{nullptr}
    98             {
    99                 for (size_type i = 0; i < n; ++i)
    100                 {
    101                     auto node = append_new_();
    102                     allocator_.construct(&node->value, val);
    103                 }
     204                : allocator_{alloc}, head_{nullptr}, size_{}
     205            {
     206                init_(
     207                    aux::insert_iterator<value_type>{val},
     208                    aux::insert_iterator<value_type>{n}
     209                );
    104210            }
    105211
     
    107213            list(InputIterator first, InputIterator last,
    108214                 const allocator_type& alloc = allocator_type{})
    109                 : allocator_{alloc}, head_{nullptr}
     215                : allocator_{alloc}, head_{nullptr}, size_{}
     216            {
     217                init_(first, last);
     218            }
     219
     220            list(const list& other)
     221                : list{other, other.allocator_}
     222            { /* DUMMY BODY */ }
     223
     224            list(list&& other)
     225                : allocator_{move(other.allocator_)},
     226                  head_{move(other.head_)},
     227                  size_{move(other.size_)}
     228            {
     229                other.head_ = nullptr;
     230            }
     231
     232            list(const list& other, const allocator_type alloc)
     233                : allocator_{alloc}, head_{nullptr}, size_{other.size_}
     234            {
     235                init_(other.begin(), other.end());
     236            }
     237
     238            list(list&& other, const allocator_type& alloc)
     239                : allocator_{alloc},
     240                  head_{move(other.head_)},
     241                  size_{move(other.size_)}
     242            {
     243                other.head_ = nullptr;
     244            }
     245
     246            list(initializer_list<value_type> init, const allocator_type& alloc)
     247                : allocator_{alloc}, head_{nullptr}, size_{}
     248            {
     249                init_(init.begin(), init.end());
     250            }
     251
     252            ~list()
     253            {
     254                fini_();
     255            }
     256
     257            list& operator=(const list& other)
     258            {
     259                fini_();
     260
     261                allocator_ = other.allocator_;
     262
     263                init_(other.begin(), other.end());
     264            }
     265
     266            list& operator=(list&& other)
     267                noexcept(allocator_traits<allocator_type>::is_always_equal::value)
     268            {
     269                fini_();
     270
     271                allocator_ = move(other.allocator_);
     272
     273                init_(
     274                    make_move_iterator(other.begin()),
     275                    make_move_iterator(other.end())
     276                );
     277            }
     278
     279            list& operator=(initializer_list<value_type> init)
     280            {
     281                fini_();
     282
     283                init_(init.begin(), init.end());
     284            }
     285
     286            template<class InputIterator>
     287            void assign(InputIterator first, InputIterator last)
     288            {
     289                fini_();
     290
     291                init_(first, last);
     292            }
     293
     294            void assign(size_type n, const value_type& val)
     295            {
     296                fini_();
     297
     298                init_(
     299                    aux::insert_iterator<value_type>{val},
     300                    aux::insert_iterator<value_type>{n}
     301                );
     302            }
     303
     304            void assign(initializer_list<value_type> init)
     305            {
     306                fini_();
     307
     308                init_(init.begin(), init.end());
     309            }
     310
     311            allocator_type get_allocator() const noexcept
     312            {
     313                return allocator_;
     314            }
     315
     316            iterator begin() noexcept
     317            {
     318                return iterator{head_};
     319            }
     320
     321            const_iterator begin() const noexcept
     322            {
     323                return cbegin();
     324            }
     325
     326            iterator end() noexcept
     327            {
     328                return iterator{};
     329            }
     330
     331            const_iterator end() const noexcept
     332            {
     333                return cend();
     334            }
     335
     336            reverse_iterator rbegin() noexcept
     337            {
     338                return make_reverse_iterator(end());
     339            }
     340
     341            const_reverse_iterator rbegin() const noexcept
     342            {
     343                return make_reverse_iterator(cend());
     344            }
     345
     346            reverse_iterator rend() noexcept
     347            {
     348                return make_reverse_iterator(begin());
     349            }
     350
     351            const_reverse_iterator rend() const noexcept
     352            {
     353                return make_reverse_iterator(cbegin());
     354            }
     355
     356            const_iterator cbegin() const noexcept
     357            {
     358                return const_iterator{head_};
     359            }
     360
     361            const_iterator cend() const noexcept
     362            {
     363                return const_iterator{};
     364            }
     365
     366            const_reverse_iterator crbegin() const noexcept
     367            {
     368                return rbegin();
     369            }
     370
     371            /**
     372             * 23.3.5.3, capacity:
     373             */
     374
     375            bool empty() const noexcept
     376            {
     377                return size_ == 0;
     378            }
     379
     380            size_type size() const noexcept
     381            {
     382                return size_;
     383            }
     384
     385            size_type max_size() const noexcept
     386            {
     387                return allocator_traits<allocator_type>::max_size(allocator_);
     388            }
     389
     390            void resize(size_type sz)
     391            {
     392                // TODO: implement
     393            }
     394
     395            void resize(size_type sz, const value_type& val)
     396            {
     397                // TODO: implement
     398            }
     399
     400            reference front()
     401            {
     402                // TODO: bounds checking
     403                return head_->value;
     404            }
     405
     406            const_reference front() const
     407            {
     408                // TODO: bounds checking
     409                return head_->value;
     410            }
     411
     412            reference back()
     413            {
     414                // TODO: bounds checking
     415                return head_->prev->value;
     416            }
     417
     418            const_reference back() const
     419            {
     420                // TODO: bounds checking
     421                return head_->prev->value;
     422            }
     423
     424            /**
     425             * 23.3.5.4, modifiers:
     426             * Note: These should have no effect when an exception
     427             *       is thrown while inserting, but since the only
     428             *       functions that can throw are the constructors,
     429             *       creating the node before any modifications to the
     430             *       list itself will satisfy this requirement.
     431             */
     432
     433            template<class... Args>
     434            void emplace_front(Args&&... args)
     435            {
     436                prepend_new_(forward<Args>(args)...);
     437            }
     438
     439            void pop_front()
     440            {
     441                if (head_)
     442                {
     443                    --size_;
     444
     445                    if (head_->next == head_)
     446                    {
     447                        delete head_;
     448                        head_ = nullptr;
     449                    }
     450                    else
     451                    {
     452                        auto tmp = head_;
     453                        head_->prev->next = head_->next;
     454                        head_->next->prev = head_->prev;
     455                        head_ = head_->next;
     456
     457                        delete tmp;
     458                    }
     459                }
     460            }
     461
     462            template<class... Args>
     463            void emplace_back(Args&&... args)
     464            {
     465                append_new_(forward<Args>(args)...);
     466            }
     467
     468            void push_front(const value_type& value)
     469            {
     470                prepend_new_(value);
     471            }
     472
     473            void push_front(value_type&& value)
     474            {
     475                prepend_new_(forward<value_type>(value));
     476            }
     477
     478            void push_back(const value_type& value)
     479            {
     480                append_new_(value);
     481            }
     482
     483            void push_back(value_type&& value)
     484            {
     485                append_new_(forward<value_type>(value));
     486            }
     487
     488            void pop_back()
     489            {
     490                if (head_)
     491                {
     492                    --size_;
     493                    auto target = head_->prev;
     494
     495                    if (!target)
     496                    {
     497                        delete head_;
     498                        head_ = nullptr;
     499                    }
     500                    else
     501                    {
     502                        auto tmp = target;
     503                        target->prev->next = target->next;
     504                        target->next->prev = target->prev;
     505                        target = target->next;
     506
     507                        delete tmp;
     508                    }
     509                }
     510            }
     511
     512        /* private: */
     513            allocator_type allocator_;
     514            aux::list_node<value_type>* head_;
     515            size_type size_;
     516
     517            template<class InputIterator>
     518            void init_(InputIterator first, InputIterator last)
    110519            {
    111520                while (first != last)
     
    116525            }
    117526
    118             list(const list& other)
    119                 : allocator_{other.allocator_}, head_{nullptr}
    120             {
    121                 auto tmp = other.head_;
    122 
    123                 while (tmp->next != other.head_)
    124                 {
    125                     auto node = append_new_();
    126                     allocator_.construct(&node->value, tmp->value);
    127                 }
    128             }
    129 
    130             list(list&& other)
    131             {
    132                 // TODO:
    133             }
    134 
    135         private:
    136             allocator_type allocator_;
    137             list_node<T>* head_;
    138 
    139             list_node<T>* append_new_()
    140             {
    141                 auto node = new aux::list_node<T>{};
     527            void fini_()
     528            {
     529                if (!head_)
     530                    return;
     531
     532                for (size_type i = size_type{}; i < size_; ++i)
     533                {
     534                    head_ = head_->next;
     535                    delete head_->prev;
     536                }
     537
     538                head_ = nullptr;
     539                size_ = size_type{};
     540            }
     541
     542            template<class... Args>
     543            aux::list_node<value_type>* append_new_(Args&&... args)
     544            {
     545                auto node = new aux::list_node<value_type>{forward<Args>(args)...};
    142546                auto last = get_last_();
    143547
     
    145549                    head_ = node;
    146550                else
    147                 {
    148                     last->next = node;
    149                     node->prev = last;
    150 
    151                     node->next = head_;
    152                     head_->prev = node;
    153                 }
     551                    last->append(node);
     552
     553                ++size_;
    154554
    155555                return node;
    156556            }
    157557
    158             list_node<T>* get_last_()
     558            template<class... Args>
     559            aux::list_node<value_type>* prepend_new_(Args&&... args)
     560            {
     561                auto node = new aux::list_node<value_type>{forward<Args>(args)...};
     562
     563                if (!head_)
     564                    head_ = node;
     565                else
     566                {
     567                    head_->prepend(node);
     568                    head_ = head_->prev;
     569                }
     570
     571                ++size_;
     572
     573                return node;
     574            }
     575
     576            aux::list_node<value_type>* get_last_()
    159577            {
    160578                if (!head_)
    161579                    return nullptr;
    162580
    163                 auto node = head_;
    164 
    165                 while (node->next != head_)
    166                     node = node->next;
     581                return head_->prev;
     582            }
     583
     584            template<class InputIterator>
     585            void insert_range_(InputIterator first, InputIterator last,
     586                               aux::list_node<value_type>* where = nullptr)
     587            {
     588                if (first == last)
     589                    return;
     590
     591                if (!where)
     592                    where = get_last_();
     593
     594                while (first != last)
     595                {
     596                    where->append(new aux::list_node<value_type>{*first++});
     597                    where = where->next;
     598                }
    167599            }
    168600    };
Note: See TracChangeset for help on using the changeset viewer.