/thirdparty/liblastfm2/src/fingerprint/fplib/CircularArray.h

http://github.com/tomahawk-player/tomahawk · C Header · 292 lines · 191 code · 54 blank · 47 comment · 16 complexity · db07a823c8104ba66b9eb4bbdc519fb1 MD5 · raw file

  1. /*
  2. Copyright 2005-2009 Last.fm Ltd. <mir@last.fm>
  3. This file is part of liblastfm.
  4. liblastfm 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 3 of the License, or
  7. (at your option) any later version.
  8. liblastfm is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with liblastfm. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #ifndef __CIRCULAR_ARRAY_H
  16. #define __CIRCULAR_ARRAY_H
  17. #include <iostream>
  18. #include <iterator>
  19. #include <vector>
  20. #include <algorithm>
  21. #include <cstdlib> // for memset
  22. #include <algorithm> // for max
  23. #ifndef NULL
  24. #define NULL 0
  25. #endif
  26. template< typename T >
  27. class CircularArray
  28. {
  29. public:
  30. typedef size_t size_type;
  31. /////////////////////////////////////////////////////////////
  32. // IMPORTANT: The distance must be redefined!!
  33. // See declaration of iterator from stl_iterator_base_types.h:
  34. // template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t,
  35. // typename _Pointer = _Tp*, typename _Reference = _Tp&>
  36. // struct iterator { ...
  37. // ---------- Forward declarations
  38. class iterator :
  39. public std::iterator<std::random_access_iterator_tag, T>
  40. {
  41. // it should be by default because is an inner class, but I put it just to be sure..
  42. friend class CircularArray;
  43. private:
  44. iterator( size_type idx, T* pData, size_type size ) : _idx(idx), _pData(pData), _size(size) {}
  45. public:
  46. //typedef random_access_iterator_tag iterator_category;
  47. iterator() : _idx(0), _pData(NULL) {}
  48. iterator& operator++()
  49. { // preincrement
  50. _idx = (_idx + 1) % _size;
  51. return (*this);
  52. }
  53. iterator operator++(int)
  54. { // postincrement
  55. iterator _Tmp = *this;
  56. _idx = (_idx + 1) % _size;
  57. return (_Tmp);
  58. }
  59. void operator+=(size_type offs)
  60. {
  61. this->_idx = (_idx + offs) % _size;
  62. }
  63. iterator operator+(size_type offs) const
  64. {
  65. size_type newIdx = (_idx + offs) % _size;
  66. iterator _Tmp(newIdx, _pData, _size);
  67. return _Tmp;
  68. }
  69. // return the distance between this iterator and it
  70. size_t operator-(const iterator& it) const
  71. {
  72. if ( this->_idx > it._idx )
  73. return this->_idx - it._idx;
  74. else
  75. return this->_idx + (_size - it._idx);
  76. }
  77. iterator operator-(size_type offs) const
  78. {
  79. size_type newIdx;
  80. if ( offs <= _idx )
  81. newIdx = _idx - offs;
  82. else
  83. newIdx = _size - ((_idx - offs) % _size); // note: should be ok, but to be checked better
  84. iterator _Tmp(newIdx, _pData, _size);
  85. return _Tmp;
  86. }
  87. iterator& operator--()
  88. { // predecrement
  89. if (_idx == 0)
  90. _idx = _size - 1;
  91. else
  92. --_idx;
  93. return (*this);
  94. }
  95. iterator operator--(int)
  96. { // postdecrement
  97. iterator _Tmp = *this;
  98. if (_idx == 0)
  99. _idx = _size - 1;
  100. else
  101. --_idx;
  102. return (_Tmp);
  103. }
  104. T& operator*() const
  105. { // return designated object
  106. return _pData[_idx];
  107. }
  108. T* operator->() const
  109. { // return pointer to class object
  110. return &_pData[_idx];
  111. }
  112. /* T& operator=(const T& right)
  113. { // assign reference right to _val
  114. return ( this->_idx = right._idx );
  115. }*/
  116. bool operator==(const iterator& right) const
  117. { // test for iterator equality
  118. return ( this->_idx == right._idx );
  119. }
  120. bool operator!=(const iterator& right) const
  121. { // test for iterator inequality
  122. return ( this->_idx != right._idx );
  123. }
  124. protected:
  125. size_type _idx;
  126. T* _pData;
  127. size_type _size;
  128. };
  129. /////////////////////////////////////////////////////////////
  130. CircularArray()
  131. : _headIdx(0), _pData(NULL), _size(0)
  132. { }
  133. CircularArray( size_type size )
  134. : _headIdx(0), _pData(NULL)
  135. {
  136. this->resize(size);
  137. }
  138. CircularArray( size_type size, const T& init )
  139. : _headIdx(0), _pData(NULL)
  140. {
  141. this->resize(size, init);
  142. }
  143. ~CircularArray()
  144. {
  145. this->clear();
  146. }
  147. // remember: it is not working (yet!) with negative numbers!
  148. T& operator[](size_type offset)
  149. {
  150. return _pData[ (_headIdx + offset) % _size ];
  151. }
  152. void resize( size_type size )
  153. {
  154. _headIdx = 0;
  155. if ( size == _size )
  156. return;
  157. this->clear();
  158. _pData = new T[size];
  159. _size = size;
  160. }
  161. void resize( size_type size, const T& init )
  162. {
  163. this->resize(size, false);
  164. this->fill(init);
  165. }
  166. void fill( const T& val )
  167. {
  168. for (size_type i=0; i<_size; ++i)
  169. _pData[i] = val;
  170. }
  171. void zero_fill()
  172. {
  173. memset( _pData, 0, _size * sizeof(T) );
  174. }
  175. bool empty() const
  176. {
  177. return ( _pData == NULL );
  178. }
  179. void clear()
  180. {
  181. if (_pData)
  182. delete [] _pData;
  183. _pData = NULL;
  184. _headIdx = 0;
  185. _size = 0;
  186. }
  187. iterator head() const
  188. {
  189. if (_pData == NULL)
  190. std::cerr << "WARNING: iterator in CircularArray points to an empty CircularArray" << std::endl;
  191. return iterator(_headIdx, _pData, _size);
  192. }
  193. void shift_head( int offset )
  194. {
  195. if ( offset < 0)
  196. {
  197. int mod = (-offset) % (int)_size;
  198. mod -= (int)_headIdx;
  199. _headIdx = _size - mod;
  200. }
  201. else
  202. _headIdx = (_headIdx + offset) % _size;
  203. }
  204. size_type size() const
  205. {
  206. return _size;
  207. }
  208. //// to be changed to an input forward iterator
  209. //template <typename TIterator>
  210. //void get_data( TIterator toFillIt, size_type size = 0 )
  211. //{
  212. // if ( size == 0 )
  213. // size = _size;
  214. // iterator it = head();
  215. //
  216. // for (size_type i = 0; i < size; ++i)
  217. // *(toFillIt++) = *(it++);
  218. //}
  219. // IMPORTANT! Destination buffer MUST be the same size!
  220. void copy_buffer( T* pDest )
  221. {
  222. memcpy( pDest, _pData, sizeof(T)*_size );
  223. }
  224. // returns the buffer
  225. T* get_buffer() const
  226. {
  227. return _pData;
  228. }
  229. private:
  230. size_type _headIdx; // index
  231. T* _pData; // array of data
  232. size_type _size; // size of data
  233. };
  234. #endif // __CIRCULAR_ARRAY_H