cmake: supernova - missing include_directories() for Jack
[supercollider.git] / server / supernova / utilities / sized_array.hpp
blob21f3b5af71fae93b7e484715f95380048014f67c
1 // templated sized array class
2 // Copyright (C) 2009 Tim Blechmann
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef UTILITIES_SIZED_ARRAY_HPP
20 #define UTILITIES_SIZED_ARRAY_HPP
22 #include <cassert>
23 #include <memory> /* std::allocator */
25 #include <stdint.h>
27 #include <boost/mpl/if.hpp>
28 #include <boost/type_traits/is_integral.hpp>
29 #include <boost/move/move.hpp>
31 namespace nova
34 /** dynamically sized array
36 * array class, inspired by boost.array, where the size is specified
37 * during the time of the construction.
38 * in contrary to std::vector, it is guaranteed to use continuous
39 * memory. the memory is allocated in the constructor an freed in the
40 * destructor, these are the only places, where the allocator
41 * functions are called.
43 * */
44 template<typename T,
45 class Alloc = std::allocator<T> >
46 class sized_array:
47 private Alloc::template rebind<T>::other
49 typedef typename Alloc::template rebind<T>::other Allocator;
51 BOOST_MOVABLE_BUT_NOT_COPYABLE(sized_array)
53 public:
54 // types
55 typedef T value_type;
56 typedef T* iterator;
57 typedef const T* const_iterator;
58 typedef std::reverse_iterator<iterator> reverse_iterator;
59 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
60 typedef T& reference;
61 typedef const T& const_reference;
62 typedef std::size_t size_type;
63 typedef std::ptrdiff_t difference_type;
65 // construct/copy/destruct
66 explicit sized_array(size_type size = 0, T const & def = T()):
67 data_(Allocator::allocate(size)), size_(size)
69 for (size_type i = 0; i != size; ++i)
70 Allocator::construct(data_ + i, def);
73 private:
74 template <typename int_type>
75 void init_from_int(int_type size)
77 data_ = Allocator::allocate(size);
78 size_ = size;
79 for (size_type i = 0; i != size_; ++i)
80 Alloc::construct(data_ + i, T());
83 template <typename Container>
84 void init_from_container(Container const & container)
86 data_ = Allocator::allocate(container.size());
87 size_ = container.size();
89 size_type index = 0;
90 typedef typename Container::const_iterator iterator;
91 for (iterator it = container.begin(); it != container.end(); ++it)
92 Allocator::construct(data_ + index++, *it);
93 assert(index == size());
96 struct call_int_ctor
98 template <typename int_type>
99 static void init(sized_array & array, int_type const & i)
101 array.init_from_int<int_type>(i);
105 struct call_container_ctor
107 template <typename Container>
108 static void init(sized_array & array, Container const & c)
110 array.init_from_container<Container>(c);
114 public:
115 template<typename Constructor_arg>
116 explicit sized_array(Constructor_arg const & arg)
118 typedef typename boost::mpl::if_<boost::is_integral<Constructor_arg>,
119 call_int_ctor,
120 call_container_ctor>::type ctor;
121 ctor::init(*this, arg);
124 #ifdef BOOST_HAS_RVALUE_REFS
125 explicit sized_array(sized_array && arg)
127 data_ = arg.data_;
128 size_ = arg.size();
129 arg.data_ = 0;
130 arg.size_ = 0;
133 /** move assignment */
134 sized_array & operator=(sized_array && arg)
136 data_ = arg.data_;
137 size_ = arg.size();
138 arg.data_ = 0;
139 arg.size_ = 0;
140 return *this;
142 #else
143 explicit sized_array(BOOST_RV_REF(sized_array) arg)
145 operator=(arg);
148 /** move assignment */
149 sized_array & operator=(BOOST_RV_REF(sized_array) arg)
151 data_ = arg.data_;
152 size_ = arg.size();
153 arg.data_ = 0;
154 arg.size_ = 0;
155 return *this;
157 #endif
159 ~sized_array(void)
161 for (size_type i = 0; i != size(); ++i)
162 Allocator::destroy(data_ + i);
163 if (size())
164 Allocator::deallocate(data_, size());
167 // iterator support
168 iterator begin()
170 return data_;
173 const_iterator begin() const
175 return data_;
178 iterator end()
180 return data_ + size();
183 const_iterator end() const
185 return data_ + size();
188 // reverse iterator support
189 reverse_iterator rbegin()
191 return reverse_iterator(data_ + size());
194 const_reverse_iterator rbegin() const
196 return const_reverse_iterator(data_ + size());
199 reverse_iterator rend()
201 return reverse_iterator(data_);
204 const_reverse_iterator rend() const
206 return const_reverse_iterator(data_);
209 // capacity
210 size_type size() const
212 return size_;
215 bool empty() const
217 return size_ == 0;
220 size_type max_size() const
222 return size_;
225 // element access
226 reference operator[](size_type i)
228 return data_[i];
231 const_reference operator[](size_type i) const
233 return data_[i];
236 reference at(size_type i)
238 return data_[i];
241 const_reference at(size_type i) const
243 return data_[i];
246 reference front()
248 return data_[0];
251 const_reference front() const
253 return data_[0];
256 reference back()
258 return data_[size_ - 1];
261 const_reference back() const
263 return data_[size_ - 1];
266 const T* data() const
268 return data_;
271 T* c_array()
273 return data_;
276 // modifiers
277 void assign(const T& t)
279 for (size_type i = 0; i != size_; ++i)
280 data_[i] = t;
283 void resize(size_type new_size, T const & t = T())
285 T * new_data = Allocator::allocate(new_size);
287 for (size_type i = 0; i != new_size; ++i)
288 Allocator::construct(new_data+i, t);
290 std::copy(data_, data_+std::min(new_size, size_), new_data);
292 T * old_data = data_;
293 data_ = new_data;
294 for (size_type i = 0; i != size_; ++i)
295 Allocator::destroy(old_data+i);
296 if (size_)
297 Allocator::deallocate(old_data, size_);
298 size_ = new_size;
301 private:
302 T * data_;
303 size_type size_;
306 } /* namespace nova */
308 #endif /* UTILITIES_SIZED_ARRAY_HPP */