Changeset 3a06cc6 in mainline


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

cpp: added a basic deque implementation, currently push/pop/clear/indexed access

File:
1 edited

Legend:

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

    r9475faf r3a06cc6  
    11/*
    2  * Copyright (c) 2017 Jaroslav Jindrak
     2 * Copyright (c) 2018 Jaroslav Jindrak
    33 * All rights reserved.
    44 *
     
    3131
    3232#include <initializer_list>
     33#include <iterator>
    3334#include <memory>
    3435
    3536namespace std
    3637{
     38    template<class T, class Allocator = allocator<T>>
     39    class deque;
    3740
    3841    namespace aux
     
    4144        class deque_iterator
    4245        {
    43             // TODO: implement
     46            using size_type = typename std::deque<T, Allocator>::size_type;
     47            using value_type = typename std::deque<T, Allocator>::value_type;
     48            using difference_type = size_type;
     49
     50            public:
     51                deque_iterator(deque<T, Allocator>* deq, size_type idx)
     52                    : deq_{deq}, idx_{idx}
     53                { /* DUMMY BODY */ }
     54
     55            private:
     56                deque<T, Allocator>* deq_;
     57                size_type idx_;
    4458        };
    4559
     
    5569     */
    5670
    57     template<class T, class Allocator = allocator<T>>
     71    template<class T, class Allocator>
    5872    class deque
    5973    {
     
    8397
    8498            explicit deque(const allocator_type& alloc)
    85             {
    86                 // TODO: implement
     99                : allocator_{alloc}, front_bucket_idx_{bucket_size_},
     100                  back_bucket_idx_{0}, front_bucket_{default_front_},
     101                  back_bucket_{default_back_}, bucket_count_{default_bucket_count_},
     102                  bucket_capacity_{default_bucket_capacity_}, size_{}, data_{}
     103            {
     104                init_();
    87105            }
    88106
     
    130148            ~deque()
    131149            {
    132                 // TODO: implement
     150                fini_();
    133151            }
    134152
     
    236254            size_type size() const noexcept
    237255            {
    238                 // TODO: implement
     256                return size_;
    239257            }
    240258
     
    261279            bool empty() const noexcept
    262280            {
    263                 // TODO: implement
     281                return size_ == size_type{};
    264282            }
    265283
    266284            reference operator[](size_type idx)
    267285            {
    268                 // TODO: implement
    269             }
    270 
    271             const_reference operator[](size_type idx)
    272             {
    273                 // TODO: implement
     286                return data_[get_bucket_index_(idx)][get_element_index_(idx)];
     287            }
     288
     289            const_reference operator[](size_type idx) const
     290            {
     291                return data_[get_bucket_index_(idx)][get_element_index_(idx)];
    274292            }
    275293
     
    279297            }
    280298
    281             const_reference at(size_type idx)
     299            const_reference at(size_type idx) const
    282300            {
    283301                // TODO: implement
     
    328346            void push_front(const value_type& value)
    329347            {
    330                 // TODO: implement
     348                if (front_bucket_idx_ == 0)
     349                    add_new_bucket_front_();
     350
     351                data_[front_bucket_][--front_bucket_idx_] = value;
     352                ++size_;
    331353            }
    332354
    333355            void push_front(value_type&& value)
    334356            {
    335                 // TODO: implement
     357                if (front_bucket_idx_ == 0)
     358                    add_new_bucket_front_();
     359
     360                data_[front_bucket_][--front_bucket_idx_] = forward<value_type>(value);
     361                ++size_;
    336362            }
    337363
    338364            void push_back(const value_type& value)
    339365            {
    340                 // TODO: implement
     366                data_[back_bucket_][back_bucket_idx_++] = value;
     367                ++size_;
     368
     369                if (back_bucket_idx_ >= bucket_size_)
     370                    add_new_bucket_back_();
    341371            }
    342372
    343373            void push_back(value_type&& value)
    344374            {
    345                 // TODO: implement
     375                data_[back_bucket_][back_bucket_idx_++] = forward<value_type>(value);
     376                ++size_;
     377
     378                if (back_bucket_idx_ >= bucket_size_)
     379                    add_new_bucket_back_();
    346380            }
    347381
     
    374408            void pop_back()
    375409            {
    376                 // TODO: implement
     410                if (empty())
     411                    return;
     412
     413                if (back_bucket_idx_ == 0)
     414                { // Means we gotta pop data_[front_bucket_][bucket_size_ - 1]!
     415                    if (data_[back_bucket_])
     416                        allocator_.deallocate(data_[back_bucket_], bucket_size_);
     417
     418                    --back_bucket_;
     419                    back_bucket_idx_ = bucket_size_ - 1;
     420                }
     421                else
     422                    --back_bucket_idx_;
     423
     424                allocator_.destroy(&data_[back_bucket_][back_bucket_idx_]);
     425                --size_;
    377426            }
    378427
    379428            void pop_front()
    380429            {
    381                 // TODO: implement
     430                if (empty())
     431                    return;
     432
     433                if (front_bucket_idx_ >= bucket_size_)
     434                { // Means we gotta pop data_[front_bucket_][0]!
     435                    if (data_[front_bucket_])
     436                        allocator_.deallocate(data_[front_bucket_], bucket_size_);
     437
     438                    ++front_bucket_;
     439                    front_bucket_idx_ = 1;
     440
     441                    allocator_.destroy(&data_[front_bucket_][0]);
     442                }
     443                else
     444                {
     445                    allocator_.destroy(&data_[front_bucket_][front_bucket_idx_]);
     446
     447                    ++front_bucket_idx_;
     448                }
     449
     450                --size_;
    382451            }
    383452
     
    387456            }
    388457
    389             iterator eraser(cosnt_iteterator first, const_iterator last)
     458            iterator erase(const_iterator first, const_iterator last)
    390459            {
    391460                // TODO: implement
     
    400469            void clear() noexcept
    401470            {
    402                 // TODO: implement
    403             }
    404 
    405         private:
     471                fini_();
     472
     473                front_bucket_ = default_front_;
     474                back_bucket_ = default_back_;
     475                bucket_count_ = default_bucket_count_;
     476                bucket_capacity_ = default_bucket_capacity_;
     477                size_ = size_type{};
     478
     479                init_();
     480            }
     481
     482        /* private: */
    406483            allocator_type allocator_;
    407484
     485            /**
     486             * Note: In our implementation, front_bucket_idx_
     487             *       points at the first element and back_bucket_idx_
     488             *       points at the one past last element. Because of this,
     489             *       some operations may be done in inverse order
     490             *       depending on the side they are applied to.
     491             */
    408492            size_type front_bucket_idx_;
    409493            size_type back_bucket_idx_;
     494            size_type front_bucket_;
     495            size_type back_bucket_;
    410496
    411497            static constexpr size_type bucket_size_{16};
     498            static constexpr size_type default_bucket_count_{2};
     499            static constexpr size_type default_bucket_capacity_{4};
     500            static constexpr size_type default_front_{1};
     501            static constexpr size_type default_back_{2};
    412502
    413503            size_type bucket_count_;
    414504            size_type bucket_capacity_;
     505            size_type size_{};
    415506
    416507            value_type** data_;
     508
     509            void init_()
     510            {
     511                data_ = new value_type*[bucket_capacity_];
     512
     513                for (size_type i = front_bucket_; i <= back_bucket_; ++i)
     514                    data_[i] = allocator_.allocate(bucket_size_);
     515            }
     516
     517            void fini_()
     518            {
     519                for (size_type i = front_bucket_; i <= back_bucket_; ++i)
     520                    allocator_.deallocate(data_[i], bucket_size_);
     521
     522                delete[] data_;
     523                data_ = nullptr;
     524            }
     525
     526            bool has_bucket_space_back_() const
     527            {
     528                return back_bucket_ < bucket_capacity_ - 1;
     529            }
     530
     531            bool has_bucket_space_front_() const
     532            {
     533                return front_bucket_ > 0;
     534            }
     535
     536            void add_new_bucket_back_()
     537            {
     538                if (!has_bucket_space_back_())
     539                    expand_();
     540
     541                ++back_bucket_;
     542                data_[back_bucket_] = allocator_.allocate(bucket_size_);
     543                back_bucket_idx_ = size_type{};
     544            }
     545
     546            void add_new_bucket_front_()
     547            {
     548                if (!has_bucket_space_front_())
     549                    expand_();
     550
     551                --front_bucket_;
     552                data_[front_bucket_] = allocator_.allocate(bucket_size_);
     553                front_bucket_idx_ = bucket_size_;
     554            }
     555
     556            void expand_()
     557            {
     558                bucket_capacity_ *= 2;
     559                value_type** new_data = new value_type*[bucket_capacity_];
     560
     561                size_type new_front = bucket_capacity_ / 4;
     562                size_type new_back = bucket_capacity_ - bucket_capacity_ / 4 - 1;
     563
     564                for (size_type i = new_front, j = front_bucket_; i <= new_back; ++i, ++j)
     565                    new_data[i] = move(data_[j]);
     566                std::swap(data_, new_data);
     567
     568                delete[] new_data;
     569                front_bucket_ = new_front;
     570                back_bucket_ = new_back;
     571            }
     572
     573            size_type get_bucket_index_(size_type idx) const
     574            {
     575                if (idx < elements_in_front_bucket_())
     576                    return front_bucket_;
     577
     578                idx -= elements_in_front_bucket_();
     579                return idx / bucket_size_ + front_bucket_ + 1;
     580            }
     581
     582            size_type get_element_index_(size_type idx) const
     583            {
     584                if (idx < elements_in_front_bucket_())
     585                    return bucket_size_ - elements_in_front_bucket_() + idx;
     586
     587                idx -= elements_in_front_bucket_();
     588                return idx % bucket_size_;
     589            }
     590
     591            size_type elements_in_front_bucket_() const
     592            {
     593                return bucket_size_ - front_bucket_idx_;
     594            }
    417595    };
    418596
     
    421599    {
    422600        // TODO: implement
     601        return false;
    423602    }
    424603
     
    427606    {
    428607        // TODO: implement
    429     }
    430 
    431     template<class T, class Allocator>
    432     bool operator=!(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
     608        return false;
     609    }
     610
     611    template<class T, class Allocator>
     612    bool operator!=(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
    433613    {
    434614        // TODO: implement
     615        return false;
    435616    }
    436617
     
    439620    {
    440621        // TODO: implement
     622        return false;
    441623    }
    442624
     
    445627    {
    446628        // TODO: implement
     629        return false;
    447630    }
    448631
     
    451634    {
    452635        // TODO: implement
     636        return false;
    453637    }
    454638
Note: See TracChangeset for help on using the changeset viewer.