|
libpsynth 0.2.1
|
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
1.7.4