Changeset 9019d85 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:
f9ce7cd
Parents:
bdc55009
git-author:
Dzejrou <dzejrou@…> (2018-04-17 19:05:01)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:21)
Message:

cpp: added insert and emplace for deque

File:
1 edited

Legend:

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

    rbdc55009 r9019d85  
    3030#define LIBCPP_DEQUE
    3131
     32#include <algorithm>
    3233#include <initializer_list>
     34#include <internal/insert_iterator.hpp>
    3335#include <iterator>
    3436#include <memory>
     
    5153
    5254        template<class T, class Allocator>
     55        class deque_iterator;
     56
     57        template<class T, class Allocator>
    5358        class deque_const_iterator
    5459        {
     
    6570                { /* DUMMY BODY */ }
    6671
     72                deque_const_iterator(const deque_const_iterator& other)
     73                    : deq_{other.deq_}, idx_{other.idx_}
     74                { /* DUMMY BODY */ }
     75
    6776                deque_const_iterator& operator=(const deque_const_iterator& other)
    6877                {
     
    144153                {
    145154                    return idx_;
     155                }
     156
     157                operator deque_iterator<T, Allocator>()
     158                {
     159                    return deque_iterator{deq_, idx_};
    146160                }
    147161
     
    180194                { /* DUMMY BODY */ }
    181195
     196                deque_iterator(const deque_iterator& other)
     197                    : deq_{other.deq_}, idx_{other.idx_}
     198                { /* DUMMY BODY */ }
     199
    182200                deque_iterator(const deque_const_iterator<T, Allocator>& other)
    183201                    : deq_{other.deq_}, idx_{other.idx_}
     
    271289                {
    272290                    return idx_;
     291                }
     292
     293                operator deque_const_iterator<T, Allocator>()
     294                {
     295                    return deque_const_iterator{deq_, idx_};
    273296                }
    274297
     
    675698            iterator emplace(const_iterator position, Args&&... args)
    676699            {
    677                 // TODO: implement
     700                auto idx = position.idx();
     701                shift_right_(idx, 1);
     702
     703                allocator_traits<allocator_type>::construct(
     704                    allocator_,
     705                    &data_[get_bucket_index_(idx)][get_element_index_(idx)],
     706                    forward<Args>(args)...
     707                );
     708                ++size_;
     709
     710                return iterator{*this, idx};
    678711            }
    679712
     
    716749            iterator insert(const_iterator position, const value_type& value)
    717750            {
    718                 // TODO: implement
     751                auto idx = position.idx();
     752                shift_right_(idx, 1);
     753
     754                /**
     755                 * Note: One may notice that when working with the deque
     756                 *       iterator, we use its index without any checks.
     757                 *       This is because a valid iterator will always have
     758                 *       a valid index as functions like pop_back or erase
     759                 *       invalidate iterators.
     760                 */
     761                data_[get_bucket_index_(idx)][get_element_index_(idx)] = value;
     762                ++size_;
     763
     764                return iterator{*this, idx};
    719765            }
    720766
    721767            iterator insert(const_iterator position, value_type&& value)
    722768            {
    723                 // TODO: implement
     769                auto idx = position.idx();
     770                shift_right_(idx, 1);
     771
     772                data_[get_bucket_index_(idx)][get_element_index_(idx)] = forward<value_type>(value);
     773                ++size_;
     774
     775                return iterator{*this, idx};
    724776            }
    725777
    726778            iterator insert(const_iterator position, size_type n, const value_type& value)
    727779            {
    728                 // TODO: implement
     780                return insert(
     781                    position,
     782                    aux::insert_iterator{value},
     783                    aux::insert_iterator{n}
     784                );
    729785            }
    730786
     
    732788            iterator insert(const_iterator position, InputIterator first, InputIterator last)
    733789            {
    734                 // TODO: implement
     790                auto idx = position.idx();
     791                auto count = distance(first, last);
     792
     793                if (idx < size_ / 2)
     794                {
     795                    shift_left_(idx, count);
     796
     797                    iterator it{*this, idx - 1};
     798                    while (first != last)
     799                        *it++ = *first++;
     800                }
     801                else
     802                {
     803                    shift_right_(idx, count);
     804
     805                    iterator it{*this, idx};
     806                    while (first != last)
     807                        *it++ = *first++;
     808                }
     809
     810                size_ += count;
     811
     812                return iterator{*this, idx};
    735813            }
    736814
    737815            iterator insert(const_iterator position, initializer_list<value_type> init)
    738816            {
    739                 // TODO: implement
     817                return insert(position, init.begin(), init.end());
    740818            }
    741819
     
    746824
    747825                if (back_bucket_idx_ == 0)
    748                 { // Means we gotta pop data_[front_bucket_][bucket_size_ - 1]!
     826                { // Means we gotta pop data_[back_bucket_ - 1][bucket_size_ - 1]!
    749827                    if (data_[back_bucket_])
    750828                        allocator_.deallocate(data_[back_bucket_], bucket_size_);
     
    766844
    767845                if (front_bucket_idx_ >= bucket_size_)
    768                 { // Means we gotta pop data_[front_bucket_][0]!
     846                { // Means we gotta pop data_[front_bucket_ + 1][0]!
    769847                    if (data_[front_bucket_])
    770848                        allocator_.deallocate(data_[front_bucket_], bucket_size_);
     
    863941                    fini_();
    864942
    865                 if (size < bucket_size_) // Always front_bucket_ != back_bucket_.
    866                     bucket_count_ = bucket_capacity_ = 2;
    867                 else if (size % bucket_size_ == 0)
    868                     bucket_count_ = bucket_capacity_ = size / bucket_size_ + 2;
    869                 else
    870                     bucket_count_ = bucket_capacity_ = size / bucket_size_ + 2;
     943                bucket_count_ = bucket_capacity_ = size / bucket_size_ + 2;
    871944
    872945                front_bucket_ = 0;
     
    889962            }
    890963
     964            void ensure_space_front_(size_type idx, size_type count)
     965            {
     966                auto free_space = bucket_size_ - elements_in_front_bucket_();
     967                if (front_bucket_idx_ == 0)
     968                    free_space = 0;
     969
     970                if (count <= free_space)
     971                {
     972                    front_bucket_idx_ -= count;
     973                    return;
     974                }
     975
     976                count -= free_space;
     977
     978                auto buckets_needed = count / bucket_size_;
     979                if (count % bucket_size_ != 0)
     980                    ++buckets_needed;
     981
     982                for (size_type i = size_type{}; i < buckets_needed; ++i)
     983                    add_new_bucket_front_();
     984
     985                front_bucket_idx_ = bucket_size_ - (count % bucket_size_);
     986            }
     987
     988            void ensure_space_back_(size_type idx, size_type count)
     989            {
     990                auto free_space = bucket_size_ - back_bucket_idx_;
     991                if (count < free_space)
     992                    return;
     993
     994                count -= free_space;
     995                auto buckets_needed = count / bucket_size_;
     996                if (count % bucket_size_ != 0)
     997                    ++buckets_needed;
     998
     999                for (size_type i = size_type{}; i < buckets_needed; ++i)
     1000                    add_new_bucket_back_();
     1001
     1002                back_bucket_idx_ = (back_bucket_idx_ + count) % bucket_size_;
     1003            }
     1004
     1005            void shift_right_(size_type idx, size_type count)
     1006            {
     1007                ensure_space_back_(idx, count);
     1008
     1009                iterator it{*this, idx};
     1010                copy_backward(it, end(), end() + count - 1);
     1011
     1012            }
     1013
     1014            void shift_left_(size_type idx, size_type count)
     1015            {
     1016                ensure_space_front_(idx, count);
     1017
     1018                copy(
     1019                    iterator{*this, count},
     1020                    iterator{*this, idx + count - 1},
     1021                    iterator{*this, 0}
     1022                );
     1023            }
     1024
    8911025            void fini_()
    8921026            {
     
    9141048
    9151049                ++back_bucket_;
     1050                ++bucket_count_;
    9161051                data_[back_bucket_] = allocator_.allocate(bucket_size_);
    9171052                back_bucket_idx_ = size_type{};
     
    9241059
    9251060                --front_bucket_;
     1061                ++bucket_count_;
    9261062                data_[front_bucket_] = allocator_.allocate(bucket_size_);
    9271063                front_bucket_idx_ = bucket_size_;
     
    9331069                value_type** new_data = new value_type*[bucket_capacity_];
    9341070
     1071                /**
     1072                 * Note: This currently expands both sides whenever one reaches
     1073                 *       its limit. Might be better to expand only one (or both when
     1074                 *       the other is near its limit)?
     1075                 */
    9351076                size_type new_front = bucket_capacity_ / 4;
    936                 size_type new_back = bucket_capacity_ - bucket_capacity_ / 4 - 1;
     1077                size_type new_back = new_front + bucket_count_ - 1;
    9371078
    9381079                for (size_type i = new_front, j = front_bucket_; i <= new_back; ++i, ++j)
Note: See TracChangeset for help on using the changeset viewer.