cdmap_ordered.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file cdmap_ordered.h
00004  * 
00005  * Author: Sergey Berezin
00006  * 
00007  * Created: Thu May 15 15:55:09 2003
00008  *
00009  * <hr>
00010  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00011  * Junior University and by New York University. 
00012  *
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.  In particular:
00017  *
00018  * - The above copyright notice and this permission notice must appear
00019  * in all copies of the software and related documentation.
00020  *
00021  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00022  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00023  * 
00024  * <hr>
00025  * 
00026  */
00027 /*****************************************************************************/
00028 
00029 #ifndef _cvcl__include__cdmap_ordered_h_
00030 #define _cvcl__include__cdmap_ordered_h_
00031 
00032 #include <map>
00033 #include <iterator>
00034 #include "context.h"
00035 
00036 namespace CVCL {
00037 
00038 ///////////////////////////////////////////////////////////////////////////////
00039 //                                                                           //
00040 // Class: CDMapOrdered (Context Dependent Map)                               //
00041 // Author: Sergey Berezin                                                    //
00042 // Created: Thu May 15 15:55:09 2003                                         //
00043 // Description: Generic templated class for a map which must be saved        //
00044 //              and restored as contexts are pushed and popped.  Requires    //
00045 //              that operator= be defined for the data class, and            //
00046 //              operator< for the key class.                                 //
00047 //                                                                           //
00048 ///////////////////////////////////////////////////////////////////////////////
00049 
00050 // Auxiliary class: almost the same as CDO (see cdo.h), but on
00051 // setNull() call it erases itself from the map.
00052 
00053 template <class Key, class Data> class CDMapOrdered;
00054 
00055 template <class Key, class Data>
00056 class CDOmapOrdered :public ContextObj {
00057   Key d_key;
00058   Data d_data;
00059   bool d_inMap; // whether the data must be in the map
00060   CDMapOrdered<Key, Data>* d_cdmap;
00061 
00062   // Doubly-linked list for keeping track of elements in order of insertion
00063   CDOmapOrdered<Key,Data>* d_prev;
00064   CDOmapOrdered<Key,Data>* d_next;
00065 
00066   virtual ContextObj* makeCopy(void) { return new CDOmapOrdered<Key,Data>(*this); }
00067 
00068   virtual void restoreData(ContextObj* data) {
00069     CDOmapOrdered<Key,Data>* p((CDOmapOrdered<Key,Data>*)data);
00070     if(p->d_inMap) { d_data = p->d_data; d_inMap = true; }
00071     else setNull();
00072   }
00073   virtual void setNull(void) {
00074     // Erase itself from the map and put itself into trash.  We cannot
00075     // "delete this" here, because it will break context operations in
00076     // a non-trivial way.
00077     if(d_cdmap->d_map.count(d_key) > 0) {
00078       d_cdmap->d_map.erase(d_key);
00079       d_cdmap->d_trash.push_back(this);
00080     }
00081     d_prev->d_next = d_next;
00082     d_next->d_prev = d_prev;
00083     if (d_cdmap->d_first == this) {
00084       d_cdmap->d_first = d_next;
00085       if (d_next == this) {
00086         d_cdmap->d_first = NULL;
00087       }
00088     }
00089   }
00090 
00091 public:
00092   CDOmapOrdered(Context* context, CDMapOrdered<Key, Data>* cdmap,
00093          const Key& key, const Data& data, int scope = -1)
00094     : ContextObj(context, true /* use bottom scope */),
00095     d_key(key), d_inMap(false), d_cdmap(cdmap) {
00096     set(data, scope);
00097     IF_DEBUG(setName("CDOmapOrdered"));
00098     CDOmapOrdered<Key, Data>*& first = d_cdmap->d_first;
00099     if (first == NULL) {
00100       first = d_next = d_prev = this;
00101     }
00102     else {
00103       d_prev = first->d_prev;
00104       d_next = first;
00105       d_prev->d_next = first->d_prev = this;
00106     }
00107   }
00108   ~CDOmapOrdered() {}
00109   void set(const Data& data, int scope=-1) {
00110     makeCurrent(scope); d_data = data; d_inMap = true;
00111   }
00112   const Key& getKey() const { return d_key; }
00113   const Data& get() const { return d_data; }
00114   operator Data() { return get(); }
00115   CDOmapOrdered<Key,Data>& operator=(const Data& data) { set(data); return *this; }
00116   CDOmapOrdered<Key,Data>* next() const {
00117     if (d_next == d_cdmap->d_first) return NULL;
00118     else return d_next;
00119   }
00120 }; // end of class CDOmapOrdered
00121 
00122 // Dummy subclass of ContextObj to serve as our data class
00123 class CDMapOrderedData : public ContextObj {
00124   ContextObj* makeCopy(void) { return new CDMapOrderedData(*this); }
00125   void restoreData(ContextObj* data) { }
00126   void setNull(void) { }
00127  public:
00128   CDMapOrderedData(Context* context): ContextObj(context) { }
00129   CDMapOrderedData(const ContextObj& co): ContextObj(co) { }
00130 };
00131 
00132 // The actual class CDMapOrdered
00133 template <class Key, class Data>
00134 class CDMapOrdered: public ContextObj {
00135   friend class CDOmapOrdered<Key, Data>;
00136  private:
00137   std::map<Key,CDOmapOrdered<Key,Data>*> d_map;
00138   // The vector of CDOmapOrdered objects to be destroyed
00139   std::vector<CDOmapOrdered<Key,Data>*> d_trash;
00140   CDOmapOrdered<Key,Data>* d_first;
00141   Context* d_context;
00142   
00143   // Nothing to save; the elements take care of themselves
00144   virtual ContextObj* makeCopy(void) { return new CDMapOrderedData(*this); }
00145   // Similarly, nothing to restore
00146   virtual void restoreData(ContextObj* data) { }
00147   
00148   // Destroy stale CDOmapOrdered objects from trash
00149   void emptyTrash() {
00150     for(typename std::vector<CDOmapOrdered<Key,Data>*>::iterator
00151           i=d_trash.begin(), iend=d_trash.end(); i!=iend; ++i)
00152       delete *i;
00153     d_trash.clear();
00154   }
00155 
00156   virtual void setNull(void) {
00157     // Delete all the elements and clear the map
00158     for(typename std::map<Key,CDOmapOrdered<Key,Data>*>::iterator
00159           i=d_map.begin(), iend=d_map.end();
00160         i!=iend; ++i) delete (*i).second;
00161     d_map.clear();
00162     emptyTrash();
00163   }
00164 public:
00165   CDMapOrdered(Context* context, int scope = -1)
00166     : ContextObj(context), d_first(NULL), d_context(context) {
00167     IF_DEBUG(setName("CDMapOrdered"));     
00168   }
00169   ~CDMapOrdered() { setNull(); }
00170   // The usual operators of map
00171   size_t size() const { return d_map.size(); }
00172   size_t count(const Key& k) const { return d_map.count(k); }
00173 
00174   // If a key is not present, a new object is created and inserted
00175   CDOmapOrdered<Key,Data>& operator[](const Key& k) {
00176     emptyTrash();
00177     typename std::map<Key,CDOmapOrdered<Key,Data>*>::iterator i(d_map.find(k));
00178     CDOmapOrdered<Key,Data>* obj;
00179     if(i == d_map.end()) { // Create new object
00180       obj = new CDOmapOrdered<Key,Data>(d_context, this, k, Data());
00181       d_map[k] = obj;
00182     } else {
00183       obj = (*i).second;
00184     }
00185     return *obj;
00186   }
00187 
00188   void insert(const Key& k, const Data& d, int scope = -1) {
00189     emptyTrash();
00190     typename std::map<Key,CDOmapOrdered<Key,Data>*>::iterator i(d_map.find(k));
00191     if(i == d_map.end()) { // Create new object
00192       CDOmapOrdered<Key,Data>*
00193         obj(new CDOmapOrdered<Key,Data>(d_context, this, k, d, scope));
00194       d_map[k] = obj;
00195     } else {
00196       (*i).second->set(d, scope);
00197     }
00198   }
00199   // FIXME: no erase(), too much hassle to implement efficiently...
00200 
00201   // Iterator for CDMapOrdered: points to pair<const Key, CDOMap<Key,Data>&>;
00202   // in most cases, this will be functionally similar to pair<const Key,Data>.
00203   class iterator : public std::iterator<std::input_iterator_tag,std::pair<const Key, Data>,std::ptrdiff_t> {
00204     private:
00205       // Private members
00206       typename std::map<Key,CDOmapOrdered<Key,Data>*>::const_iterator d_it;
00207     public:
00208       // Constructor from std::map
00209       iterator(const typename std::map<Key,CDOmapOrdered<Key,Data>*>::const_iterator& i)
00210       : d_it(i) { }
00211       // Copy constructor
00212       iterator(const iterator& i): d_it(i.d_it) { }
00213       // Default constructor
00214       iterator() { }
00215       // (Dis)equality
00216       bool operator==(const iterator& i) const {
00217         return d_it == i.d_it;
00218       }
00219       bool operator!=(const iterator& i) const {
00220         return d_it != i.d_it;
00221       }
00222       // Dereference operators.
00223       std::pair<const Key, Data> operator*() const {
00224         const std::pair<const Key, CDOmapOrdered<Key,Data>*>& p(*d_it);
00225         return std::pair<const Key, Data>(p.first, *p.second);
00226       }
00227       // Who needs an operator->() for maps anyway?...
00228       // It'd be nice, but not possible by design.
00229       //std::pair<const Key,Data>* operator->() const {
00230       //  return &(operator*());
00231       //}
00232       
00233 
00234       // Prefix and postfix increment
00235       iterator& operator++() { ++d_it; return *this; }
00236       // Postfix increment: requires a Proxy object to hold the
00237       // intermediate value for dereferencing
00238       class Proxy {
00239         const std::pair<const Key, Data>* d_pair;
00240       public:
00241         Proxy(const std::pair<const Key, Data>& p): d_pair(&p) { }
00242         std::pair<const Key, Data>& operator*() { return *d_pair; }
00243       };
00244       // Actual postfix increment: returns Proxy with the old value.
00245       // Now, an expression like *i++ will return the current *i, and
00246       // then advance the iterator.  However, don't try to use Proxy for
00247       // anything else.
00248       Proxy operator++(int) {
00249         Proxy e(*(*this));
00250         ++(*this);
00251         return e;
00252       }
00253   };
00254 
00255   iterator begin() const { return iterator(d_map.begin()); }
00256   iterator end() const { return iterator(d_map.end()); }
00257 
00258   class orderedIterator {
00259       const CDOmapOrdered<Key,Data>* d_it;
00260     public:
00261       orderedIterator(const CDOmapOrdered<Key,Data>* p): d_it(p) {}
00262       orderedIterator(const orderedIterator& i): d_it(i.d_it) { }
00263       // Default constructor
00264       orderedIterator() { }
00265       // (Dis)equality
00266       bool operator==(const orderedIterator& i) const {
00267         return d_it == i.d_it;
00268       }
00269       bool operator!=(const orderedIterator& i) const {
00270         return d_it != i.d_it;
00271       }
00272       // Dereference operators.
00273       std::pair<const Key, Data> operator*() const {
00274         return std::pair<const Key, Data>(d_it->getKey(), d_it->get());
00275       }
00276 
00277       // Prefix and postfix increment
00278       orderedIterator& operator++() { d_it = d_it->next(); return *this; }
00279       // Postfix increment: requires a Proxy object to hold the
00280       // intermediate value for dereferencing
00281       class Proxy {
00282         const std::pair<const Key, Data>* d_pair;
00283       public:
00284         Proxy(const std::pair<const Key, Data>& p): d_pair(&p) { }
00285         std::pair<const Key, Data>& operator*() { return *d_pair; }
00286       };
00287       // Actual postfix increment: returns Proxy with the old value.
00288       // Now, an expression like *i++ will return the current *i, and
00289       // then advance the orderedIterator.  However, don't try to use Proxy for
00290       // anything else.
00291       Proxy operator++(int) {
00292         Proxy e(*(*this));
00293         ++(*this);
00294         return e;
00295       }
00296   };
00297 
00298   orderedIterator orderedBegin() const { return orderedIterator(d_first); }
00299   orderedIterator orderedEnd() const { return orderedIterator(NULL); }
00300 
00301   iterator find(const Key& k) const { return iterator(d_map.find(k)); }
00302 
00303 }; // end of class CDMapOrdered
00304 
00305 
00306 }
00307 
00308 #endif

Generated on Thu Apr 13 16:57:29 2006 for CVC Lite by  doxygen 1.4.4