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