00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef LEMON_ARRAY_MAP_H
00018 #define LEMON_ARRAY_MAP_H
00019
00020 #include <memory>
00021 #include <lemon/bits/map_iterator.h>
00022
00027
00028 namespace lemon {
00029
00030
00033
00041
00042
00043 template <typename _Graph,
00044 typename _Item,
00045 typename _Value>
00046 class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
00047
00048 typedef _Item Item;
00049 public:
00050
00052 typedef _Graph Graph;
00054 typedef _Item Key;
00055
00056 typedef AlterationNotifier<_Item> Registry;
00057
00059 typedef typename Registry::ObserverBase Parent;
00060
00062 typedef _Value Value;
00063
00064
00065 private:
00066 typedef std::allocator<Value> Allocator;
00067
00068
00069 public:
00070
00072
00073 ArrayMap(const Graph& _g) : graph(&_g) {
00074 Item it;
00075 attach(_g.getNotifier(Item()));
00076 allocate_memory();
00077 for (graph->first(it); it != INVALID; graph->next(it)) {
00078 int id = graph->id(it);;
00079 allocator.construct(&(values[id]), Value());
00080 }
00081 }
00082
00084
00086
00087 ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
00088 Item it;
00089 attach(_g.getNotifier(_Item()));
00090 allocate_memory();
00091 for (graph->first(it); it != INVALID; graph->next(it)) {
00092 int id = graph->id(it);;
00093 allocator.construct(&(values[id]), _v);
00094 }
00095 }
00096
00098
00099 ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
00100 if (copy.attached()) {
00101 attach(*copy.getRegistry());
00102 }
00103 capacity = copy.capacity;
00104 if (capacity == 0) return;
00105 values = allocator.allocate(capacity);
00106 Item it;
00107 for (graph->first(it); it != INVALID; graph->next(it)) {
00108 int id = graph->id(it);;
00109 allocator.construct(&(values[id]), copy.values[id]);
00110 }
00111 }
00112
00113 using Parent::attach;
00114 using Parent::detach;
00115 using Parent::attached;
00116
00118
00119 ArrayMap& operator=(const ArrayMap& copy) {
00120 if (© == this) return *this;
00121
00122 if (graph != copy.graph) {
00123 if (attached()) {
00124 clear();
00125 detach();
00126 }
00127 if (copy.attached()) {
00128 attach(*copy.getRegistry());
00129 }
00130 capacity = copy.capacity;
00131 if (capacity == 0) return *this;
00132 values = allocator.allocate(capacity);
00133 }
00134
00135 Item it;
00136 for (graph->first(it); it != INVALID; graph->next(it)) {
00137 int id = graph->id(it);;
00138 allocator.construct(&(values[id]), copy.values[id]);
00139 }
00140
00141 return *this;
00142 }
00143
00145
00146 virtual ~ArrayMap() {
00147 if (attached()) {
00148 clear();
00149 detach();
00150 }
00151 }
00152
00153
00156
00157 Value& operator[](const Key& key) {
00158 int id = graph->id(key);
00159 return values[id];
00160 }
00161
00162
00165
00166 const Value& operator[](const Key& key) const {
00167 int id = graph->id(key);
00168 return values[id];
00169 }
00170
00173
00174 void set(const Key& key, const Value& val) {
00175 (*this)[key] = val;
00176 }
00177
00179
00180 void add(const Key& key) {
00181 int id = graph->id(key);
00182 if (id >= capacity) {
00183 int new_capacity = (capacity == 0 ? 1 : capacity);
00184 while (new_capacity <= id) {
00185 new_capacity <<= 1;
00186 }
00187 Value* new_values = allocator.allocate(new_capacity);
00188 Item it;
00189 for (graph->first(it); it != INVALID; graph->next(it)) {
00190 int jd = graph->id(it);;
00191 if (id != jd) {
00192 allocator.construct(&(new_values[jd]), values[jd]);
00193 allocator.destroy(&(values[jd]));
00194 }
00195 }
00196 if (capacity != 0) allocator.deallocate(values, capacity);
00197 values = new_values;
00198 capacity = new_capacity;
00199 }
00200 allocator.construct(&(values[id]), Value());
00201 }
00202
00203 void add(const std::vector<Key>& keys) {
00204 int max_id = -1;
00205 for (int i = 0; i < (int)keys.size(); ++i) {
00206 int id = graph->id(keys[i]);
00207 if (id > max_id) {
00208 max_id = id;
00209 }
00210 }
00211 if (max_id >= capacity) {
00212 int new_capacity = (capacity == 0 ? 1 : capacity);
00213 while (new_capacity <= max_id) {
00214 new_capacity <<= 1;
00215 }
00216 Value* new_values = allocator.allocate(new_capacity);
00217 Item it;
00218 for (graph->first(it); it != INVALID; graph->next(it)) {
00219 int id = graph->id(it);
00220 bool found = false;
00221 for (int i = 0; i < (int)keys.size(); ++i) {
00222 int jd = graph->id(keys[i]);
00223 if (id == jd) {
00224 found = true;
00225 break;
00226 }
00227 }
00228 if (found) continue;
00229 allocator.construct(&(new_values[id]), values[id]);
00230 allocator.destroy(&(values[id]));
00231 }
00232 if (capacity != 0) allocator.deallocate(values, capacity);
00233 values = new_values;
00234 capacity = new_capacity;
00235 }
00236 for (int i = 0; i < (int)keys.size(); ++i) {
00237 int id = graph->id(keys[i]);
00238 allocator.construct(&(values[id]), Value());
00239 }
00240 }
00241
00243
00244 void erase(const Key& key) {
00245 int id = graph->id(key);
00246 allocator.destroy(&(values[id]));
00247 }
00248
00249 void erase(const std::vector<Key>& keys) {
00250 for (int i = 0; i < (int)keys.size(); ++i) {
00251 int id = graph->id(keys[i]);
00252 allocator.destroy(&(values[id]));
00253 }
00254 }
00255
00256 void build() {
00257 allocate_memory();
00258 Item it;
00259 for (graph->first(it); it != INVALID; graph->next(it)) {
00260 int id = graph->id(it);;
00261 allocator.construct(&(values[id]), Value());
00262 }
00263 }
00264
00265 void clear() {
00266 if (capacity != 0) {
00267 Item it;
00268 for (graph->first(it); it != INVALID; graph->next(it)) {
00269 int id = graph->id(it);
00270 allocator.destroy(&(values[id]));
00271 }
00272 allocator.deallocate(values, capacity);
00273 capacity = 0;
00274 }
00275 }
00276
00277 const Graph* getGraph() {
00278 return graph;
00279 }
00280
00281 private:
00282
00283 void allocate_memory() {
00284 int max_id = graph->maxId(_Item());
00285 if (max_id == -1) {
00286 capacity = 0;
00287 values = 0;
00288 return;
00289 }
00290 capacity = 1;
00291 while (capacity <= max_id) {
00292 capacity <<= 1;
00293 }
00294 values = allocator.allocate(capacity);
00295 }
00296
00297 const Graph* graph;
00298 int capacity;
00299 Value* values;
00300 Allocator allocator;
00301
00302 };
00303
00304 template <typename _Base>
00305 class ArrayMappableGraphExtender : public _Base {
00306 public:
00307
00308 typedef ArrayMappableGraphExtender<_Base> Graph;
00309 typedef _Base Parent;
00310
00311 typedef typename Parent::Node Node;
00312 typedef typename Parent::NodeIt NodeIt;
00313 typedef typename Parent::NodeNotifier NodeObserverRegistry;
00314
00315 typedef typename Parent::Edge Edge;
00316 typedef typename Parent::EdgeIt EdgeIt;
00317 typedef typename Parent::EdgeNotifier EdgeObserverRegistry;
00318
00319
00320
00321 template <typename _Value>
00322 class NodeMap
00323 : public IterableMapExtender<ArrayMap<Graph, Node, _Value> > {
00324 public:
00325 typedef ArrayMappableGraphExtender<_Base> Graph;
00326
00327 typedef typename Graph::Node Node;
00328 typedef typename Graph::NodeIt NodeIt;
00329
00330 typedef IterableMapExtender<ArrayMap<Graph, Node, _Value> > Parent;
00331
00332
00333 typedef typename Parent::Value Value;
00334
00335 NodeMap(const Graph& g)
00336 : Parent(g) {}
00337 NodeMap(const Graph& g, const Value& v)
00338 : Parent(g, v) {}
00339
00340 };
00341
00342 template <typename _Value>
00343 class EdgeMap
00344 : public IterableMapExtender<ArrayMap<Graph, Edge, _Value> > {
00345 public:
00346 typedef ArrayMappableGraphExtender<_Base> Graph;
00347
00348 typedef typename Graph::Edge Edge;
00349 typedef typename Graph::EdgeIt EdgeIt;
00350
00351 typedef IterableMapExtender<ArrayMap<Graph, Edge, _Value> > Parent;
00352
00353
00354 typedef typename Parent::Value Value;
00355
00356 EdgeMap(const Graph& g)
00357 : Parent(g) {}
00358 EdgeMap(const Graph& g, const Value& v)
00359 : Parent(g, v) {}
00360
00361 };
00362
00363 };
00364
00366
00367 }
00368
00369 #endif //LEMON_ARRAY_MAP_H