BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Compact_container.h
Go to the documentation of this file.
00001 // Copyright (c) 2003,2004,2007-2009  INRIA Sophia-Antipolis (France).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License as
00006 // published by the Free Software Foundation; version 2.1 of the License.
00007 // See the file LICENSE.LGPL distributed with CGAL.
00008 //
00009 // Licensees holding a valid commercial license may use this file in
00010 // accordance with the commercial license agreement provided with the software.
00011 //
00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014 //
00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/STL_Extension/include/CGAL/Compact_container.h $
00016 // $Id: Compact_container.h 48759 2009-04-10 21:55:24Z spion $
00017 //
00018 // Author(s)     : Sylvain Pion
00019 
00020 #ifndef CGAL_COMPACT_CONTAINER_H
00021 #define CGAL_COMPACT_CONTAINER_H
00022 
00023 #include <CGAL/basic.h>
00024 #include <CGAL/Default.h>
00025 
00026 #include <iterator>
00027 #include <algorithm>
00028 #include <vector>
00029 
00030 #include <CGAL/memory.h>
00031 #include <CGAL/iterator.h>
00032 
00033 #include <boost/mpl/if.hpp>
00034 
00035 // An STL like container with the following properties :
00036 // - to achieve compactness, it requires access to a pointer stored in T,
00037 //   specified by a traits.  This pointer is supposed to be 4 bytes aligned
00038 //   when the object is alive, otherwise, the container uses the 2 least
00039 //   significant bits to store information in the pointer.
00040 // - Ts are allocated in arrays of increasing size, which are linked together
00041 //   by their first and last element.
00042 // - the iterator looks at the famous 2 bits to know if it has to deal with
00043 //   a free/used/boundary element.
00044 
00045 // TODO :
00046 // - Add .reserve() and .resize() (and proper copy of capacity_).
00047 // - Add preconditions in input that real pointers need to have clean bits.
00048 //   Also for the allocated memory alignment, and sizeof().
00049 // - Do a benchmark before/after.
00050 // - Check the end result with Valgrind.
00051 // - The bit squatting mecanism will be reused for the conflict flag, maybe
00052 //   it could be put out of the class.
00053 
00054 // TODO low priority :
00055 // - rebind<> the allocator
00056 // - Exception safety guarantees
00057 // - Thread safety guarantees
00058 // - std requirements on iterators says all defined operations are constant
00059 //   time amortized (it's not true here, maybe it could be with some work...)
00060 // - all this is expected especially when there are not so many free objects
00061 //   compared to the allocated elements.
00062 // - Should block_size be selectable/hintable by .reserve() ?
00063 // - would be nice to have a temporary_free_list (still active elements, but
00064 //   which are going to be freed soon).  Probably it prevents compactness.
00065 // - eventually something to copy this data structure, providing a way to
00066 //   update the pointers (give access to a hash_map, at least a function that
00067 //   converts an old pointer to the new one ?).  Actually it doesn't have to
00068 //   be stuck to a particular DS, because for a list it's useful too...
00069 // - Currently, end() can be invalidated on insert() if a new block is added.
00070 //   It would be nice to fix this.  We could insert the new block at the
00071 //   beginning instead ?  That would drop the property that iterator order
00072 //   is preserved.  Maybe it's not a problem if end() is not preserved, after
00073 //   all nothing is going to dereference it, it's just for comparing with
00074 //   end() that it can be a problem.
00075 //   Another way would be to have end() point to the end of an always
00076 //   empty block (containing no usable element), and insert new blocks just
00077 //   before this one.
00078 //   Instead of having the blocks linked between them, the start/end pointers
00079 //   could point back to the container, so that we can do more interesting
00080 //   things (e.g. freeing empty blocks automatically) ?
00081 // - Submission to Boost.
00082 
00083 CGAL_BEGIN_NAMESPACE
00084 
00085 // The following base class can be used to easily add a squattable pointer
00086 // to a class (maybe you loose a bit of compactness though).
00087 // TODO : Shouldn't adding these bits be done automatically and transparently,
00088 //        based on the traits class info ?
00089 class Compact_container_base
00090 {
00091   void * p;
00092 public:
00093   Compact_container_base()
00094   : p(NULL) {}
00095   void *   for_compact_container() const { return p; }
00096   void * & for_compact_container()       { return p; }
00097 };
00098 
00099 // The traits class describes the way to access the pointer.
00100 // It can be specialized.
00101 template < class T >
00102 struct Compact_container_traits {
00103   static void *   pointer(const T &t) { return t.for_compact_container(); }
00104   static void * & pointer(T &t)       { return t.for_compact_container(); }
00105 };
00106 
00107 namespace CGALi {
00108   template < class DSC, bool Const >
00109   class CC_iterator;
00110 }
00111 
00112 template < class T, class Allocator_ = Default >
00113 class Compact_container
00114 {
00115   typedef Allocator_                                Al;
00116   typedef typename Default::Get< Al, CGAL_ALLOCATOR(T) >::type Allocator;
00117   typedef Compact_container <T, Al>                 Self;
00118   typedef Compact_container_traits <T>              Traits;
00119 public:
00120   typedef T                                         value_type;
00121   typedef Allocator                                 allocator_type;
00122   typedef typename Allocator::reference             reference;
00123   typedef typename Allocator::const_reference       const_reference;
00124   typedef typename Allocator::pointer               pointer;
00125   typedef typename Allocator::const_pointer         const_pointer;
00126   typedef typename Allocator::size_type             size_type;
00127   typedef typename Allocator::difference_type       difference_type;
00128   typedef CGALi::CC_iterator<Self, false>           iterator;
00129   typedef CGALi::CC_iterator<Self, true>            const_iterator;
00130   typedef std::reverse_iterator<iterator>           reverse_iterator;
00131   typedef std::reverse_iterator<const_iterator>     const_reverse_iterator;
00132 
00133   friend class CGALi::CC_iterator<Self, false>;
00134   friend class CGALi::CC_iterator<Self, true>;
00135 
00136   explicit Compact_container(const Allocator &a = Allocator())
00137   : alloc(a)
00138   {
00139     init();
00140   }
00141 
00142   template < class InputIterator >
00143   Compact_container(InputIterator first, InputIterator last,
00144                     const Allocator & a = Allocator())
00145   : alloc(a)
00146   {
00147     init();
00148     std::copy(first, last, CGAL::inserter(*this));
00149   }
00150 
00151   // The copy constructor and assignment operator preserve the iterator order
00152   Compact_container(const Compact_container &c)
00153   : alloc(c.get_allocator())
00154   {
00155     init();
00156     block_size = c.block_size;
00157     std::copy(c.begin(), c.end(), CGAL::inserter(*this));
00158   }
00159 
00160   Compact_container & operator=(const Compact_container &c)
00161   {
00162     if (&c != this) {
00163       Self tmp(c);
00164       swap(tmp);
00165     }
00166     return *this;
00167   }
00168 
00169   ~Compact_container()
00170   {
00171     clear();
00172   }
00173 
00174   void swap(Self &c)
00175   {
00176     std::swap(alloc, c.alloc);
00177     std::swap(capacity_, c.capacity_);
00178     std::swap(size_, c.size_);
00179     std::swap(block_size, c.block_size);
00180     std::swap(first_item, c.first_item);
00181     std::swap(last_item, c.last_item);
00182     std::swap(free_list, c.free_list);
00183     all_items.swap(c.all_items);
00184   }
00185 
00186   iterator begin() { return iterator(first_item, 0, 0); }
00187   iterator end()   { return iterator(last_item, 0); }
00188 
00189   const_iterator begin() const { return const_iterator(first_item, 0, 0); }
00190   const_iterator end()   const { return const_iterator(last_item, 0); }
00191 
00192   reverse_iterator rbegin() { return reverse_iterator(end()); }
00193   reverse_iterator rend()   { return reverse_iterator(begin()); }
00194 
00195   const_reverse_iterator
00196   rbegin() const { return const_reverse_iterator(end()); }
00197   const_reverse_iterator
00198   rend()   const { return const_reverse_iterator(begin()); }
00199 
00200   // Boost.Intrusive interface
00201   iterator iterator_to(reference value) const {
00202     return iterator(&value, 0);
00203   }
00204   const_iterator iterator_to(const_reference value) const {
00205     return const_iterator(&value, 0);
00206   }
00207   static iterator s_iterator_to(reference value) {
00208     return iterator(&value, 0);
00209   }
00210   static const_iterator s_iterator_to(const_reference value) {
00211     return const_iterator(&value, 0);
00212   }
00213 
00214   // Special insert methods that construct the objects in place
00215   // (just forward the arguments to the constructor, to optimize a copy).
00216 #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
00217   template < typename... Args >
00218   iterator
00219   emplace(const Args&... args)
00220   {
00221     if (free_list == NULL)
00222       allocate_new_block();
00223 
00224     pointer ret = free_list;
00225     free_list = clean_pointee(ret);
00226     new (ret) value_type(args...);
00227     CGAL_assertion(type(ret) == USED);
00228     ++size_;
00229     return iterator(ret, 0);
00230   }
00231 #else
00232   // inserts a default constructed item.
00233   iterator emplace()
00234   {
00235     if (free_list == NULL)
00236       allocate_new_block();
00237 
00238     pointer ret = free_list;
00239     free_list = clean_pointee(ret);
00240     new (ret) value_type();
00241     CGAL_assertion(type(ret) == USED);
00242     ++size_;
00243     return iterator(ret, 0);
00244   }
00245 
00246   template < typename T1 >
00247   iterator
00248   emplace(const T1 &t1)
00249   {
00250     if (free_list == NULL)
00251       allocate_new_block();
00252 
00253     pointer ret = free_list;
00254     free_list = clean_pointee(ret);
00255     new (ret) value_type(t1);
00256     CGAL_assertion(type(ret) == USED);
00257     ++size_;
00258     return iterator(ret, 0);
00259   }
00260 
00261   template < typename T1, typename T2 >
00262   iterator
00263   emplace(const T1 &t1, const T2 &t2)
00264   {
00265     if (free_list == NULL)
00266       allocate_new_block();
00267 
00268     pointer ret = free_list;
00269     free_list = clean_pointee(ret);
00270     new (ret) value_type(t1, t2);
00271     CGAL_assertion(type(ret) == USED);
00272     ++size_;
00273     return iterator(ret, 0);
00274   }
00275 
00276   template < typename T1, typename T2, typename T3 >
00277   iterator
00278   emplace(const T1 &t1, const T2 &t2, const T3 &t3)
00279   {
00280     if (free_list == NULL)
00281       allocate_new_block();
00282 
00283     pointer ret = free_list;
00284     free_list = clean_pointee(ret);
00285     new (ret) value_type(t1, t2, t3);
00286     CGAL_assertion(type(ret) == USED);
00287     ++size_;
00288     return iterator(ret, 0);
00289   }
00290 
00291   template < typename T1, typename T2, typename T3, typename T4 >
00292   iterator
00293   emplace(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4)
00294   {
00295     if (free_list == NULL)
00296       allocate_new_block();
00297 
00298     pointer ret = free_list;
00299     free_list = clean_pointee(ret);
00300     new (ret) value_type(t1, t2, t3, t4);
00301     CGAL_assertion(type(ret) == USED);
00302     ++size_;
00303     return iterator(ret, 0);
00304   }
00305 
00306   template < typename T1, typename T2, typename T3, typename T4, typename T5 >
00307   iterator
00308   emplace(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4,
00309           const T5 &t5)
00310   {
00311     if (free_list == NULL)
00312       allocate_new_block();
00313 
00314     pointer ret = free_list;
00315     free_list = clean_pointee(ret);
00316     new (ret) value_type(t1, t2, t3, t4, t5);
00317     CGAL_assertion(type(ret) == USED);
00318     ++size_;
00319     return iterator(ret, 0);
00320   }
00321 
00322   template < typename T1, typename T2, typename T3, typename T4,
00323              typename T5, typename T6 >
00324   iterator
00325   emplace(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4,
00326           const T5 &t5, const T6 &t6)
00327   {
00328     if (free_list == NULL)
00329       allocate_new_block();
00330 
00331     pointer ret = free_list;
00332     free_list = clean_pointee(ret);
00333     new (ret) value_type(t1, t2, t3, t4, t5, t6);
00334     CGAL_assertion(type(ret) == USED);
00335     ++size_;
00336     return iterator(ret, 0);
00337   }
00338 
00339   template < typename T1, typename T2, typename T3, typename T4,
00340              typename T5, typename T6, typename T7 >
00341   iterator
00342   emplace(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4,
00343           const T5 &t5, const T6 &t6, const T7 &t7)
00344   {
00345     if (free_list == NULL)
00346       allocate_new_block();
00347 
00348     pointer ret = free_list;
00349     free_list = clean_pointee(ret);
00350     new (ret) value_type(t1, t2, t3, t4, t5, t6, t7);
00351     CGAL_assertion(type(ret) == USED);
00352     ++size_;
00353     return iterator(ret, 0);
00354   }
00355 
00356   template < typename T1, typename T2, typename T3, typename T4,
00357              typename T5, typename T6, typename T7, typename T8 >
00358   iterator
00359   emplace(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4,
00360           const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8)
00361   {
00362     if (free_list == NULL)
00363       allocate_new_block();
00364 
00365     pointer ret = free_list;
00366     free_list = clean_pointee(ret);
00367     new (ret) value_type(t1, t2, t3, t4, t5, t6, t7, t8);
00368     CGAL_assertion(type(ret) == USED);
00369     ++size_;
00370     return iterator(ret, 0);
00371   }
00372 #endif // CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
00373 
00374   iterator insert(const T &t)
00375   {
00376     if (free_list == NULL)
00377       allocate_new_block();
00378 
00379     pointer ret = free_list;
00380     free_list = clean_pointee(ret);
00381     alloc.construct(ret, t);
00382     CGAL_assertion(type(ret) == USED);
00383     ++size_;
00384     return iterator(ret, 0);
00385   }
00386 
00387   template < class InputIterator >
00388   void insert(InputIterator first, InputIterator last)
00389   {
00390     for (; first != last; ++first)
00391       insert(*first);
00392   }
00393 
00394   template < class InputIterator >
00395   void assign(InputIterator first, InputIterator last)
00396   {
00397     clear(); // erase(begin(), end()); // ?
00398     insert(first, last);
00399   }
00400 
00401   void erase(iterator x)
00402   {
00403     CGAL_precondition(type(&*x) == USED);
00404     alloc.destroy(&*x);
00405     put_on_free_list(&*x);
00406     --size_;
00407   }
00408 
00409   void erase(iterator first, iterator last) {
00410     for (; first != last; ++first)
00411       erase(first);
00412   }
00413 
00414   void clear();
00415 
00416   // Merge the content of d into *this.  d gets cleared.
00417   // The complexity is O(size(free list = capacity-size)).
00418   void merge(Self &d);
00419 
00420   size_type size() const
00421   {
00422     CGAL_expensive_assertion(size_ ==
00423                              (size_type) std::distance(begin(), end()));
00424     return size_;
00425   }
00426 
00427   size_type max_size() const
00428   {
00429     return alloc.max_size();
00430   }
00431 
00432   size_type capacity() const
00433   {
00434     return capacity_;
00435   }
00436 
00437   void reserve(size_type n); // TODO
00438 
00439   // void resize(size_type sz, T c = T()); // TODO  makes sense ???
00440 
00441   bool empty() const
00442   {
00443     return size_ == 0;
00444   }
00445 
00446   allocator_type get_allocator() const
00447   {
00448     return alloc;
00449   }
00450 
00451 private:
00452 
00453   void allocate_new_block();
00454 
00455   void put_on_free_list(pointer x)
00456   {
00457     set_type(x, free_list, FREE);
00458     free_list = x;
00459   }
00460 
00461   // Definition of the bit squatting :
00462   // =================================
00463   // ptr is composed of a pointer part and the last 2 bits.
00464   // Here is the meaning of each of the 8 cases.
00465   //
00466   //                          value of the last 2 bits as "Type"
00467   // pointer part     0              1                2              3
00468   //         NULL     user elt       unused           free_list end  start/end
00469   //      != NULL     user elt       block boundary   free elt       unused
00470   //
00471   // meaning of ptr : user stuff     next/prev block  free_list      unused
00472 
00473   enum Type { USED = 0, BLOCK_BOUNDARY = 1, FREE = 2, START_END = 3 };
00474 
00475   // The bit squatting is implemented by casting pointers to (char *), then
00476   // subtracting to NULL, doing bit manipulations on the resulting integer,
00477   // and converting back.
00478 
00479   static char * clean_pointer(char * p)
00480   {
00481     return ((p - (char *) NULL) & ~ (std::ptrdiff_t) START_END) + (char *) NULL;
00482   }
00483 
00484   // Returns the pointee, cleaned up from the squatted bits.
00485   static pointer clean_pointee(const_pointer ptr)
00486   {
00487     return (pointer) clean_pointer((char *) Traits::pointer(*ptr));
00488   }
00489 
00490   // Get the type of the pointee.
00491   static Type type(const_pointer ptr)
00492   {
00493     char * p = (char *) Traits::pointer(*ptr);
00494     return (Type) (p - clean_pointer(p));
00495   }
00496 
00497   // Sets the pointer part and the type of the pointee.
00498   static void set_type(pointer ptr, void * p, Type t)
00499   {
00500     CGAL_precondition(0 <= t && t < 4);
00501     Traits::pointer(*ptr) = (void *) ((clean_pointer((char *) p)) + (int) t);
00502   }
00503 
00504   // We store a vector of pointers to all allocated blocks and their sizes.
00505   // Knowing all pointers, we don't have to walk to the end of a block to reach
00506   // the pointer to the next block.
00507   // Knowing the sizes allows to deallocate() without having to compute the size
00508   // by walking through the block till its end.
00509   // This opens up the possibility for the compiler to optimize the clear()
00510   // function considerably when has_trivial_destructor<T>.
00511   typedef std::vector<std::pair<pointer, size_type> >  All_items;
00512 
00513   void init()
00514   {
00515     block_size = 14;
00516     capacity_  = 0;
00517     size_      = 0;
00518     free_list  = NULL;
00519     first_item = NULL;
00520     last_item  = NULL;
00521     all_items  = All_items();
00522   }
00523 
00524   allocator_type   alloc;
00525   size_type        capacity_;
00526   size_type        size_;
00527   size_type        block_size;
00528   pointer          free_list;
00529   pointer          first_item;
00530   pointer          last_item;
00531   All_items        all_items;
00532 };
00533 
00534 template < class T, class Allocator >
00535 void Compact_container<T, Allocator>::merge(Self &d)
00536 {
00537   CGAL_precondition(&d != this);
00538 
00539   // Allocators must be "compatible" :
00540   CGAL_precondition(get_allocator() == d.get_allocator());
00541 
00542   // Concatenate the free_lists.
00543   if (free_list == NULL) {
00544     free_list = d.free_list;
00545   } else if (d.free_list != NULL) {
00546     pointer p = free_list;
00547     while (clean_pointee(p) != NULL)
00548       p = clean_pointee(p);
00549     set_type(p, d.free_list, FREE);
00550   }
00551   // Concatenate the blocks.
00552   if (last_item == NULL) { // empty...
00553     first_item = d.first_item;
00554     last_item  = d.last_item;
00555   } else if (d.last_item != NULL) {
00556     set_type(last_item, d.first_item, BLOCK_BOUNDARY);
00557     set_type(d.first_item, last_item, BLOCK_BOUNDARY);
00558     last_item = d.last_item;
00559   }
00560   // Add the sizes.
00561   size_ += d.size_;
00562   // Add the capacities.
00563   capacity_ += d.capacity_;
00564   // It seems reasonnable to take the max of the block sizes.
00565   block_size = (std::max)(block_size, d.block_size);
00566   // Clear d.
00567   d.init();
00568 }
00569 
00570 template < class T, class Allocator >
00571 void Compact_container<T, Allocator>::clear()
00572 {
00573   for (typename All_items::iterator it = all_items.begin(), end = all_items.end();
00574        it != end; ++it) {
00575     pointer p = it->first;
00576     size_type s = it->second;
00577     for (pointer pp = p + 1; pp != p + s - 1; ++pp) {
00578       if (type(pp) == USED)
00579         alloc.destroy(pp);
00580     }
00581     alloc.deallocate(p, s);
00582   }
00583   init();
00584 }
00585 
00586 template < class T, class Allocator >
00587 void Compact_container<T, Allocator>::allocate_new_block()
00588 {
00589   pointer new_block = alloc.allocate(block_size + 2);
00590   all_items.push_back(std::make_pair(new_block, block_size + 2));
00591   capacity_ += block_size;
00592   // We don't touch the first and the last one.
00593   // We mark them free in reverse order, so that the insertion order
00594   // will correspond to the iterator order...
00595   for (size_type i = block_size; i >= 1; --i)
00596     put_on_free_list(new_block + i);
00597   // We insert this new block at the end.
00598   if (last_item == NULL) // First time
00599   {
00600       first_item = new_block;
00601       last_item  = new_block + block_size + 1;
00602       set_type(first_item, NULL, START_END);
00603   }
00604   else
00605   {
00606       set_type(last_item, new_block, BLOCK_BOUNDARY);
00607       set_type(new_block, last_item, BLOCK_BOUNDARY);
00608       last_item = new_block + block_size + 1;
00609   }
00610   set_type(last_item, NULL, START_END);
00611   // Increase the block_size for the next time.
00612   block_size += 16;
00613 }
00614 
00615 template < class T, class Allocator >
00616 inline
00617 bool operator==(const Compact_container<T, Allocator> &lhs,
00618                 const Compact_container<T, Allocator> &rhs)
00619 {
00620   return lhs.size() == rhs.size() &&
00621     std::equal(lhs.begin(), lhs.end(), rhs.begin());
00622 }
00623 
00624 template < class T, class Allocator >
00625 inline
00626 bool operator!=(const Compact_container<T, Allocator> &lhs,
00627                 const Compact_container<T, Allocator> &rhs)
00628 {
00629   return ! (lhs == rhs);
00630 }
00631 
00632 template < class T, class Allocator >
00633 inline
00634 bool operator< (const Compact_container<T, Allocator> &lhs,
00635                 const Compact_container<T, Allocator> &rhs)
00636 {
00637   return std::lexicographical_compare(lhs.begin(), lhs.end(),
00638                                       rhs.begin(), rhs.end());
00639 }
00640 
00641 template < class T, class Allocator >
00642 inline
00643 bool operator> (const Compact_container<T, Allocator> &lhs,
00644                 const Compact_container<T, Allocator> &rhs)
00645 {
00646   return rhs < lhs;
00647 }
00648 
00649 template < class T, class Allocator >
00650 inline
00651 bool operator<=(const Compact_container<T, Allocator> &lhs,
00652                 const Compact_container<T, Allocator> &rhs)
00653 {
00654   return ! (lhs > rhs);
00655 }
00656 
00657 template < class T, class Allocator >
00658 inline
00659 bool operator>=(const Compact_container<T, Allocator> &lhs,
00660                 const Compact_container<T, Allocator> &rhs)
00661 {
00662   return ! (lhs < rhs);
00663 }
00664 
00665 namespace CGALi {
00666 
00667   template < class DSC, bool Const >
00668   class CC_iterator
00669   {
00670     typedef typename DSC::iterator                    iterator;
00671     typedef CC_iterator<DSC, Const>                   Self;
00672   public:
00673     typedef typename DSC::value_type                  value_type;
00674     typedef typename DSC::size_type                   size_type;
00675     typedef typename DSC::difference_type             difference_type;
00676     typedef typename boost::mpl::if_c< Const, const value_type*,
00677                                        value_type*>::type pointer;
00678     typedef typename boost::mpl::if_c< Const, const value_type&,
00679                                        value_type&>::type reference;
00680     typedef std::bidirectional_iterator_tag           iterator_category;
00681 
00682     // the initialization with NULL is required by our Handle concept.
00683     CC_iterator()
00684     {
00685       m_ptr.p = NULL;
00686     }
00687 
00688     // Either a harmless copy-ctor,
00689     // or a conversion from iterator to const_iterator.
00690     CC_iterator (const iterator &it)
00691     {
00692       m_ptr.p = &(*it);
00693     }
00694 
00695     // Same for assignment operator (otherwise MipsPro warns)
00696     CC_iterator & operator= (const iterator &it)
00697     {
00698       m_ptr.p = &(*it);
00699       return *this;
00700     }
00701 
00702     // Construction from NULL
00703     CC_iterator (Nullptr_t CGAL_assertion_code(n))
00704     {
00705       CGAL_assertion (n == NULL);
00706       m_ptr.p = NULL;
00707     }
00708 
00709   private:
00710 
00711     union {
00712       pointer      p;
00713       void        *vp;
00714     } m_ptr;
00715 
00716     // Only Compact_container should access these constructors.
00717     friend class Compact_container<value_type, typename DSC::Al>;
00718 
00719     // For begin()
00720     CC_iterator(pointer ptr, int, int)
00721     {
00722       m_ptr.p = ptr;
00723       if (m_ptr.p == NULL) // empty container.
00724         return;
00725 
00726       ++(m_ptr.p); // if not empty, p = start
00727       if (DSC::type(m_ptr.p) == DSC::FREE)
00728         increment();
00729     }
00730 
00731     // Construction from raw pointer and for end().
00732     CC_iterator(pointer ptr, int)
00733     {
00734       m_ptr.p = ptr;
00735     }
00736 
00737     // NB : in case empty container, begin == end == NULL.
00738     void increment()
00739     {
00740       // It's either pointing to end(), or valid.
00741       CGAL_assertion_msg(m_ptr.p != NULL,
00742                          "Doing ++ on empty container iterator ?");
00743       CGAL_assertion_msg(DSC::type(m_ptr.p) != DSC::START_END,
00744                          "Doing ++ on end() ?");
00745 
00746       // If it's not end(), then it's valid, we can do ++.
00747       do {
00748         ++(m_ptr.p);
00749         if (DSC::type(m_ptr.p) == DSC::USED ||
00750             DSC::type(m_ptr.p) == DSC::START_END)
00751           return;
00752 
00753         if (DSC::type(m_ptr.p) == DSC::BLOCK_BOUNDARY)
00754           m_ptr.p = DSC::clean_pointee(m_ptr.p);
00755       } while (true);
00756     }
00757 
00758     void decrement()
00759     {
00760       // It's either pointing to end(), or valid.
00761       CGAL_assertion_msg(m_ptr.p != NULL,
00762                          "Doing -- on empty container iterator ?");
00763       CGAL_assertion_msg(DSC::type(m_ptr.p - 1) != DSC::START_END,
00764                          "Doing -- on begin() ?");
00765 
00766       // If it's not begin(), then it's valid, we can do --.
00767       do {
00768         --m_ptr.p;
00769         if (DSC::type(m_ptr.p) == DSC::USED ||
00770             DSC::type(m_ptr.p) == DSC::START_END)
00771           return;
00772 
00773         if (DSC::type(m_ptr.p) == DSC::BLOCK_BOUNDARY)
00774           m_ptr.p = DSC::clean_pointee(m_ptr.p);
00775       } while (true);
00776     }
00777 
00778   public:
00779 
00780     Self & operator++() { increment(); return *this; }
00781     Self & operator--() { decrement(); return *this; }
00782 
00783     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
00784     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
00785 
00786     reference operator*() const { return *(m_ptr.p); }
00787 
00788     pointer   operator->() const { return (m_ptr.p); }
00789 
00790     // For std::less...
00791     bool operator<(const CC_iterator& other) const
00792     {
00793       return (m_ptr.p < other.m_ptr.p);
00794     }
00795 
00796     // Can itself be used for bit-squatting.
00797     void *   for_compact_container() const { return (m_ptr.vp); }
00798     void * & for_compact_container()       { return (m_ptr.vp); }
00799   };
00800 
00801   template < class DSC, bool Const1, bool Const2 >
00802   inline
00803   bool operator==(const CC_iterator<DSC, Const1> &rhs,
00804                   const CC_iterator<DSC, Const2> &lhs)
00805   {
00806     return &*rhs == &*lhs;
00807   }
00808 
00809   template < class DSC, bool Const1, bool Const2 >
00810   inline
00811   bool operator!=(const CC_iterator<DSC, Const1> &rhs,
00812                   const CC_iterator<DSC, Const2> &lhs)
00813   {
00814     return &*rhs != &*lhs;
00815   }
00816 
00817   // Comparisons with NULL are part of CGAL's Handle concept...
00818   template < class DSC, bool Const >
00819   inline
00820   bool operator==(const CC_iterator<DSC, Const> &rhs,
00821                   Nullptr_t CGAL_assertion_code(n))
00822   {
00823     CGAL_assertion( n == NULL);
00824     return &*rhs == NULL;
00825   }
00826 
00827   template < class DSC, bool Const >
00828   inline
00829   bool operator!=(const CC_iterator<DSC, Const> &rhs,
00830                   Nullptr_t CGAL_assertion_code(n))
00831   {
00832     CGAL_assertion( n == NULL);
00833     return &*rhs != NULL;
00834   }
00835 
00836 } // namespace CGALi
00837 
00838 CGAL_END_NAMESPACE
00839 
00840 #endif // CGAL_COMPACT_CONTAINER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines