class library: Volume - use ServerBoot to send synthdef
[supercollider.git] / server / supernova / utilities / sized_array.hpp
blob13145de72ab29d6adbd8b7860d746b82520e640e
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 */
24 #include <type_traits>
26 #include <boost/mpl/if.hpp>
28 namespace nova {
30 /** dynamically sized array
32 * array class, inspired by boost.array, where the size is specified
33 * during the time of the construction.
34 * in contrary to std::vector, it is guaranteed to use continuous
35 * memory. the memory is allocated in the constructor an freed in the
36 * destructor, these are the only places, where the allocator
37 * functions are called.
39 * */
40 template<typename T,
41 class Alloc = std::allocator<T> >
42 class sized_array:
43 private Alloc::template rebind<T>::other
45 typedef typename Alloc::template rebind<T>::other Allocator;
47 public:
48 // types
49 typedef T value_type;
50 typedef T* iterator;
51 typedef const T* const_iterator;
52 typedef std::reverse_iterator<iterator> reverse_iterator;
53 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
54 typedef T& reference;
55 typedef const T& const_reference;
56 typedef std::size_t size_type;
57 typedef std::ptrdiff_t difference_type;
59 // construct/copy/destruct
60 explicit sized_array(size_type size = 0, T const & def = T()):
61 data_( size ? Allocator::allocate(size) : 0), size_(size)
63 for (size_type i = 0; i != size; ++i)
64 Allocator::construct(data_ + i, def);
67 sized_array(sized_array & arg) = delete;
68 sized_array & operator=(sized_array & arg) = delete;
70 private:
71 template <typename int_type>
72 void init_from_int(int_type size)
74 data_ = Allocator::allocate(size);
75 size_ = size;
76 for (size_type i = 0; i != size_; ++i)
77 Alloc::construct(data_ + i, T());
80 template <typename Container>
81 void init_from_container(Container const & container)
83 data_ = Allocator::allocate(container.size());
84 size_ = container.size();
86 size_type index = 0;
87 typedef typename Container::const_iterator iterator;
88 for (iterator it = container.begin(); it != container.end(); ++it)
89 Allocator::construct(data_ + index++, *it);
90 assert(index == size());
93 struct call_int_ctor
95 template <typename int_type>
96 static void init(sized_array & array, int_type const & i)
98 array.init_from_int<int_type>(i);
102 struct call_container_ctor
104 template <typename Container>
105 static void init(sized_array & array, Container const & c)
107 array.init_from_container<Container>(c);
111 public:
112 template<typename Constructor_arg>
113 explicit sized_array(Constructor_arg const & arg)
115 typedef typename boost::mpl::if_<std::is_integral<Constructor_arg>,
116 call_int_ctor,
117 call_container_ctor>::type ctor;
118 ctor::init(*this, arg);
121 explicit sized_array(sized_array && arg)
123 data_ = arg.data_;
124 size_ = arg.size();
125 arg.data_ = 0;
126 arg.size_ = 0;
129 /** move assignment */
130 sized_array & operator=(sized_array && arg)
132 data_ = arg.data_;
133 size_ = arg.size();
134 arg.data_ = 0;
135 arg.size_ = 0;
136 return *this;
139 ~sized_array(void)
141 for (size_type i = 0; i != size(); ++i)
142 Allocator::destroy(data_ + i);
143 if (size())
144 Allocator::deallocate(data_, size());
147 // iterator support
148 iterator begin()
150 return data_;
153 const_iterator begin() const
155 return data_;
158 iterator end()
160 return data_ + size();
163 const_iterator end() const
165 return data_ + size();
168 // reverse iterator support
169 reverse_iterator rbegin()
171 return reverse_iterator(data_ + size());
174 const_reverse_iterator rbegin() const
176 return const_reverse_iterator(data_ + size());
179 reverse_iterator rend()
181 return reverse_iterator(data_);
184 const_reverse_iterator rend() const
186 return const_reverse_iterator(data_);
189 // capacity
190 size_type size() const
192 return size_;
195 bool empty() const
197 return size_ == 0;
200 size_type max_size() const
202 return size_;
205 // element access
206 reference operator[](size_type i)
208 return data_[i];
211 const_reference operator[](size_type i) const
213 return data_[i];
216 reference at(size_type i)
218 return data_[i];
221 const_reference at(size_type i) const
223 return data_[i];
226 reference front()
228 return data_[0];
231 const_reference front() const
233 return data_[0];
236 reference back()
238 return data_[size_ - 1];
241 const_reference back() const
243 return data_[size_ - 1];
246 const T* data() const
248 return data_;
251 T* c_array()
253 return data_;
256 // modifiers
257 void assign(const T& t)
259 for (size_type i = 0; i != size_; ++i)
260 data_[i] = t;
263 void resize(size_type new_size, T const & t = T())
265 T * new_data = Allocator::allocate(new_size);
267 for (size_type i = 0; i != new_size; ++i)
268 Allocator::construct(new_data+i, t);
270 std::copy(data_, data_+std::min(new_size, size_), new_data);
272 T * old_data = data_;
273 data_ = new_data;
274 for (size_type i = 0; i != size_; ++i)
275 Allocator::destroy(old_data+i);
276 if (size_)
277 Allocator::deallocate(old_data, size_);
278 size_ = new_size;
281 private:
282 T * data_;
283 size_type size_;
286 } /* namespace nova */
288 #endif /* UTILITIES_SIZED_ARRAY_HPP */