src/hugo/array_map.h
changeset 822 88226d9fe821
child 830 89dfa3bece81
equal deleted inserted replaced
-1:000000000000 0:6239d20c7029
       
     1 // -*- c++ -*-
       
     2 #ifndef ARRAY_MAP_H
       
     3 #define ARRAY_MAP_H
       
     4 
       
     5 #include <memory>
       
     6 
       
     7 #include <hugo/map_iterator.h>
       
     8 
       
     9 ///\ingroup graphmaps
       
    10 ///\file
       
    11 ///\brief Graph maps that construates and destruates
       
    12 ///their elements dynamically.
       
    13 
       
    14 namespace hugo {
       
    15 
       
    16 
       
    17   /// \addtogroup graphmaps
       
    18   /// @{
       
    19 	
       
    20   /** The ArrayMap template class is graph map structure what
       
    21    *  automatically updates the map when a key is added to or erased from
       
    22    *  the map. This map factory uses the allocators to implement 
       
    23    *  the container functionality.
       
    24    *
       
    25    *  The template parameter is the MapRegistry that the maps
       
    26    *  will belong to and the ValueType.
       
    27    */
       
    28 
       
    29   template <typename MapRegistry, typename Value> 
       
    30   class ArrayMap : public MapRegistry::MapBase {
       
    31 		
       
    32   public:
       
    33 		
       
    34     /// The graph type of the maps. 
       
    35     typedef typename MapRegistry::Graph Graph;
       
    36     /// The key type of the maps.
       
    37     typedef typename MapRegistry::KeyType KeyType;
       
    38     /// The iterator to iterate on the keys.
       
    39     typedef typename MapRegistry::KeyIt KeyIt;
       
    40 
       
    41     /// The MapBase of the Map which imlements the core regisitry function.
       
    42     typedef typename MapRegistry::MapBase MapBase;
       
    43 		
       
    44     
       
    45   public:
       
    46 
       
    47     /// The value type of the map.
       
    48     typedef Value ValueType;
       
    49     /// The reference type of the map;
       
    50     typedef Value& ReferenceType;
       
    51     /// The pointer type of the map;
       
    52     typedef Value* PointerType;
       
    53 
       
    54     /// The const value type of the map.
       
    55     typedef const Value ConstValueType;
       
    56     /// The const reference type of the map;
       
    57     typedef const Value& ConstReferenceType;
       
    58     /// The pointer type of the map;
       
    59     typedef const Value* ConstPointerType;
       
    60 
       
    61 
       
    62     typedef std::allocator<Value> Allocator;
       
    63 
       
    64 	
       
    65     /** Default constructor for the map.
       
    66      */
       
    67     ArrayMap() : values(0), capacity(0) {}
       
    68 			
       
    69     /** Graph and Registry initialized map constructor.
       
    70      */
       
    71     ArrayMap(const Graph& g, MapRegistry& r) : MapBase(g, r) {
       
    72       allocate_memory();
       
    73       for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
    74 	int id = MapBase::getGraph()->id(it);
       
    75 	allocator.construct(&(values[id]), Value());
       
    76       }								
       
    77     }
       
    78 
       
    79     /** Constructor to use default value to initialize the map. 
       
    80      */
       
    81     ArrayMap(const Graph& g, MapRegistry& r, const Value& v) 
       
    82       : MapBase(g, r) {
       
    83       allocate_memory();
       
    84       for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
    85 	int id = MapBase::getGraph()->id(it);
       
    86 	allocator.construct(&(values[id]), v);
       
    87       }								
       
    88     }
       
    89 
       
    90     /** Constructor to copy a map of the same map type.
       
    91      */
       
    92     ArrayMap(const ArrayMap& copy) : MapBase(*copy.graph, *copy.registry) {
       
    93       capacity = copy.capacity;
       
    94       if (capacity == 0) return;
       
    95       values = allocator.allocate(capacity);
       
    96       for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
    97 	int id = MapBase::getGraph()->id(it);
       
    98 	allocator.construct(&(values[id]), copy.values[id]);
       
    99       }
       
   100     }
       
   101 
       
   102     /** Constructor to copy a map of an other map type.
       
   103      */
       
   104     template <typename CMap> ArrayMap(const CMap& copy) 
       
   105       : MapBase(copy), capacity(0), values(0) {
       
   106       if (MapBase::getGraph()) {
       
   107 	allocate_memory();
       
   108 	for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
   109 	  set(it, copy[it]);
       
   110 	}
       
   111       }
       
   112     }
       
   113 
       
   114     /** Assign operator to copy a map of the same map type.
       
   115      */
       
   116     ArrayMap& operator=(const ArrayMap& copy) {
       
   117       if (&copy == this) return *this;
       
   118       if (capacity != 0) {
       
   119 	MapBase::destroy();
       
   120 	allocator.deallocate(values, capacity);
       
   121       }
       
   122       capacity = copy.capacity;
       
   123       if (capacity == 0) return *this;
       
   124       values = allocator.allocate(capacity);
       
   125       for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
   126 	int id = MapBase::getGraph()->id(it);
       
   127 	allocator.construct(&(values[id]), copy.values[id]);
       
   128       }
       
   129       return *this;
       
   130     }
       
   131 
       
   132     /** Assign operator to copy a map an other map type.
       
   133      */
       
   134     template <typename CMap> ArrayMap& operator=(const CMap& copy) {
       
   135       if (MapBase::getGraph()) {
       
   136 	MapBase::destroy();
       
   137       } 
       
   138       MapBase::operator=(copy);
       
   139       if (MapBase::getGraph()) {
       
   140 	allocate_memory();
       
   141 	for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
   142 	  set(it, copy[it]);
       
   143 	}
       
   144       }
       
   145       return *this;
       
   146     }
       
   147 				
       
   148     /** The destructor of the map.
       
   149      */
       
   150     virtual ~ArrayMap() {
       
   151       if (capacity != 0) {
       
   152 	MapBase::destroy();
       
   153 	allocator.deallocate(values, capacity);
       
   154       }
       
   155     }
       
   156 	
       
   157 	
       
   158     /**
       
   159      * The subscript operator. The map can be subscripted by the
       
   160      * actual keys of the graph. 
       
   161      */
       
   162     ReferenceType operator[](const KeyType& key) {
       
   163       int id = MapBase::getGraph()->id(key);
       
   164       return values[id];
       
   165     } 
       
   166 		
       
   167     /**
       
   168      * The const subscript operator. The map can be subscripted by the
       
   169      * actual keys of the graph. 
       
   170      */
       
   171     ConstReferenceType operator[](const KeyType& key) const {
       
   172       int id = MapBase::getGraph()->id(key);
       
   173       return values[id];
       
   174     }
       
   175 	
       
   176     /** Setter function of the map. Equivalent with map[key] = val.
       
   177      *  This is a compatibility feature with the not dereferable maps.
       
   178      */
       
   179     void set(const KeyType& key, const ValueType& val) {
       
   180       int id = MapBase::getGraph()->id(key);
       
   181       values[id] = val;
       
   182     }
       
   183 		
       
   184     /** Add a new key to the map. It called by the map registry.
       
   185      */
       
   186     void add(const KeyType& key) {
       
   187       int id = MapBase::getGraph()->id(key);
       
   188       if (id >= capacity) {
       
   189 	int new_capacity = (capacity == 0 ? 1 : capacity);
       
   190 	while (new_capacity <= id) {
       
   191 	  new_capacity <<= 1;
       
   192 	}
       
   193 	Value* new_values = allocator.allocate(new_capacity);;
       
   194 	for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
   195 	  int jd = MapBase::getGraph()->id(it);
       
   196 	  if (id != jd) {
       
   197 	    allocator.construct(&(new_values[jd]), values[jd]);
       
   198 	    allocator.destroy(&(values[jd]));
       
   199 	  }
       
   200 	}
       
   201 	if (capacity != 0) allocator.deallocate(values, capacity);
       
   202 	values = new_values;
       
   203 	capacity = new_capacity;
       
   204       }
       
   205       allocator.construct(&(values[id]), Value());
       
   206     }
       
   207 		
       
   208     /** Erase a key from the map. It called by the map registry.
       
   209      */
       
   210     void erase(const KeyType& key) {
       
   211       int id = MapBase::getGraph()->id(key);
       
   212       allocator.destroy(&(values[id]));
       
   213     }
       
   214 
       
   215     /** Clear the data structure.
       
   216      */
       
   217     void clear() {	
       
   218       if (capacity != 0) {
       
   219 	MapBase::destroy();
       
   220 	allocator.deallocate(values, capacity);
       
   221 	capacity = 0;
       
   222       }
       
   223     }
       
   224 
       
   225     /// The stl compatible pair iterator of the map.
       
   226     typedef MapIterator<ArrayMap> Iterator;
       
   227     /// The stl compatible const pair iterator of the map.
       
   228     typedef MapConstIterator<ArrayMap> ConstIterator;
       
   229 
       
   230     /** Returns the begin iterator of the map.
       
   231      */
       
   232     Iterator begin() {
       
   233       return Iterator(*this, KeyIt(*MapBase::getGraph()));
       
   234     }
       
   235 
       
   236     /** Returns the end iterator of the map.
       
   237      */
       
   238     Iterator end() {
       
   239       return Iterator(*this, INVALID);
       
   240     }
       
   241 
       
   242     /** Returns the begin ConstIterator of the map.
       
   243      */
       
   244     ConstIterator begin() const {
       
   245       return ConstIterator(*this, KeyIt(*MapBase::getGraph()));
       
   246     }
       
   247 
       
   248     /** Returns the end const_iterator of the map.
       
   249      */
       
   250     ConstIterator end() const {
       
   251       return ConstIterator(*this, INVALID);
       
   252     }
       
   253 
       
   254   private:
       
   255       
       
   256     void allocate_memory() {
       
   257       int max_id = -1;
       
   258       for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
       
   259 	int id = MapBase::getGraph()->id(it);
       
   260 	if (id > max_id) {
       
   261 	  max_id = id;
       
   262 	}			
       
   263       }
       
   264       if (max_id == -1) {
       
   265 	capacity = 0;
       
   266 	values = 0;
       
   267 	return;
       
   268       }
       
   269       capacity = 1;
       
   270       while (capacity <= max_id) {
       
   271 	capacity <<= 1;
       
   272       }
       
   273       values = allocator.allocate(capacity);	
       
   274     }      
       
   275 
       
   276     int capacity;
       
   277     Value* values;
       
   278     Allocator allocator;
       
   279   };		
       
   280 
       
   281 /// @}
       
   282 
       
   283 }
       
   284 
       
   285 #endif