libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/hetero_deque.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2011 Juan Pedro BolĂ­var Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 #ifndef PSYNTH_BASE_HETERO_DEQUE_HPP_
00032 #define PSYNTH_BASE_HETERO_DEQUE_HPP_
00033 
00034 #include <type_traits>
00035 #include <vector>
00036 
00037 #include <boost/iterator/iterator_facade.hpp>
00038 #include <boost/iterator/reverse_iterator.hpp>
00039 
00040 #include <psynth/base/util.hpp>
00041 #include <psynth/base/exception.hpp>
00042 
00043 
00044 namespace psynth
00045 {
00046 namespace base
00047 {
00048 
00049 PSYNTH_DECLARE_ERROR (error, hetero_deque_empty);
00050 
00051 namespace detail
00052 {
00053 
00054 template <class Base>
00055 struct hetero_header
00056 {
00057     Base*          access;
00058     hetero_header* next;
00059     hetero_header* prev;
00060 };
00061 
00062 template <class Base>
00063 class hetero_iterator : public boost::iterator_facade <
00064     hetero_iterator<Base>,
00065     Base,
00066     boost::bidirectional_traversal_tag>
00067 {
00068     typedef hetero_header<Base> header;
00069     
00070 public:
00071     explicit hetero_iterator (header* curr)
00072         : _curr (curr) {}
00073 
00074     hetero_iterator () : _curr (0) {}
00075     hetero_iterator (const hetero_iterator&) = default;
00076     hetero_iterator& operator= (const hetero_iterator&) = default;
00077 
00078 private:
00079     friend class boost::iterator_core_access;
00080     
00081     Base& dereference () const
00082     { return *_curr->access; }
00083 
00084     bool equal (const hetero_iterator& other) const
00085     { return _curr == other._curr; }
00086 
00087     void increment ()
00088     { _curr = _curr->next; }
00089     
00090     void decrement ()
00091     { _curr = _curr->prev; }
00092                 
00093     header* _curr;
00094 };
00095 
00096 } /* namespace detail */
00097 
00115 template <class Base>
00116 class hetero_deque : public boost::noncopyable
00117 {
00118 public:
00119     typedef detail::hetero_iterator<Base> iterator;
00120     typedef detail::hetero_iterator<const Base> const_iterator;
00121     typedef boost::reverse_iterator<iterator> reverse_iterator;
00122     typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
00123 
00124     typedef typename iterator::value_type value_type;
00125     typedef typename iterator::reference reference;
00126     typedef typename iterator::difference_type difference_type;
00127     typedef typename const_iterator::reference const_reference;
00128     
00129     explicit hetero_deque (std::size_t size = 0);
00130     hetero_deque (hetero_deque&&);
00131     hetero_deque& operator= (hetero_deque&&);
00132 #if 0
00133     hetero_deque (const hetero_deque&);
00134     hetero_deque& operator= (const hetero_deque&);
00135 #endif
00136     ~hetero_deque ();
00137     
00138     Base& back ();
00139     const Base& back () const;
00140     template <class Concrete, typename ...Args>
00141     bool push_back (Args&& ... args);
00142     template <class Concrete>
00143     bool push_back (Concrete&& arg)
00144     {
00145         return this->push_back<
00146             typename std::decay<Concrete>::type,
00147             decltype (std::forward<Concrete> (arg))> (
00148                 std::forward<Concrete> (arg));
00149     }
00150     bool pop_back ();
00151 
00152     Base& front ();
00153     const Base& front () const;
00154     template <class Concrete, typename ...Args>
00155     bool push_front (Args&&... args);
00156     template <class Concrete>
00157     bool push_front (Concrete&& arg)
00158     {
00159         return this->push_front<
00160             typename std::decay<Concrete>::type,
00161             decltype (std::forward<Concrete> (arg))> (
00162                 std::forward<Concrete> (arg));
00163     }
00164     bool pop_front ();
00165 
00166     void clear ();
00167     
00168     void swap (hetero_deque& other);
00169 
00170     bool empty () const
00171     { return !_front->access; }
00172 
00173     iterator begin ()
00174     { return iterator (_front); }
00175     const_iterator begin () const
00176     { return const_iterator (_front); }
00177     const_iterator cbegin () const
00178     { return const_iterator (_front); }
00179     reverse_iterator rbegin ()
00180     { return reverse_iterator (_front); }
00181     const_reverse_iterator rbegin () const
00182     { return const_reverse_iterator (_front); }
00183     
00184     iterator end ()
00185     { return iterator (_back->next ? _back->next : _back); }
00186     const_iterator end () const
00187     { return const_iterator (_back->next ? _back->next : _back); }
00188     const_iterator cend () const
00189     { return const_iterator (_back->next ? _back->next : _back); }
00190     reverse_iterator rend ()
00191     { return reverse_iterator (_back->next ? _back->next : _back); }
00192     const_reverse_iterator rend () const
00193     { return const_reverse_iterator (_back->next ? _back->next : _back); }
00194     
00195 private:
00196     typedef detail::hetero_header<Base> header;
00197     static_assert (std::is_pod<header>::value,
00198                    "hetero_header must be a POD");
00199     
00200     template <class Concrete, typename ...Args>
00201     void construct (header* data, Args&&... args);
00202     
00203     const Base& access (const header* data) const;
00204     Base& access (header* data) const;
00205         
00206     typedef std::vector<char> memory_t;
00207     
00208     memory_t    _memory;
00209     header*     _front;
00210     header*     _back;
00211 };
00212 
00213 } /* namespace base */
00214 } /* namespace psynth */
00215 
00216 namespace std
00217 {
00218 
00219 template <class B>
00220 void swap (psynth::base::hetero_deque<B>& a,
00221            psynth::base::hetero_deque<B>& b)
00222 {
00223     a.swap (b);
00224 }
00225 
00226 } /* namespace std */
00227 
00228 #include <psynth/base/hetero_deque.tpp>
00229 
00230 #endif /* PSYNTH_BASE_HETERO_DEQUE_HPP_ */
00231