foobar2000 SDK  2015-01-14
array.h
Go to the documentation of this file.
1 #ifndef _PFC_ARRAY_H_
2 #define _PFC_ARRAY_H_
3 
4 namespace pfc {
5 
6  template<typename t_item, template<typename> class t_alloc = alloc_standard> class array_t;
7 
8 
10  template<typename _t_item>
12  public: typedef _t_item t_item;
14  public:
16  array_staticsize_t(t_size p_size) : m_array(new t_item[p_size]), m_size(p_size) {}
18 
20  array_staticsize_t(const t_self & p_source) : m_size(0), m_array(NULL) {
21  *this = p_source;
22  }
23 
25  const t_self & operator=(const t_self & p_source) {
26  release_();
27 
28  //m_array = pfc::malloc_copy_t(p_source.get_size(),p_source.get_ptr());
29  const t_size newsize = p_source.get_size();
30  m_array = new t_item[newsize];
31  m_size = newsize;
32  for(t_size n = 0; n < newsize; n++) m_array[n] = p_source[n];
33  return *this;
34  }
35 
36  void set_size_discard(t_size p_size) {
37  release_();
38  if (p_size > 0) {
39  m_array = new t_item[p_size];
40  m_size = p_size;
41  }
42  }
44  template<typename t_source>
45  void set_data_fromptr(const t_source * p_buffer,t_size p_count) {
46  set_size_discard(p_count);
47  pfc::copy_array_loop_t(*this,p_buffer,p_count);
48  }
49 
50 
51  t_size get_size() const {return m_size;}
52  const t_item * get_ptr() const {return m_array;}
53  t_item * get_ptr() {return m_array;}
54 
55  const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < get_size());return m_array[p_index];}
56  t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < get_size());return m_array[p_index];}
57 
58  template<typename t_source> bool is_owned(const t_source & p_item) {return pfc::is_pointer_in_range(get_ptr(),get_size(),&p_item);}
59 
60  template<typename t_out> void enumerate(t_out & out) const { for(t_size walk = 0; walk < m_size; ++walk) out(m_array[walk]); }
61  private:
62  void release_() {
63  m_size = 0;
64  delete[] pfc::replace_null_t(m_array);
65  }
66  t_item * m_array;
68  };
69 
70  template<typename t_to,typename t_from>
71  void copy_array_t(t_to & p_to,const t_from & p_from) {
72  const t_size size = array_size_t(p_from);
73  if (p_to.has_owned_items(p_from)) {//avoid landmines with actual array data overlapping, or p_from being same as p_to
75  temp.set_size_discard(size);
76  pfc::copy_array_loop_t(temp,p_from,size);
77  p_to.set_size(size);
78  pfc::copy_array_loop_t(p_to,temp,size);
79  } else {
80  p_to.set_size(size);
81  pfc::copy_array_loop_t(p_to,p_from,size);
82  }
83  }
84 
85  template<typename t_array,typename t_value>
86  void fill_array_t(t_array & p_array,const t_value & p_value) {
87  const t_size size = array_size_t(p_array);
88  for(t_size n=0;n<size;n++) p_array[n] = p_value;
89  }
90 
91  template<typename _t_item, template<typename> class t_alloc> class array_t {
92  public: typedef _t_item t_item;
93  private: typedef array_t<t_item,t_alloc> t_self;
94  public:
95  array_t() {}
96  array_t(const t_self & p_source) {copy_array_t(*this,p_source);}
97  template<typename t_source> array_t(const t_source & p_source) {copy_array_t(*this,p_source);}
98  const t_self & operator=(const t_self & p_source) {copy_array_t(*this,p_source); return *this;}
99  template<typename t_source> const t_self & operator=(const t_source & p_source) {copy_array_t(*this,p_source); return *this;}
100 
101  array_t(t_self && p_source) {move_from(p_source);}
102  const t_self & operator=(t_self && p_source) {move_from(p_source); return *this;}
103 
104  void set_size(t_size p_size) {m_alloc.set_size(p_size);}
105 
106  template<typename fill_t>
107  void set_size_fill(size_t p_size, fill_t const & filler) {
108  size_t before = get_size();
109  set_size( p_size );
110  for(size_t w = before; w < p_size; ++w) this->get_ptr()[w] = filler;
111  }
112 
113  void set_size_in_range(size_t minSize, size_t maxSize) {
114  if (minSize >= maxSize) { set_size( minSize); return; }
115  size_t walk = maxSize;
116  for(;;) {
117  try {
118  set_size(walk);
119  return;
120  } catch(std::bad_alloc) {
121  if (walk <= minSize) throw;
122  // go on
123  }
124  walk >>= 1;
125  if (walk < minSize) walk = minSize;
126  }
127  }
128  void set_size_discard(t_size p_size) {m_alloc.set_size(p_size);}
129  void set_count(t_size p_count) {m_alloc.set_size(p_count);}
130  t_size get_size() const {return m_alloc.get_size();}
131  t_size get_count() const {return m_alloc.get_size();}
132  void force_reset() {m_alloc.force_reset();}
133 
134  const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < get_size());return m_alloc[p_index];}
135  t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < get_size());return m_alloc[p_index];}
136 
138  template<typename t_source>
139  void set_data_fromptr(const t_source * p_buffer,t_size p_count) {
140  set_size(p_count);
141  pfc::copy_array_loop_t(*this,p_buffer,p_count);
142  }
143 
144  template<typename t_array>
145  void append(const t_array & p_source) {
146  if (has_owned_items(p_source)) append(array_t<t_item>(p_source));
147  else {
148  const t_size source_size = array_size_t(p_source);
149  const t_size base = get_size();
150  increase_size(source_size);
151  for(t_size n=0;n<source_size;n++) m_alloc[base+n] = p_source[n];
152  }
153  }
154 
155  template<typename t_insert>
156  void insert_multi(const t_insert & value, t_size base, t_size count) {
157  const t_size oldSize = get_size();
158  if (base > oldSize) base = oldSize;
159  increase_size(count);
160  pfc::memmove_t(get_ptr() + base + count, get_ptr() + base, oldSize - base);
161  pfc::fill_ptr_t(get_ptr() + base, count, value);
162  }
163  template<typename t_append> void append_multi(const t_append & value, t_size count) {insert_multi(value,~0,count);}
164 
166  template<typename t_append>
167  void append_fromptr(const t_append * p_buffer,t_size p_count) {
168  PFC_ASSERT( !is_owned(&p_buffer[0]) );
169  t_size base = get_size();
170  increase_size(p_count);
171  for(t_size n=0;n<p_count;n++) m_alloc[base+n] = p_buffer[n];
172  }
173 
174  void increase_size(t_size p_delta) {
175  t_size new_size = get_size() + p_delta;
176  if (new_size < p_delta) throw std::bad_alloc();
177  set_size(new_size);
178  }
179 
180  template<typename t_append>
181  void append_single_val( t_append item ) {
182  const t_size base = get_size();
183  increase_size(1);
184  m_alloc[base] = item;
185  }
186 
187  template<typename t_append>
188  void append_single(const t_append & p_item) {
189  if (is_owned(p_item)) append_single(t_append(p_item));
190  else {
191  const t_size base = get_size();
192  increase_size(1);
193  m_alloc[base] = p_item;
194  }
195  }
196 
197  template<typename t_filler>
198  void fill(const t_filler & p_filler) {
199  const t_size max = get_size();
200  for(t_size n=0;n<max;n++) m_alloc[n] = p_filler;
201  }
202 
203  void fill_null() {
204  const t_size max = get_size();
205  for(t_size n=0;n<max;n++) m_alloc[n] = 0;
206  }
207 
208  void grow_size(t_size p_size) {
209  if (p_size > get_size()) set_size(p_size);
210  }
211 
212  //not supported by some allocs
213  const t_item * get_ptr() const {return m_alloc.get_ptr();}
214  t_item * get_ptr() {return m_alloc.get_ptr();}
215 
216  void prealloc(t_size p_size) {m_alloc.prealloc(p_size);}
217 
218  template<typename t_array>
219  bool has_owned_items(const t_array & p_source) {
220  if (array_size_t(p_source) == 0) return false;
221 
222  //how the hell would we properly check if any of source items is owned by us, in case source array implements some weird mixing of references of items from different sources?
223  //the most obvious way means evil bottleneck here (whether it matters or not from caller's point of view which does something O(n) already is another question)
224  //at least this will work fine with all standard classes which don't crossreference anyhow and always use own storage
225  //perhaps we'll traitify this someday later
226  return is_owned(p_source[0]);
227  }
228 
229  template<typename t_source>
230  bool is_owned(const t_source & p_item) {
231  return m_alloc.is_ptr_owned(&p_item);
232  }
233 
234  template<typename t_item>
235  void set_single(const t_item & p_item) {
236  set_size(1);
237  (*this)[0] = p_item;
238  }
239 
240  template<typename t_callback> void enumerate(t_callback & p_callback) const { for(t_size n = 0; n < get_size(); n++ ) { p_callback((*this)[n]); } }
241 
242  void move_from(t_self & other) {
243  m_alloc.move_from(other.m_alloc);
244  }
245  private:
247  };
248 
249  template<typename t_item,t_size p_width,template<typename> class t_alloc = alloc_standard >
250  class array_hybrid_t : public array_t<t_item, pfc::alloc_hybrid<p_width,t_alloc>::template alloc >
251  {};
252 
253 
254  template<typename t_item> class traits_t<array_staticsize_t<t_item> > : public traits_default_movable {};
255  template<typename t_item,template<typename> class t_alloc> class traits_t<array_t<t_item,t_alloc> > : public pfc::traits_t<t_alloc<t_item> > {};
256 
257 
258  template<typename t_comparator = comparator_default>
260  public:
261  template<typename t_array1, typename t_array2>
262  static int compare(const t_array1 & p_array1, const t_array2 & p_array2) {
263  t_size walk = 0;
264  for(;;) {
265  if (walk >= p_array1.get_size() && walk >= p_array2.get_size()) return 0;
266  else if (walk >= p_array1.get_size()) return -1;
267  else if (walk >= p_array2.get_size()) return 1;
268  else {
269  int state = t_comparator::compare(p_array1[walk],p_array2[walk]);
270  if (state != 0) return state;
271  }
272  ++walk;
273  }
274  }
275  };
276 
277  template<typename t_a1, typename t_a2>
278  static bool array_equals(const t_a1 & arr1, const t_a2 & arr2) {
279  const t_size s = array_size_t(arr1);
280  if (s != array_size_t(arr2)) return false;
281  for(t_size walk = 0; walk < s; ++walk) {
282  if (arr1[walk] != arr2[walk]) return false;
283  }
284  return true;
285  }
286 
287 
288 
289  template<typename t_item, template<typename> class t_alloc = alloc_standard> class array_2d_t {
290  public:
291  array_2d_t() : m_d1(), m_d2() {}
292  void set_size(t_size d1, t_size d2) {
293  m_content.set_size(pfc::mul_safe_t<std::bad_alloc>(d1, d2));
294  m_d1 = d1; m_d2 = d2;
295  }
296  t_size get_dim1() const {return m_d1;}
297  t_size get_dim2() const {return m_d2;}
298 
299  t_item & at(t_size i1, t_size i2) {
300  return * _transformPtr(m_content.get_ptr(), i1, i2);
301  }
302  const t_item & at(t_size i1, t_size i2) const {
303  return * _transformPtr(m_content.get_ptr(), i1, i2);
304  }
305  template<typename t_filler> void fill(const t_filler & p_filler) {m_content.fill(p_filler);}
307 
308  t_item * rowPtr(t_size i1) {return _transformPtr(m_content.get_ptr(), i1, 0);}
309  const t_item * rowPtr(t_size i1) const {return _transformPtr(m_content.get_ptr(), i1, 0);}
310 
311  const t_item * operator[](t_size i1) const {return rowPtr(i1);}
312  t_item * operator[](t_size i1) {return rowPtr(i1);}
313  private:
314  template<typename t_ptr> t_ptr _transformPtr(t_ptr ptr, t_size i1, t_size i2) const {
315  PFC_ASSERT( i1 < m_d1 ); PFC_ASSERT( i2 < m_d2 );
316  return ptr + i1 * m_d2 + i2;
317  }
320  };
321 
322 }
323 
324 
325 #endif //_PFC_ARRAY_H_
void increase_size(t_size p_delta)
Definition: array.h:174
const t_item & at(t_size i1, t_size i2) const
Definition: array.h:302
void set_size_in_range(size_t minSize, size_t maxSize)
Definition: array.h:113
const t_item * get_ptr() const
Definition: array.h:52
array_staticsize_t(t_size p_size)
Definition: array.h:16
const t_item * get_ptr() const
Definition: array.h:213
array_t(const t_self &p_source)
Definition: array.h:96
t_alloc< t_item > m_alloc
Definition: array.h:246
array_t()
Definition: array.h:95
void set_size_fill(size_t p_size, fill_t const &filler)
Definition: array.h:107
Special simplififed version of array class that avoids stepping on landmines with classes without pub...
Definition: array.h:11
t_size m_d1
Definition: array.h:319
const t_item * rowPtr(t_size i1) const
Definition: array.h:309
void append_multi(const t_append &value, t_size count)
Definition: array.h:163
t_type replace_null_t(t_type &p_var)
Definition: primitives.h:688
const t_item & operator[](t_size p_index) const
Definition: array.h:55
array_t(const t_source &p_source)
Definition: array.h:97
array_staticsize_t< t_item > t_self
Definition: array.h:13
int compare(t1 const &p1, t2 const &p2)
Definition: pathUtils.h:29
t_size get_dim1() const
Definition: array.h:296
void fill_ptr_t(t_array *p_buffer, const t_size p_count, const t_filler &p_filler)
Definition: primitives.h:330
t_item * m_array
Definition: array.h:66
t_item & operator[](t_size p_index)
Definition: array.h:56
array_staticsize_t(const t_self &p_source)
Copy constructor nonfunctional when data type is not copyable.
Definition: array.h:20
t_item & operator[](t_size p_index)
Definition: array.h:135
void move_from(t_self &other)
Definition: array.h:242
void append_single(const t_append &p_item)
Definition: array.h:188
t_item * get_ptr()
Definition: array.h:214
void append_single_val(t_append item)
Definition: array.h:181
const t_item * operator[](t_size i1) const
Definition: array.h:311
t_size get_dim2() const
Definition: array.h:297
t_item & at(t_size i1, t_size i2)
Definition: array.h:299
array_t(t_self &&p_source)
Definition: array.h:101
array_t< t_item, t_alloc > t_self
Definition: array.h:93
void copy_array_t(t_to &p_to, const t_from &p_from)
Definition: array.h:71
void copy_array_loop_t(t_dst &p_dst, const t_src &p_src, t_size p_count)
Definition: primitives.h:616
void set_count(t_size p_count)
Definition: array.h:129
bool is_owned(const t_source &p_item)
Definition: array.h:58
size_t t_size
Definition: int_types.h:48
const t_self & operator=(t_self &&p_source)
Definition: array.h:102
void set_size(t_size p_size)
Definition: array.h:104
void memmove_t(T *p_dst, const T *p_src, t_size p_count)
Definition: primitives.h:649
const t_item & operator[](t_size p_index) const
Definition: array.h:134
void prealloc(t_size p_size)
Definition: array.h:216
void fill_array_t(t_array &p_array, const t_value &p_value)
Definition: array.h:86
void enumerate(t_out &out) const
Definition: array.h:60
const t_self & operator=(const t_self &p_source)
Definition: array.h:98
void append_fromptr(const t_append *p_buffer, t_size p_count)
Warning: buffer pointer must not point to buffer allocated by this array (fixme). ...
Definition: array.h:167
void fill_null()
Definition: array.h:306
pfc::array_t< t_item, t_alloc > m_content
Definition: array.h:318
t_size get_count() const
Definition: array.h:131
void fill(const t_filler &p_filler)
Definition: array.h:305
void set_data_fromptr(const t_source *p_buffer, t_size p_count)
Warning: buffer pointer must not point to buffer allocated by this array (fixme). ...
Definition: array.h:139
void fill(const t_filler &p_filler)
Definition: array.h:198
void fill_null()
Definition: array.h:203
_t_item t_item
Definition: array.h:92
bool has_owned_items(const t_array &p_source)
Definition: array.h:219
void set_size(t_size d1, t_size d2)
Definition: array.h:292
t_item * get_ptr()
Definition: array.h:53
void fill_t(t_array &p_buffer, const t_size p_count, const t_filler &p_filler)
Definition: primitives.h:324
t_size array_size_t(const t_array &p_array)
Definition: primitives.h:309
void insert_multi(const t_insert &value, t_size base, t_size count)
Definition: array.h:156
t_ptr _transformPtr(t_ptr ptr, t_size i1, t_size i2) const
Definition: array.h:314
void append(const t_array &p_source)
Definition: array.h:145
t_item * rowPtr(t_size i1)
Definition: array.h:308
void enumerate(t_callback &p_callback) const
Definition: array.h:240
void set_size_discard(t_size p_size)
Definition: array.h:128
t_size get_size() const
Definition: array.h:51
const t_self & operator=(const t_self &p_source)
Copy operator nonfunctional when data type is not copyable.
Definition: array.h:25
void set_size_discard(t_size p_size)
Definition: array.h:36
void force_reset()
Definition: array.h:132
static bool array_equals(const t_a1 &arr1, const t_a2 &arr2)
Definition: array.h:278
void set_single(const t_item &p_item)
Definition: array.h:235
t_size get_size() const
Definition: array.h:130
const t_self & operator=(const t_source &p_source)
Definition: array.h:99
t_item * operator[](t_size i1)
Definition: array.h:312
void grow_size(t_size p_size)
Definition: array.h:208
void set_data_fromptr(const t_source *p_buffer, t_size p_count)
Warning: buffer pointer must not point to buffer allocated by this array (fixme). ...
Definition: array.h:45
static int compare(const t_array1 &p_array1, const t_array2 &p_array2)
Definition: array.h:262
t_size m_d2
Definition: array.h:319
bool is_pointer_in_range(const t_item *p_buffer, t_size p_buffer_size, const void *p_pointer)
Definition: alloc.h:84
bool is_owned(const t_source &p_item)
Definition: array.h:230