src/hugo/array_map.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
child 830 89dfa3bece81
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

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