foobar2000 SDK  2015-01-14
primitives.h
Go to the documentation of this file.
1 #define tabsize(x) ((size_t)(sizeof(x)/sizeof(*x)))
2 #define PFC_TABSIZE(x) ((size_t)(sizeof(x)/sizeof(*x)))
3 
4 #define TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD_WITH_INITIALIZER(THISCLASS,MEMBER,INITIALIZER) \
5  THISCLASS() : MEMBER() INITIALIZER \
6  template<typename t_param1> THISCLASS(const t_param1 & p_param1) : MEMBER(p_param1) INITIALIZER \
7  template<typename t_param1,typename t_param2> THISCLASS(const t_param1 & p_param1,const t_param2 & p_param2) : MEMBER(p_param1,p_param2) INITIALIZER \
8  template<typename t_param1,typename t_param2,typename t_param3> THISCLASS(const t_param1 & p_param1,const t_param2 & p_param2,const t_param3 & p_param3) : MEMBER(p_param1,p_param2,p_param3) INITIALIZER \
9  template<typename t_param1,typename t_param2,typename t_param3,typename t_param4> THISCLASS(const t_param1 & p_param1,const t_param2 & p_param2,const t_param3 & p_param3,const t_param4 & p_param4) : MEMBER(p_param1,p_param2,p_param3,p_param4) INITIALIZER \
10  template<typename t_param1,typename t_param2,typename t_param3,typename t_param4,typename t_param5> THISCLASS(const t_param1 & p_param1,const t_param2 & p_param2,const t_param3 & p_param3,const t_param4 & p_param4,const t_param5 & p_param5) : MEMBER(p_param1,p_param2,p_param3,p_param4,p_param5) INITIALIZER \
11  template<typename t_param1,typename t_param2,typename t_param3,typename t_param4,typename t_param5,typename t_param6> THISCLASS(const t_param1 & p_param1,const t_param2 & p_param2,const t_param3 & p_param3,const t_param4 & p_param4,const t_param5 & p_param5,const t_param6 & p_param6) : MEMBER(p_param1,p_param2,p_param3,p_param4,p_param5,p_param6) INITIALIZER \
12  template<typename t_param1,typename t_param2,typename t_param3,typename t_param4,typename t_param5,typename t_param6, typename t_param7> THISCLASS(const t_param1 & p_param1,const t_param2 & p_param2,const t_param3 & p_param3,const t_param4 & p_param4,const t_param5 & p_param5,const t_param6 & p_param6,const t_param7 & p_param7) : MEMBER(p_param1,p_param2,p_param3,p_param4,p_param5,p_param6,p_param7) INITIALIZER \
13  template<typename t_param1,typename t_param2,typename t_param3,typename t_param4,typename t_param5,typename t_param6, typename t_param7, typename t_param8> THISCLASS(const t_param1 & p_param1,const t_param2 & p_param2,const t_param3 & p_param3,const t_param4 & p_param4,const t_param5 & p_param5,const t_param6 & p_param6,const t_param7 & p_param7, const t_param8 & p_param8) : MEMBER(p_param1,p_param2,p_param3,p_param4,p_param5,p_param6,p_param7, p_param8) INITIALIZER
14 
15 #define TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD(THISCLASS,MEMBER) TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD_WITH_INITIALIZER(THISCLASS,MEMBER,{})
16 
17 
18 #ifdef _WIN32
19 
20 #ifndef _MSC_VER
21 #error MSVC expected
22 #endif
23 
24 // MSVC specific - part of fb2k ABI - cannot ever change on MSVC/Windows
25 
26 #define PFC_DECLARE_EXCEPTION(NAME,BASECLASS,DEFAULTMSG) \
27 class NAME : public BASECLASS { \
28 public: \
29  static const char * g_what() {return DEFAULTMSG;} \
30  NAME() : BASECLASS(DEFAULTMSG,0) {} \
31  NAME(const char * p_msg) : BASECLASS(p_msg) {} \
32  NAME(const char * p_msg,int) : BASECLASS(p_msg,0) {} \
33  NAME(const NAME & p_source) : BASECLASS(p_source) {} \
34 };
35 
36 namespace pfc {
37  template<typename t_exception> PFC_NORETURN inline void throw_exception_with_message(const char * p_message) {
38  throw t_exception(p_message);
39  }
40 }
41 
42 #else
43 
44 #define PFC_DECLARE_EXCEPTION(NAME,BASECLASS,DEFAULTMSG) \
45 class NAME : public BASECLASS { \
46 public: \
47  static const char * g_what() {return DEFAULTMSG;} \
48  const char* what() const throw() {return DEFAULTMSG;} \
49 };
50 
51 namespace pfc {
52  template<typename t_base> class __exception_with_message_t : public t_base {
54  public:
55  __exception_with_message_t(const char * p_message) : m_message(NULL) {
56  set_message(p_message);
57  }
59  __exception_with_message_t(const t_self & p_source) : m_message(NULL) {set_message(p_source.m_message);}
60 
61  const char* what() const throw() {return m_message != NULL ? m_message : "unnamed exception";}
62 
63  const t_self & operator=(const t_self & p_source) {set_message(p_source.m_message);}
64 
66 
67  private:
68  void set_message(const char * p_message) throw() {
69  cleanup();
70  if (p_message != NULL) m_message = strdup(p_message);
71  }
72  void cleanup() throw() {
73  if (m_message != NULL) {free(m_message); m_message = NULL;}
74  }
75  char * m_message;
76  };
77  template<typename t_exception> PFC_NORETURN void throw_exception_with_message(const char * p_message) {
79  }
80 }
81 #endif
82 
83 namespace pfc {
84 
85  template<typename p_type1,typename p_type2> class assert_same_type;
86  template<typename p_type> class assert_same_type<p_type,p_type> {};
87 
88  template<typename p_type1,typename p_type2>
89  class is_same_type { public: enum {value = false}; };
90  template<typename p_type>
91  class is_same_type<p_type,p_type> { public: enum {value = true}; };
92 
93  template<bool val> class static_assert_t;
94  template<> class static_assert_t<true> {};
95 
96 #define PFC_STATIC_ASSERT(X) { ::pfc::static_assert_t<(X)>(); }
97 
98  template<typename t_type>
100 
101  template<typename t_type> class assert_byte_type;
102  template<> class assert_byte_type<char> {};
103  template<> class assert_byte_type<unsigned char> {};
104  template<> class assert_byte_type<signed char> {};
105 
106 
107  template<typename t_type> void __unsafe__memcpy_t(t_type * p_dst,const t_type * p_src,t_size p_count) {
108  ::memcpy(reinterpret_cast<void*>(p_dst), reinterpret_cast<const void*>(p_src), p_count * sizeof(t_type));
109  }
110 
111  template<typename t_type> void __unsafe__in_place_destructor_t(t_type & p_item) throw() {
112  if (traits_t<t_type>::needs_destructor) try{ p_item.~t_type(); } catch(...) {}
113  }
114 
115  template<typename t_type> void __unsafe__in_place_constructor_t(t_type & p_item) {
117  t_type * ret = new(&p_item) t_type;
118  PFC_ASSERT(ret == &p_item);
119  (void) ret; // suppress warning
120  }
121  }
122 
123  template<typename t_type> void __unsafe__in_place_destructor_array_t(t_type * p_items, t_size p_count) throw() {
125  t_type * walk = p_items;
126  for(t_size n=p_count;n;--n) __unsafe__in_place_destructor_t(*(walk++));
127  }
128  }
129 
130  template<typename t_type> t_type * __unsafe__in_place_constructor_array_t(t_type * p_items,t_size p_count) {
132  t_size walkptr = 0;
133  try {
134  for(walkptr=0;walkptr<p_count;++walkptr) __unsafe__in_place_constructor_t(p_items[walkptr]);
135  } catch(...) {
136  __unsafe__in_place_destructor_array_t(p_items,walkptr);
137  throw;
138  }
139  }
140  return p_items;
141  }
142 
143  template<typename t_type> t_type * __unsafe__in_place_resize_array_t(t_type * p_items,t_size p_from,t_size p_to) {
144  if (p_from < p_to) __unsafe__in_place_constructor_array_t(p_items + p_from, p_to - p_from);
145  else if (p_from > p_to) __unsafe__in_place_destructor_array_t(p_items + p_to, p_from - p_to);
146  return p_items;
147  }
148 
149  template<typename t_type,typename t_copy> void __unsafe__in_place_constructor_copy_t(t_type & p_item,const t_copy & p_copyfrom) {
151  t_type * ret = new(&p_item) t_type(p_copyfrom);
152  PFC_ASSERT(ret == &p_item);
153  (void) ret; // suppress warning
154  } else {
155  p_item = p_copyfrom;
156  }
157  }
158 
159  template<typename t_type,typename t_copy> t_type * __unsafe__in_place_constructor_array_copy_t(t_type * p_items,t_size p_count, const t_copy * p_copyfrom) {
160  t_size walkptr = 0;
161  try {
162  for(walkptr=0;walkptr<p_count;++walkptr) __unsafe__in_place_constructor_copy_t(p_items[walkptr],p_copyfrom[walkptr]);
163  } catch(...) {
164  __unsafe__in_place_destructor_array_t(p_items,walkptr);
165  throw;
166  }
167  return p_items;
168  }
169 
170  template<typename t_type,typename t_copy> t_type * __unsafe__in_place_constructor_array_copy_partial_t(t_type * p_items,t_size p_count, const t_copy * p_copyfrom,t_size p_copyfrom_count) {
171  if (p_copyfrom_count > p_count) p_copyfrom_count = p_count;
172  __unsafe__in_place_constructor_array_copy_t(p_items,p_copyfrom_count,p_copyfrom);
173  try {
174  __unsafe__in_place_constructor_array_t(p_items + p_copyfrom_count,p_count - p_copyfrom_count);
175  } catch(...) {
176  __unsafe__in_place_destructor_array_t(p_items,p_copyfrom_count);
177  throw;
178  }
179  return p_items;
180  }
181 
182  template<typename t_ret> t_ret implicit_cast(t_ret val) {return val;}
183 
184  template<typename t_ret,typename t_param>
185  t_ret * safe_ptr_cast(t_param * p_param) {
186  if (pfc::is_same_type<t_ret,t_param>::value) return p_param;
187  else {
188  if (p_param == NULL) return NULL;
189  else return p_param;
190  }
191  }
192 
194 
195  PFC_DECLARE_EXCEPTION(exception_overflow,exception,"Overflow");
196  PFC_DECLARE_EXCEPTION(exception_bug_check,exception,"Bug check");
197  PFC_DECLARE_EXCEPTION(exception_invalid_params,exception_bug_check,"Invalid parameters");
198  PFC_DECLARE_EXCEPTION(exception_unexpected_recursion,exception_bug_check,"Unexpected recursion");
199  PFC_DECLARE_EXCEPTION(exception_not_implemented,exception_bug_check,"Feature not implemented");
200  PFC_DECLARE_EXCEPTION(exception_dynamic_assert,exception_bug_check,"dynamic_assert failure");
201 
202  template<typename t_ret,typename t_param>
203  t_ret downcast_guarded(const t_param & p_param) {
204  t_ret temp = (t_ret) p_param;
205  if ((t_param) temp != p_param) throw exception_overflow();
206  return temp;
207  }
208 
209  template<typename t_exception,typename t_ret,typename t_param>
210  t_ret downcast_guarded_ex(const t_param & p_param) {
211  t_ret temp = (t_ret) p_param;
212  if ((t_param) temp != p_param) throw t_exception();
213  return temp;
214  }
215 
216  template<typename t_acc,typename t_add>
217  void accumulate_guarded(t_acc & p_acc, const t_add & p_add) {
218  t_acc delta = downcast_guarded<t_acc>(p_add);
219  delta += p_acc;
220  if (delta < p_acc) throw exception_overflow();
221  p_acc = delta;
222  }
223 
224  //deprecated
225  inline void bug_check_assert(bool p_condition, const char * p_msg) {
226  if (!p_condition) {
227  PFC_ASSERT(0);
228  throw_exception_with_message<exception_bug_check>(p_msg);
229  }
230  }
231  //deprecated
232  inline void bug_check_assert(bool p_condition) {
233  if (!p_condition) {
234  PFC_ASSERT(0);
235  throw exception_bug_check();
236  }
237  }
238 
239  inline void dynamic_assert(bool p_condition, const char * p_msg) {
240  if (!p_condition) {
241  PFC_ASSERT(0);
242  throw_exception_with_message<exception_dynamic_assert>(p_msg);
243  }
244  }
245  inline void dynamic_assert(bool p_condition) {
246  if (!p_condition) {
247  PFC_ASSERT(0);
248  throw exception_dynamic_assert();
249  }
250  }
251 
252  template<typename T>
253  inline void swap_multi_t(T * p_buffer1,T * p_buffer2,t_size p_size) {
254  T * walk1 = p_buffer1, * walk2 = p_buffer2;
255  for(t_size n=p_size;n;--n) {
256  T temp (* walk1);
257  *walk1 = *walk2;
258  *walk2 = temp;
259  walk1++; walk2++;
260  }
261  }
262 
263  template<typename T,t_size p_size>
264  inline void swap_multi_t(T * p_buffer1,T * p_buffer2) {
265  T * walk1 = p_buffer1, * walk2 = p_buffer2;
266  for(t_size n=p_size;n;--n) {
267  T temp (* walk1);
268  *walk1 = *walk2;
269  *walk2 = temp;
270  walk1++; walk2++;
271  }
272  }
273 
274 
275  template<t_size p_size>
276  inline void __unsafe__swap_raw_t(void * p_object1, void * p_object2) {
277  if (p_size % sizeof(t_size) == 0) {
278  swap_multi_t<t_size,p_size/sizeof(t_size)>(reinterpret_cast<t_size*>(p_object1),reinterpret_cast<t_size*>(p_object2));
279  } else {
280  swap_multi_t<t_uint8,p_size>(reinterpret_cast<t_uint8*>(p_object1),reinterpret_cast<t_uint8*>(p_object2));
281  }
282  }
283 
284  template<typename T>
285  inline void swap_t(T & p_item1, T & p_item2) {
287  __unsafe__swap_raw_t<sizeof(T)>( reinterpret_cast<void*>( &p_item1 ), reinterpret_cast<void*>( &p_item2 ) );
288  } else {
289  T temp( std::move(p_item2) );
290  p_item2 = std::move(p_item1);
291  p_item1 = std::move(temp);
292  }
293  }
294 
297  template<typename T>
298  inline void move_t(T & p_item1, T & p_item2) {
299  typedef traits_t<T> t;
300  if (t::needs_constructor || t::needs_destructor) {
301  if (t::realloc_safe) swap_t(p_item1, p_item2);
302  else p_item1 = std::move( p_item2 );
303  } else {
304  p_item1 = std::move( p_item2 );
305  }
306  }
307 
308  template<typename t_array>
309  t_size array_size_t(const t_array & p_array) {return p_array.get_size();}
310 
311  template<typename t_item, t_size p_width>
312  t_size array_size_t(const t_item (&p_array)[p_width]) {return p_width;}
313 
314  template<typename t_array, typename t_item> static bool array_isLast(const t_array & arr, const t_item & item) {
315  const t_size size = pfc::array_size_t(arr);
316  return size > 0 && arr[size-1] == item;
317  }
318  template<typename t_array, typename t_item> static bool array_isFirst(const t_array & arr, const t_item & item) {
319  const t_size size = pfc::array_size_t(arr);
320  return size > 0 && arr[0] == item;
321  }
322 
323  template<typename t_array,typename t_filler>
324  inline void fill_t(t_array & p_buffer,const t_size p_count, const t_filler & p_filler) {
325  for(t_size n=0;n<p_count;n++)
326  p_buffer[n] = p_filler;
327  }
328 
329  template<typename t_array,typename t_filler>
330  inline void fill_ptr_t(t_array * p_buffer,const t_size p_count, const t_filler & p_filler) {
331  for(t_size n=0;n<p_count;n++)
332  p_buffer[n] = p_filler;
333  }
334 
335  template<typename t_item1, typename t_item2>
336  inline int compare_t(const t_item1 & p_item1, const t_item2 & p_item2) {
337  if (p_item1 < p_item2) return -1;
338  else if (p_item1 > p_item2) return 1;
339  else return 0;
340  }
341 
344  public:
345  template<typename t_item1,typename t_item2>
346  inline static int compare(const t_item1 & p_item1,const t_item2 & p_item2) {return pfc::compare_t(p_item1,p_item2);}
347  };
348 
349  template<typename t_comparator = pfc::comparator_default> class comparator_pointer { public:
350  template<typename t_item1,typename t_item2> static int compare(const t_item1 & p_item1,const t_item2 & p_item2) {return t_comparator::compare(*p_item1,*p_item2);}
351  };
352 
353  template<typename t_primary,typename t_secondary> class comparator_dual { public:
354  template<typename t_item1,typename t_item2> static int compare(const t_item1 & p_item1,const t_item2 & p_item2) {
355  int state = t_primary::compare(p_item1,p_item2);
356  if (state != 0) return state;
357  return t_secondary::compare(p_item1,p_item2);
358  }
359  };
360 
362  public:
363  template<typename t_item1,typename t_item2>
364  inline static int compare(const t_item1 & p_item1,const t_item2 & p_item2) {
366  return memcmp(&p_item1,&p_item2,sizeof(t_item1));
367  }
368  };
369 
370  template<typename t_source1, typename t_source2>
371  t_size subtract_sorted_lists_calculate_count(const t_source1 & p_source1, const t_source2 & p_source2) {
372  t_size walk1 = 0, walk2 = 0, walk_out = 0;
373  const t_size max1 = p_source1.get_size(), max2 = p_source2.get_size();
374  for(;;) {
375  int state;
376  if (walk1 < max1 && walk2 < max2) {
377  state = pfc::compare_t(p_source1[walk1],p_source2[walk2]);
378  } else if (walk1 < max1) {
379  state = -1;
380  } else if (walk2 < max2) {
381  state = 1;
382  } else {
383  break;
384  }
385  if (state < 0) walk_out++;
386  if (state <= 0) walk1++;
387  if (state >= 0) walk2++;
388  }
389  return walk_out;
390  }
391 
394  template<typename t_destination, typename t_source1, typename t_source2>
395  void subtract_sorted_lists(t_destination & p_destination,const t_source1 & p_source1, const t_source2 & p_source2) {
396  p_destination.set_size(subtract_sorted_lists_calculate_count(p_source1,p_source2));
397  t_size walk1 = 0, walk2 = 0, walk_out = 0;
398  const t_size max1 = p_source1.get_size(), max2 = p_source2.get_size();
399  for(;;) {
400  int state;
401  if (walk1 < max1 && walk2 < max2) {
402  state = pfc::compare_t(p_source1[walk1],p_source2[walk2]);
403  } else if (walk1 < max1) {
404  state = -1;
405  } else if (walk2 < max2) {
406  state = 1;
407  } else {
408  break;
409  }
410 
411 
412  if (state < 0) p_destination[walk_out++] = p_source1[walk1];
413  if (state <= 0) walk1++;
414  if (state >= 0) walk2++;
415  }
416  }
417 
418  template<typename t_source1, typename t_source2>
419  t_size merge_sorted_lists_calculate_count(const t_source1 & p_source1, const t_source2 & p_source2) {
420  t_size walk1 = 0, walk2 = 0, walk_out = 0;
421  const t_size max1 = p_source1.get_size(), max2 = p_source2.get_size();
422  for(;;) {
423  int state;
424  if (walk1 < max1 && walk2 < max2) {
425  state = pfc::compare_t(p_source1[walk1],p_source2[walk2]);
426  } else if (walk1 < max1) {
427  state = -1;
428  } else if (walk2 < max2) {
429  state = 1;
430  } else {
431  break;
432  }
433  if (state <= 0) walk1++;
434  if (state >= 0) walk2++;
435  walk_out++;
436  }
437  return walk_out;
438  }
439 
442  template<typename t_destination, typename t_source1, typename t_source2>
443  void merge_sorted_lists(t_destination & p_destination,const t_source1 & p_source1, const t_source2 & p_source2) {
444  p_destination.set_size(merge_sorted_lists_calculate_count(p_source1,p_source2));
445  t_size walk1 = 0, walk2 = 0, walk_out = 0;
446  const t_size max1 = p_source1.get_size(), max2 = p_source2.get_size();
447  for(;;) {
448  int state;
449  if (walk1 < max1 && walk2 < max2) {
450  state = pfc::compare_t(p_source1[walk1],p_source2[walk2]);
451  } else if (walk1 < max1) {
452  state = -1;
453  } else if (walk2 < max2) {
454  state = 1;
455  } else {
456  break;
457  }
458  if (state < 0) {
459  p_destination[walk_out] = p_source1[walk1++];
460  } else if (state > 0) {
461  p_destination[walk_out] = p_source2[walk2++];
462  } else {
463  p_destination[walk_out] = p_source1[walk1];
464  walk1++; walk2++;
465  }
466  walk_out++;
467  }
468  }
469 
470 
471 
472  template<typename t_array,typename T>
473  inline t_size append_t(t_array & p_array,const T & p_item)
474  {
475  t_size old_count = p_array.get_size();
476  p_array.set_size(old_count + 1);
477  p_array[old_count] = p_item;
478  return old_count;
479  }
480 
481  template<typename t_array,typename T>
482  inline t_size append_swap_t(t_array & p_array,T & p_item)
483  {
484  t_size old_count = p_array.get_size();
485  p_array.set_size(old_count + 1);
486  swap_t(p_array[old_count],p_item);
487  return old_count;
488  }
489 
490  template<typename t_array>
491  inline t_size insert_uninitialized_t(t_array & p_array,t_size p_index) {
492  t_size old_count = p_array.get_size();
493  if (p_index > old_count) p_index = old_count;
494  p_array.set_size(old_count + 1);
495  for(t_size n=old_count;n>p_index;n--) move_t(p_array[n], p_array[n-1]);
496  return p_index;
497  }
498 
499  template<typename t_array,typename T>
500  inline t_size insert_t(t_array & p_array,const T & p_item,t_size p_index) {
501  t_size old_count = p_array.get_size();
502  if (p_index > old_count) p_index = old_count;
503  p_array.set_size(old_count + 1);
504  for(t_size n=old_count;n>p_index;n--)
505  move_t(p_array[n], p_array[n-1]);
506  p_array[p_index] = p_item;
507  return p_index;
508  }
509  template<typename array1_t, typename array2_t>
510  void insert_array_t( array1_t & outArray, size_t insertAt, array2_t const & inArray, size_t inArraySize) {
511  const size_t oldSize = outArray.get_size();
512  if (insertAt > oldSize) insertAt = oldSize;
513  const size_t newSize = oldSize + inArraySize;
514  outArray.set_size( newSize );
515  for(size_t m = oldSize; m != insertAt; --m) {
516  move_t( outArray[ m - 1 + inArraySize], outArray[m - 1] );
517  }
518  for(size_t w = 0; w < inArraySize; ++w) {
519  outArray[ insertAt + w ] = inArray[ w ];
520  }
521  }
522 
523  template<typename t_array,typename in_array_t>
524  inline t_size insert_multi_t(t_array & p_array,const in_array_t & p_items, size_t p_itemCount, t_size p_index) {
525  const t_size old_count = p_array.get_size();
526  const size_t new_count = old_count + p_itemCount;
527  if (p_index > old_count) p_index = old_count;
528  p_array.set_size(new_count);
529  size_t toMove = old_count - p_index;
530  for(size_t w = 0; w < toMove; ++w) {
531  move_t( p_array[new_count - 1 - w], p_array[old_count - 1 - w] );
532  }
533 
534  for(size_t w = 0; w < p_itemCount; ++w) {
535  p_array[p_index+w] = p_items[w];
536  }
537 
538  return p_index;
539  }
540  template<typename t_array,typename T>
541  inline t_size insert_swap_t(t_array & p_array,T & p_item,t_size p_index) {
542  t_size old_count = p_array.get_size();
543  if (p_index > old_count) p_index = old_count;
544  p_array.set_size(old_count + 1);
545  for(t_size n=old_count;n>p_index;n--)
546  swap_t(p_array[n],p_array[n-1]);
547  swap_t(p_array[p_index],p_item);
548  return p_index;
549  }
550 
551 
552  template<typename T>
553  inline T max_t(const T & item1, const T & item2) {return item1 > item2 ? item1 : item2;};
554 
555  template<typename T>
556  inline T min_t(const T & item1, const T & item2) {return item1 < item2 ? item1 : item2;};
557 
558  template<typename T>
559  inline T abs_t(T item) {return item<0 ? -item : item;}
560 
561  template<typename T>
562  inline T sqr_t(T item) {return item * item;}
563 
564  template<typename T>
565  inline T clip_t(const T & p_item, const T & p_min, const T & p_max) {
566  if (p_item < p_min) return p_min;
567  else if (p_item <= p_max) return p_item;
568  else return p_max;
569  }
570 
571 
572 
573 
574 
575  template<typename T>
576  inline void delete_t(T* ptr) {delete ptr;}
577 
578  template<typename T>
579  inline void delete_array_t(T* ptr) {delete[] ptr;}
580 
581  template<typename T>
582  inline T* clone_t(T* ptr) {return new T(*ptr);}
583 
584 
585  template<typename t_exception,typename t_int>
586  inline t_int mul_safe_t(t_int p_val1,t_int p_val2) {
587  if (p_val1 == 0 || p_val2 == 0) return 0;
588  t_int temp = (t_int) (p_val1 * p_val2);
589  if (temp / p_val1 != p_val2) throw t_exception();
590  return temp;
591  }
592  template<typename t_int>
594  return mul_safe_t<exception_overflow>(v1, v2);
595  }
596  template<typename t_int> t_int add_unsigned_clipped(t_int v1, t_int v2) {
597  t_int v = v1 + v2;
598  if (v < v1) return ~0;
599  return v;
600  }
601  template<typename t_int> t_int sub_unsigned_clipped(t_int v1, t_int v2) {
602  t_int v = v1 - v2;
603  if (v > v1) return 0;
604  return v;
605  }
606  template<typename t_int> void acc_unsigned_clipped(t_int & v1, t_int v2) {
607  v1 = add_unsigned_clipped(v1, v2);
608  }
609 
610  template<typename t_src,typename t_dst>
611  void memcpy_t(t_dst* p_dst,const t_src* p_src,t_size p_count) {
612  for(t_size n=0;n<p_count;n++) p_dst[n] = p_src[n];
613  }
614 
615  template<typename t_dst,typename t_src>
616  void copy_array_loop_t(t_dst & p_dst,const t_src & p_src,t_size p_count) {
617  for(t_size n=0;n<p_count;n++) p_dst[n] = p_src[n];
618  }
619 
620  template<typename t_src,typename t_dst>
621  void memcpy_backwards_t(t_dst * p_dst,const t_src * p_src,t_size p_count) {
622  p_dst += p_count; p_src += p_count;
623  for(t_size n=0;n<p_count;n++) *(--p_dst) = *(--p_src);
624  }
625 
626  template<typename T,typename t_val>
627  void memset_t(T * p_buffer,const t_val & p_val,t_size p_count) {
628  for(t_size n=0;n<p_count;n++) p_buffer[n] = p_val;
629  }
630 
631  template<typename T,typename t_val>
632  void memset_t(T &p_buffer,const t_val & p_val) {
633  const t_size width = pfc::array_size_t(p_buffer);
634  for(t_size n=0;n<width;n++) p_buffer[n] = p_val;
635  }
636 
637  template<typename T>
638  void memset_null_t(T * p_buffer,t_size p_count) {
639  for(t_size n=0;n<p_count;n++) p_buffer[n] = 0;
640  }
641 
642  template<typename T>
643  void memset_null_t(T &p_buffer) {
644  const t_size width = pfc::array_size_t(p_buffer);
645  for(t_size n=0;n<width;n++) p_buffer[n] = 0;
646  }
647 
648  template<typename T>
649  void memmove_t(T* p_dst,const T* p_src,t_size p_count) {
650  if (p_dst == p_src) {/*do nothing*/}
651  else if (p_dst > p_src && p_dst < p_src + p_count) memcpy_backwards_t<T>(p_dst,p_src,p_count);
652  else memcpy_t<T>(p_dst,p_src,p_count);
653  }
654 
655  template<typename TVal> void memxor_t(TVal * out, const TVal * s1, const TVal * s2, t_size count) {
656  for(t_size walk = 0; walk < count; ++walk) out[walk] = s1[walk] ^ s2[walk];
657  }
658  static void memxor(void * target, const void * source1, const void * source2, t_size size) {
659  memxor_t( reinterpret_cast<t_uint8*>(target), reinterpret_cast<const t_uint8*>(source1), reinterpret_cast<const t_uint8*>(source2), size);
660  }
661 
662  template<typename T>
663  T* new_ptr_check_t(T* p_ptr) {
664  if (p_ptr == NULL) throw std::bad_alloc();
665  return p_ptr;
666  }
667 
668  template<typename T>
669  int sgn_t(const T & p_val) {
670  if (p_val < 0) return -1;
671  else if (p_val > 0) return 1;
672  else return 0;
673  }
674 
675  template<typename T> const T* empty_string_t();
676 
677  template<> inline const char * empty_string_t<char>() {return "";}
678  template<> inline const wchar_t * empty_string_t<wchar_t>() {return L"";}
679 
680 
681  template<typename t_type,typename t_newval>
682  t_type replace_t(t_type & p_var,const t_newval & p_newval) {
683  t_type oldval = p_var;
684  p_var = p_newval;
685  return oldval;
686  }
687  template<typename t_type>
688  t_type replace_null_t(t_type & p_var) {
689  t_type ret = p_var;
690  p_var = 0;
691  return ret;
692  }
693 
694  template<t_size p_size_pow2>
695  inline bool is_ptr_aligned_t(const void * p_ptr) {
696  static_assert_t< (p_size_pow2 & (p_size_pow2 - 1)) == 0 >();
697  return ( ((t_size)p_ptr) & (p_size_pow2-1) ) == 0;
698  }
699 
700 
701  template<typename t_array>
702  void array_rangecheck_t(const t_array & p_array,t_size p_index) {
703  if (p_index >= pfc::array_size_t(p_array)) throw pfc::exception_overflow();
704  }
705 
706  template<typename t_array>
707  void array_rangecheck_t(const t_array & p_array,t_size p_from,t_size p_to) {
708  if (p_from > p_to) throw pfc::exception_overflow();
709  array_rangecheck_t(p_array,p_from); array_rangecheck_t(p_array,p_to);
710  }
711 
712  inline t_int32 rint32(double p_val) {return (t_int32) floor(p_val + 0.5);}
713  inline t_int64 rint64(double p_val) {return (t_int64) floor(p_val + 0.5);}
714 
715 
716 
717 
718  template<typename t_array>
719  inline t_size remove_mask_t(t_array & p_array,const bit_array & p_mask)//returns amount of items left
720  {
721  t_size n,count = p_array.get_size(), total = 0;
722 
723  n = total = p_mask.find(true,0,count);
724 
725  if (n<count)
726  {
727  for(n=p_mask.find(false,n+1,count-n-1);n<count;n=p_mask.find(false,n+1,count-n-1))
728  move_t(p_array[total++],p_array[n]);
729 
730  p_array.set_size(total);
731 
732  return total;
733  }
734  else return count;
735  }
736 
737  template<typename t_array,typename t_compare>
738  t_size find_duplicates_sorted_t(t_array p_array,t_size p_count,t_compare p_compare,bit_array_var & p_out) {
739  t_size ret = 0;
740  t_size n;
741  if (p_count > 0)
742  {
743  p_out.set(0,false);
744  for(n=1;n<p_count;n++)
745  {
746  bool found = p_compare(p_array[n-1],p_array[n]) == 0;
747  if (found) ret++;
748  p_out.set(n,found);
749  }
750  }
751  return ret;
752  }
753 
754  template<typename t_array,typename t_compare,typename t_permutation>
755  t_size find_duplicates_sorted_permutation_t(t_array p_array,t_size p_count,t_compare p_compare,t_permutation const & p_permutation,bit_array_var & p_out) {
756  t_size ret = 0;
757  t_size n;
758  if (p_count > 0) {
759  p_out.set(p_permutation[0],false);
760  for(n=1;n<p_count;n++)
761  {
762  bool found = p_compare(p_array[p_permutation[n-1]],p_array[p_permutation[n]]) == 0;
763  if (found) ret++;
764  p_out.set(p_permutation[n],found);
765  }
766  }
767  return ret;
768  }
769 
770  template<typename t_char>
771  t_size strlen_t(const t_char * p_string,t_size p_length = ~0) {
772  for(t_size walk = 0;;walk++) {
773  if (walk >= p_length || p_string[walk] == 0) return walk;
774  }
775  }
776 
777 
778  template<typename t_array>
780  public:
781  __list_to_array_enumerator(t_array & p_array) : m_array(p_array), m_walk(0) {}
782  template<typename t_item>
783  void operator() (const t_item & p_item) {
784  PFC_ASSERT(m_walk < m_array.get_size());
785  m_array[m_walk++] = p_item;
786  }
787  void finalize() {
788  PFC_ASSERT(m_walk == m_array.get_size());
789  }
790  private:
792  t_array & m_array;
793  };
794 
795  template<typename t_list,typename t_array>
796  void list_to_array(t_array & p_array,const t_list & p_list) {
797  p_array.set_size(p_list.get_count());
798  __list_to_array_enumerator<t_array> enumerator(p_array);
799  p_list.enumerate(enumerator);
800  enumerator.finalize();
801  }
802 
803  template<typename t_receiver>
805  public:
806  enumerator_add_item(t_receiver & p_receiver) : m_receiver(p_receiver) {}
807  template<typename t_item> void operator() (const t_item & p_item) {m_receiver.add_item(p_item);}
808  private:
809  t_receiver & m_receiver;
810  };
811 
812  template<typename t_receiver,typename t_giver>
813  void overwrite_list_enumerated(t_receiver & p_receiver,const t_giver & p_giver) {
814  enumerator_add_item<t_receiver> wrapper(p_receiver);
815  p_giver.enumerate(wrapper);
816  }
817 
818  template<typename t_receiver,typename t_giver>
819  void copy_list_enumerated(t_receiver & p_receiver,const t_giver & p_giver) {
820  p_receiver.remove_all();
821  overwrite_list_enumerated(p_receiver,p_giver);
822  }
823 
824  inline bool lxor(bool p_val1,bool p_val2) {
825  return p_val1 == !p_val2;
826  }
827 
828  template<typename t_val>
829  inline void min_acc(t_val & p_acc,const t_val & p_val) {
830  if (p_val < p_acc) p_acc = p_val;
831  }
832 
833  template<typename t_val>
834  inline void max_acc(t_val & p_acc,const t_val & p_val) {
835  if (p_val > p_acc) p_acc = p_val;
836  }
837 
838  t_uint64 pow_int(t_uint64 base, t_uint64 exp);
839 
840 
841  template<typename t_val>
843  public:
844  incrementScope(t_val & i) : v(i) {++v;}
846  private:
847  t_val & v;
848  };
849 
850  inline unsigned countBits32(uint32_t i) {
851  const uint32_t mask = 0x11111111;
852  uint32_t acc = i & mask;
853  acc += (i >> 1) & mask;
854  acc += (i >> 2) & mask;
855  acc += (i >> 3) & mask;
856 
857  const uint32_t mask2 = 0x0F0F0F0F;
858  uint32_t acc2 = acc & mask2;
859  acc2 += (acc >> 4) & mask2;
860 
861  const uint32_t mask3 = 0x00FF00FF;
862  uint32_t acc3 = acc2 & mask3;
863  acc3 += (acc2 >> 8) & mask3;
864 
865  return (acc3 & 0xFFFF) + ((acc3 >> 16) & 0xFFFF);
866  }
867 
868  // Forward declarations
869  template<typename t_to,typename t_from>
870  void copy_array_t(t_to & p_to,const t_from & p_from);
871 
872  template<typename t_array,typename t_value>
873  void fill_array_t(t_array & p_array,const t_value & p_value);
874 };
875 
876 
877 #define PFC_CLASS_NOT_COPYABLE(THISCLASSNAME,THISTYPE) \
878  private: \
879  THISCLASSNAME(const THISTYPE&); \
880  const THISTYPE & operator=(const THISTYPE &);
881 
882 #define PFC_CLASS_NOT_COPYABLE_EX(THISTYPE) PFC_CLASS_NOT_COPYABLE(THISTYPE,THISTYPE)
const char * what() const
Definition: primitives.h:61
t_type * __unsafe__in_place_resize_array_t(t_type *p_items, t_size p_from, t_size p_to)
Definition: primitives.h:143
For use with avltree/map etc.
Definition: primitives.h:343
void list_to_array(t_array &p_array, const t_list &p_list)
Definition: primitives.h:796
int sgn_t(const T &p_val)
Definition: primitives.h:669
uint8_t t_uint8
Definition: int_types.h:9
void __unsafe__in_place_destructor_array_t(t_type *p_items, t_size p_count)
Definition: primitives.h:123
T min_t(const T &item1, const T &item2)
Definition: primitives.h:556
void set_message(const char *p_message)
Definition: primitives.h:68
void copy_list_enumerated(t_receiver &p_receiver, const t_giver &p_giver)
Definition: primitives.h:819
t_uint64 pow_int(t_uint64 base, t_uint64 exp)
Definition: other.cpp:128
__exception_with_message_t< t_base > t_self
Definition: primitives.h:53
void __unsafe__in_place_destructor_t(t_type &p_item)
Definition: primitives.h:111
uint64_t t_uint64
Definition: int_types.h:3
virtual t_size find(bool val, t_size start, t_ssize count) const
Returns the first occurance of val between start and start+count (excluding start+count), or start+count if not found; count may be negative to search back rather than forward. Can be overridden by bit_array implementations for improved speed in specific cases.
Definition: bit_array.h:11
void memxor_t(TVal *out, const TVal *s1, const TVal *s2, t_size count)
Definition: primitives.h:655
t_size subtract_sorted_lists_calculate_count(const t_source1 &p_source1, const t_source2 &p_source2)
Definition: primitives.h:371
t_type replace_null_t(t_type &p_var)
Definition: primitives.h:688
t_size find_duplicates_sorted_permutation_t(t_array p_array, t_size p_count, t_compare p_compare, t_permutation const &p_permutation, bit_array_var &p_out)
Definition: primitives.h:755
t_int multiply_guarded(t_int v1, t_int v2)
Definition: primitives.h:593
Bit array interface class, constant version (you can only retrieve values). Range of valid indexes d...
Definition: bit_array.h:6
int compare(t1 const &p1, t2 const &p2)
Definition: pathUtils.h:29
t_ret * safe_ptr_cast(t_param *p_param)
Definition: primitives.h:185
t_int sub_unsigned_clipped(t_int v1, t_int v2)
Definition: primitives.h:601
t_size merge_sorted_lists_calculate_count(const t_source1 &p_source1, const t_source2 &p_source2)
Definition: primitives.h:419
void fill_ptr_t(t_array *p_buffer, const t_size p_count, const t_filler &p_filler)
Definition: primitives.h:330
void memcpy_backwards_t(t_dst *p_dst, const t_src *p_src, t_size p_count)
Definition: primitives.h:621
void operator()(const t_item &p_item)
Definition: primitives.h:807
t_receiver & m_receiver
Definition: primitives.h:809
t_size remove_mask_t(t_array &p_array, const bit_array &p_mask)
Definition: primitives.h:719
t_int add_unsigned_clipped(t_int v1, t_int v2)
Definition: primitives.h:596
int t_int
Definition: int_types.h:11
bool is_ptr_aligned_t(const void *p_ptr)
Definition: primitives.h:695
t_type replace_t(t_type &p_var, const t_newval &p_newval)
Definition: primitives.h:682
T * clone_t(T *ptr)
Definition: primitives.h:582
static int compare(const t_item1 &p_item1, const t_item2 &p_item2)
Definition: primitives.h:350
unsigned countBits32(uint32_t i)
Definition: primitives.h:850
void dynamic_assert(bool p_condition, const char *p_msg)
Definition: primitives.h:239
t_size append_t(t_array &p_array, const T &p_item)
Definition: primitives.h:473
int32_t t_int32
Definition: int_types.h:4
void move_t(T &p_item1, T &p_item2)
This is similar to plain p_item1 = p_item2; assignment, but optimized for the case where p_item2 cont...
Definition: primitives.h:298
t_type * __unsafe__in_place_constructor_array_copy_t(t_type *p_items, t_size p_count, const t_copy *p_copyfrom)
Definition: primitives.h:159
enumerator_add_item(t_receiver &p_receiver)
Definition: primitives.h:806
void max_acc(t_val &p_acc, const t_val &p_val)
Definition: primitives.h:834
void merge_sorted_lists(t_destination &p_destination, const t_source1 &p_source1, const t_source2 &p_source2)
Merges p_source1 and p_source2, storing content in p_destination. Both source lists must be sorted...
Definition: primitives.h:443
void __unsafe__swap_raw_t(void *p_object1, void *p_object2)
Definition: primitives.h:276
__exception_with_message_t(const char *p_message)
Definition: primitives.h:55
virtual void set(t_size n, bool val)=0
static void memxor(void *target, const void *source1, const void *source2, t_size size)
Definition: primitives.h:658
void insert_array_t(array1_t &outArray, size_t insertAt, array2_t const &inArray, size_t inArraySize)
Definition: primitives.h:510
bool lxor(bool p_val1, bool p_val2)
Definition: primitives.h:824
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
T abs_t(T item)
Definition: primitives.h:559
void acc_unsigned_clipped(t_int &v1, t_int v2)
Definition: primitives.h:606
t_size strlen_t(const t_char *p_string, t_size p_length=~0)
Definition: primitives.h:771
size_t t_size
Definition: int_types.h:48
void operator()(const t_item &p_item)
Definition: primitives.h:783
t_size insert_multi_t(t_array &p_array, const in_array_t &p_items, size_t p_itemCount, t_size p_index)
Definition: primitives.h:524
const wchar_t * empty_string_t< wchar_t >()
Definition: primitives.h:678
void memmove_t(T *p_dst, const T *p_src, t_size p_count)
Definition: primitives.h:649
void assert_raw_type()
Definition: primitives.h:99
void subtract_sorted_lists(t_destination &p_destination, const t_source1 &p_source1, const t_source2 &p_source2)
Subtracts p_source2 contents from p_source1 and stores result in p_destination. Both source lists mus...
Definition: primitives.h:395
t_int64 rint64(double p_val)
Definition: primitives.h:713
t_int32 rint32(double p_val)
Definition: primitives.h:712
t_size append_swap_t(t_array &p_array, T &p_item)
Definition: primitives.h:482
void memset_null_t(T *p_buffer, t_size p_count)
Definition: primitives.h:638
void delete_array_t(T *ptr)
Definition: primitives.h:579
void fill_array_t(t_array &p_array, const t_value &p_value)
Definition: array.h:86
int compare_t(const hasher_md5_result &p_item1, const hasher_md5_result &p_item2)
Definition: hasher_md5.h:20
static bool array_isFirst(const t_array &arr, const t_item &item)
Definition: primitives.h:318
Bit array interface class, variable version (you can both set and retrieve values). As with the constant version, valid index range depends on the context.
Definition: bit_array.h:40
T * new_ptr_check_t(T *p_ptr)
Definition: primitives.h:663
t_ret downcast_guarded(const t_param &p_param)
Definition: primitives.h:203
const char * empty_string_t< char >()
Definition: primitives.h:677
incrementScope(t_val &i)
Definition: primitives.h:844
void accumulate_guarded(t_acc &p_acc, const t_add &p_add)
Definition: primitives.h:217
T clip_t(const T &p_item, const T &p_min, const T &p_max)
Definition: primitives.h:565
void delete_t(T *ptr)
Definition: primitives.h:576
static bool array_isLast(const t_array &arr, const t_item &item)
Definition: primitives.h:314
t_size find_duplicates_sorted_t(t_array p_array, t_size p_count, t_compare p_compare, bit_array_var &p_out)
Definition: primitives.h:738
std::exception exception
Definition: primitives.h:193
t_ret downcast_guarded_ex(const t_param &p_param)
Definition: primitives.h:210
void __unsafe__in_place_constructor_t(t_type &p_item)
Definition: primitives.h:115
const t_self & operator=(const t_self &p_source)
Definition: primitives.h:63
t_ret implicit_cast(t_ret val)
Definition: primitives.h:182
void fill_t(t_array &p_buffer, const t_size p_count, const t_filler &p_filler)
Definition: primitives.h:324
t_type * __unsafe__in_place_constructor_array_t(t_type *p_items, t_size p_count)
Definition: primitives.h:130
t_size array_size_t(const t_array &p_array)
Definition: primitives.h:309
PFC_NORETURN void throw_exception_with_message(const char *p_message)
Definition: primitives.h:37
T sqr_t(T item)
Definition: primitives.h:562
t_int mul_safe_t(t_int p_val1, t_int p_val2)
Definition: primitives.h:586
__exception_with_message_t(const t_self &p_source)
Definition: primitives.h:59
t_type * __unsafe__in_place_constructor_array_copy_partial_t(t_type *p_items, t_size p_count, const t_copy *p_copyfrom, t_size p_copyfrom_count)
Definition: primitives.h:170
__list_to_array_enumerator(t_array &p_array)
Definition: primitives.h:781
void __unsafe__memcpy_t(t_type *p_dst, const t_type *p_src, t_size p_count)
Definition: primitives.h:107
void overwrite_list_enumerated(t_receiver &p_receiver, const t_giver &p_giver)
Definition: primitives.h:813
t_size insert_swap_t(t_array &p_array, T &p_item, t_size p_index)
Definition: primitives.h:541
void memcpy_t(t_dst *p_dst, const t_src *p_src, t_size p_count)
Definition: primitives.h:611
static int compare(const t_item1 &p_item1, const t_item2 &p_item2)
Definition: primitives.h:346
void array_rangecheck_t(const t_array &p_array, t_size p_index)
Definition: primitives.h:702
static int compare(const t_item1 &p_item1, const t_item2 &p_item2)
Definition: primitives.h:364
void swap_multi_t(T *p_buffer1, T *p_buffer2, t_size p_size)
Definition: primitives.h:253
void swap_t(T &p_item1, T &p_item2)
Definition: primitives.h:285
t_size insert_uninitialized_t(t_array &p_array, t_size p_index)
Definition: primitives.h:491
const T * empty_string_t()
PFC_DECLARE_EXCEPTION(exception_map_entry_not_found, exception,"Map entry not found")
T max_t(const T &item1, const T &item2)
Definition: primitives.h:553
void memset_t(T *p_buffer, const t_val &p_val, t_size p_count)
Definition: primitives.h:627
void __unsafe__in_place_constructor_copy_t(t_type &p_item, const t_copy &p_copyfrom)
Definition: primitives.h:149
t_size insert_t(t_array &p_array, const T &p_item, t_size p_index)
Definition: primitives.h:500
void min_acc(t_val &p_acc, const t_val &p_val)
Definition: primitives.h:829
int64_t t_int64
Definition: int_types.h:2
void bug_check_assert(bool p_condition, const char *p_msg)
Definition: primitives.h:225
static int compare(const t_item1 &p_item1, const t_item2 &p_item2)
Definition: primitives.h:354