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