PageRenderTime 318ms CodeModel.GetById 83ms app.highlight 163ms RepoModel.GetById 69ms app.codeStats 0ms

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