DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
IndexedListWithBlocks.h
1 
17 #pragma once
18 
31 #if defined(IndexedListWithBlocks_RECURSES)
32 #error Recursive header files inclusion detected in IndexedListWithBlocks.h
33 #else // defined(IndexedListWithBlocks_RECURSES)
34 
35 #define IndexedListWithBlocks_RECURSES
36 
37 #if !defined IndexedListWithBlocks_h
38 
39 #define IndexedListWithBlocks_h
40 
42 // Inclusions
43 #include <cstring>
44 #include <iostream>
45 #include "DGtal/base/Common.h"
47 
48 namespace DGtal
49 {
50 
52  // template class IndexedListWithBlocks
93  template <typename TValue, unsigned int N, unsigned int M>
95  {
96  BOOST_STATIC_ASSERT( N >= 1 );
97  BOOST_STATIC_ASSERT( M >= 2 );
98  public:
99  // ----------------------- Public types ------------------------------
100  typedef TValue Value;
101  typedef std::ptrdiff_t DifferenceType;
102  typedef std::size_t SizeType;
103  typedef Value& Reference;
104  typedef Value* Pointer;
105  typedef const Value& ConstReference;
106  typedef const Value* ConstPointer;
107 
108  class Iterator;
110 
111  // ----------------------- Standard types ------------------------------
112  typedef Value value_type;
115  typedef Pointer pointer;
121 
122  struct FirstBlock; //< Forward declaration
123  struct AnyBlock; //< Forward declaration
124 
125  union BlockPointer {
128  };
129 
132  Value lastValue; // used when at the end of the list
133  AnyBlock* nextBlock; // used otherwise
134  };
135 
138  struct FirstBlock {
139  inline
140  FirstBlock() : size( 0 )
141  { data.nextBlock = 0; }
142 
143  inline
144  void insert( unsigned int idx, const Value & v )
145  {
146  if ( size <= N )
147  {
148  ASSERT( idx <= size );
149  // works also in the case we use 'data' to store a N+1-th value.
150  std::copy_backward( values + idx, values + size, values + size + 1 );
151  values[ idx ] = v;
152  }
153  else if ( size == (N+1) )
154  {
155  ASSERT( idx <= size );
156  // This cannot be tested.
157  // ASSERT( data.nextBlock == 0 );
158  AnyBlock* next = new AnyBlock;
159  if ( idx < N )
160  {
161  next->values[ 0 ] = values[ N - 1 ];
162  next->values[ 1 ] = data.lastValue;
163  std::copy_backward( values + idx, values + N - 1, values + N );
164  values[ idx ] = v;
165  }
166  else if ( idx == N )
167  {
168  next->values[ 0 ] = v;
169  next->values[ 1 ] = data.lastValue;
170  }
171  else if ( idx > N )
172  {
173  next->values[ 0 ] = data.lastValue;
174  next->values[ 1 ] = v;
175  }
176  data.nextBlock = next;
177  }
178  else // size > N + 1
179  {
180  if ( idx < N )
181  {
182  Value v1 = values[ N - 1 ];
183  std::copy_backward( values + idx, values + N - 1, values + N );
184  data.nextBlock->insert( 0, size - N, v1 );
185  values[ idx ] = v;
186  }
187  else
188  data.nextBlock->insert( idx - N, size - N, v );
189  }
190  ++size;
191  }
192 
193  inline
194  void erase( unsigned int idx )
195  {
196  // std::cerr << "FirstBlock::erase(" << idx << ")"
197  // << " this=" << this
198  // << " next=" << data.nextBlock
199  // << std::endl;
200  ASSERT( idx < size );
201  if ( size <= ( N + 1 ) )
202  {
203  // works also in the case we use 'data' to store a N+1-th value.
204  std::copy( values + idx + 1, values + size, values + idx );
205  data.nextBlock = 0;
206  }
207  else if ( size == N + 2 )
208  {
209  if ( idx < N )
210  {
211  std::copy( values + idx + 1, values + N, values + idx );
212  values[ N - 1 ] = data.nextBlock->values[ 0 ];
213  Value tmp = data.nextBlock->values[ 1 ];
214  delete data.nextBlock;
215  data.lastValue = tmp;
216  }
217  else if ( idx == N )
218  {
219  Value tmp = data.nextBlock->values[ 1 ];
220  delete data.nextBlock;
221  data.lastValue = tmp;
222  }
223  else // idx == N + 1
224  {
225  Value tmp = data.nextBlock->values[ 0 ];
226  delete data.nextBlock;
227  data.lastValue = tmp;
228  }
229  }
230  else // size > N + 2
231  {
232  if ( idx < N )
233  {
234  std::copy( values + idx + 1, values + N, values + idx );
235  values[ N - 1 ] = data.nextBlock->values[ 0 ];
236  data.nextBlock = data.nextBlock->erase( 0, size - N );
237  }
238  else
239  data.nextBlock = data.nextBlock->erase( idx - N, size - N );
240  }
241  --size;
242  }
243 
244  unsigned int size;
245  Value values[ N ];
247  };
248 
251  struct AnyBlock {
252  inline AnyBlock() : next( 0 ) {}
253 
254  inline
255  void insert( unsigned int idx, unsigned int size, const Value & v )
256  {
257  ASSERT( idx <= size );
258  if ( idx >= M )
259  {
260  if ( next == 0 )
261  {
262  ASSERT( idx == M );
263  next = new AnyBlock;
264  next->values[ 0 ] = v;
265  }
266  else
267  next->insert( idx - M, size - M, v );
268  }
269  else
270  { // idx < M
271  if ( size < ( M - 1) )
272  {
273  std::copy_backward( values + idx, values + size,
274  values + size + 1 );
275  values[ idx ] = v;
276  }
277  else
278  {
279  Value v1 = values[ M - 1 ];
280  std::copy_backward( values + idx, values + M - 1, values + M );
281  values[ idx ] = v;
282  if ( size >= M )
283  {
284  if ( next == 0 )
285  {
286  ASSERT( size == M );
287  next = new AnyBlock;
288  next->values[ 0 ] = v1;
289  }
290  else
291  next->insert( 0, size - M, v1 );
292  }
293  }
294  }
295  }
296 
297  inline
298  AnyBlock* erase( unsigned int idx, unsigned int size )
299  {
300  // std::cerr << "AnyBlock::erase(" << idx << "," << size << ")"
301  // << " this=" << this
302  // << " next=" << next
303  // << std::endl;
304  if ( size == 1 )
305  {
306  ASSERT( idx == 0 );
307  delete this;
308  return 0;
309  }
310  if ( idx < M )
311  {
312  std::copy( values + idx + 1, values + M, values + idx );
313  if ( next != 0 )
314  {
315  ASSERT( size > M );
316  values[ M - 1 ] = next->values[ 0 ];
317  next = next->erase( 0, size - M );
318  }
319  }
320  else
321  next = next->erase( idx - M, size - M );
322  return this;
323  }
324 
325 
326  Value values[ M ];
328  };
329 
335  class Iterator {
336  public:
337  typedef Iterator Self;
338  typedef TValue Value;
339  typedef Value* Pointer;
340  typedef Value& Reference;
341  typedef std::ptrdiff_t DifferenceType; //< only positive offsets allowed.
342 
343  // ----------------------- std types ----------------------------------
344  typedef Value value_type;
345  typedef std::size_t size_type;
347  typedef Pointer pointer;
349  //typedef const Reference const_reference;
350  typedef std::forward_iterator_tag iterator_category;
351 
352 
353  protected:
354  unsigned int myIdx; //< current index in \a myValues of the iterator
355  unsigned int myNbValues; //< number of valid values in array \a myValues
356  Value* myValues; //< array of \a myNbValues values.
357  AnyBlock* myNext; //< pointer to next block or 0 if last block.
358 
359  friend class IndexedListWithBlocks;
360 
361  protected:
365  Iterator( FirstBlock & block, unsigned int idx );
366 
367  public:
371  ~Iterator();
372 
376  Iterator();
377 
382  Iterator( const Iterator & other );
383 
389  Self & operator= ( const Self & other );
390 
395  Reference operator*() const;
396 
401  Pointer operator->() const;
402 
407  Self& operator++();
408 
413  Self operator++( int );
414 
421 
428 
434  bool operator==( const Self & other ) const;
435 
441  bool operator!=( const Self & other ) const;
442 
443 
444  };
445 
446 
453  public:
455  typedef TValue Value;
456  typedef const Value* Pointer;
457  typedef const Value& Reference;
458  typedef std::ptrdiff_t DifferenceType; //< only positive offsets allowed.
459 
460  // ----------------------- std types ----------------------------------
461  typedef Value value_type;
462  typedef std::size_t size_type;
464  typedef Pointer pointer;
466  // typedef Reference const_reference;
467  typedef std::forward_iterator_tag iterator_category;
468 
469 
470  protected:
471  unsigned int myIdx; //< current index in \a myValues of the iterator
472  unsigned int myNbValues; //< number of valid values in array \a myValues
473  const Value* myValues; //< array of \a myNbValues values.
474  const AnyBlock* myNext; //< pointer to next block or 0 if last block.
475 
476  friend class IndexedListWithBlocks;
477 
478  protected:
483  ConstIterator( const FirstBlock & block, unsigned int idx );
484 
485  public:
489  ~ConstIterator();
490 
494  ConstIterator();
495 
500  ConstIterator( const ConstIterator & other );
501 
507  Self & operator= ( const Self & other );
508 
513  Reference operator*() const;
514 
519  Pointer operator->() const;
520 
525  Self& operator++();
526 
531  Self operator++( int );
532 
539 
546 
552  bool operator==( const Self & other ) const;
553 
559  bool operator!=( const Self & other ) const;
560 
561 
562  };
563 
564 
565  // ----------------------- Standard services ------------------------------
566  public:
567 
572 
578 
585 
590 
591  // ----------------------- Container services -----------------------------
592  public:
593 
597  SizeType size() const;
598 
602  bool empty() const;
603 
607  SizeType max_size() const;
608 
612  SizeType capacity() const;
613 
618  void clear();
619 
627  Value & operator[]( unsigned int idx );
628 
636  const Value & operator[]( unsigned int idx ) const;
637 
647  void insert( unsigned int idx, const Value & value );
648 
656  void erase( unsigned int idx );
657 
661  Iterator begin();
662 
666  Iterator end();
667 
671  ConstIterator begin() const;
672 
676  ConstIterator end() const;
677 
678  // ----------------------- Interface --------------------------------------
679  public:
680 
685  void selfDisplay ( std::ostream & out ) const;
686 
691  bool isValid() const;
692 
693  // ------------------------- Protected Datas ------------------------------
694  private:
695  // ------------------------- Private Datas --------------------------------
696  private:
697 
702 
703  // ------------------------- Hidden services ------------------------------
704  protected:
705 
706  // ------------------------- Internals ------------------------------------
707  private:
708 
709  }; // end of class IndexedListWithBlocks
710 
711 
723  template <typename TValue, unsigned int N, unsigned int M>
724  std::ostream&
725  operator<< ( std::ostream & out,
726  const IndexedListWithBlocks<TValue, N, M> & object );
727 
728 } // namespace DGtal
729 
730 
732 // Includes inline functions.
733 #include "DGtal/base/IndexedListWithBlocks.ih"
734 
735 // //
737 
738 #endif // !defined IndexedListWithBlocks_h
739 
740 #undef IndexedListWithBlocks_RECURSES
741 #endif // else defined(IndexedListWithBlocks_RECURSES)