src/hugo/array_map.h
author alpar
Mon, 13 Sep 2004 17:20:03 +0000
changeset 842 a4bb28813570
parent 822 88226d9fe821
child 844 9bf990cb066d
permissions -rw-r--r--
Fix a DANGEROUS bug.
     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     /// The KeySet of the Map.
   255     typedef MapConstKeySet<ArrayMap> ConstKeySet;
   256 
   257     /// KeySet getter function.
   258     ConstKeySet keySet() const {
   259       return ConstKeySet(*this); 
   260     }
   261 
   262     /// The ConstValueSet of the Map.
   263     typedef MapConstValueSet<ArrayMap> ConstValueSet;
   264 
   265     /// ConstValueSet getter function.
   266     ConstValueSet valueSet() const {
   267       return ConstValueSet(*this);
   268     }
   269 
   270     /// The ValueSet of the Map.
   271     typedef MapValueSet<ArrayMap> ValueSet;
   272 
   273     /// ValueSet getter function.
   274     ValueSet valueSet() {
   275       return ValueSet(*this);
   276     }
   277 
   278   private:
   279       
   280     void allocate_memory() {
   281       int max_id = -1;
   282       for (KeyIt it(*MapBase::getGraph()); it != INVALID; ++it) {
   283 	int id = MapBase::getGraph()->id(it);
   284 	if (id > max_id) {
   285 	  max_id = id;
   286 	}			
   287       }
   288       if (max_id == -1) {
   289 	capacity = 0;
   290 	values = 0;
   291 	return;
   292       }
   293       capacity = 1;
   294       while (capacity <= max_id) {
   295 	capacity <<= 1;
   296       }
   297       values = allocator.allocate(capacity);	
   298     }      
   299 
   300     int capacity;
   301     Value* values;
   302     Allocator allocator;
   303   };		
   304 
   305 /// @}
   306 
   307 }
   308 
   309 #endif