00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef __MAP_H__
00026 #define __MAP_H__
00027
00028 #include <iostream.h>
00029 #include "magic/mobject.h"
00030 #include "magic/mmagisupp.h"
00031 #include "magic/mpararr.h"
00032
00033
00034 class DumpContext;
00035
00036 class MapPair;
00037 class HashBucket;
00038 class HashFunc;
00039 class GenHash;
00040 class GenHashIter;
00041
00044 class MapPair : public Object {
00045 public:
00046 const Comparable* key;
00047 Object* value;
00048 bool isref;
00049 MapPair () {key=NULL; value=NULL; isref=0;}
00050 ~MapPair ();
00051 int match (const Comparable& okey) const {return (*key) == okey;}
00052 DumpContext& operator>> (DumpContext& out) const;
00053 void check () const;
00054
00055 private:
00056 decl_dynamic (MapPair);
00057 };
00058
00060
00063 class HashBucket : public Object {
00064 public:
00065 MapPair pair;
00066 HashBucket* next;
00067
00068 HashBucket ();
00069 ~HashBucket ();
00070 DumpContext& operator>> (DumpContext& out) const;
00071 void check () const;
00072
00073 private:
00074 decl_dynamic (HashBucket);
00075 };
00076
00079 class HashFunc {
00080 public:
00081 virtual void hashfunc (int hashsize) const = 0;
00082 };
00083
00084 EXCEPTIONCLASS (not_found);
00085
00088 class GenHash : public Object {
00089 public:
00090
00091 GenHash (int hsize=64, int flags=0) {make (NULL, hsize, flags);}
00092 GenHash (HashFunc* hfunc, int hsize=16, int flags=0) {
00093 make (hfunc, hsize, flags);
00094 }
00095 void make (HashFunc* hashfunc, int hsize, int flags);
00096
00097 void set (const Comparable* key, Object* value);
00098 const Object* get (const Comparable& key) const throw (not_found);
00099 DumpContext& operator>> (DumpContext& out) const;
00100 ostream& operator>> (ostream& out) const;
00101 void empty ();
00102 void remove (const Comparable& key);
00103 void operator+= (const GenHash& other);
00104
00105 void check () const;
00106
00107 protected:
00108 Array<HashBucket> hash;
00109 int hashsize;
00110 HashFunc* hashfunc;
00111 bool isref;
00112
00113 private:
00114 decl_dynamic (GenHash);
00115 friend GenHashIter;
00116 };
00117
00120 class GenHashIter {
00121 public:
00122
00123 GenHashIter (const GenHash* hash);
00124
00125 void first ();
00126 void next ();
00127 Comparable& getkeyv ();
00128 Object& getvaluev ();
00129 const Comparable& getkey () const;
00130 const Object& getvalue () const;
00131 int exhausted () const {return exh;}
00132
00133 protected:
00134 const GenHash* hash;
00135 int bucket;
00136 HashBucket* currbucket;
00137 int exh;
00138 };
00139
00140 EXCEPTIONCLASS (map_item_not_found);
00141
00142
00143
00144
00164 template <class keyclass, class valueclass>
00165 class Map : public Object {
00166 public:
00169 Map () {
00170 hash = new GenHash ();
00171 isref = 0;
00172 mFailByThrow=false;
00173 mFailByThrowOnce=false;
00174 mFailByNullOnce=false;
00175 }
00185 Map (int hashsize, int flags) {
00186 hash = new GenHash (hashsize, flags);
00187 isref = flags & MAP_REF;
00188 mFailByThrow=false;
00189 mFailByThrowOnce=false;
00190 mFailByNullOnce=false;
00191 }
00192 Map (const Map& orig) {
00193 hash = new GenHash ();
00194 isref = 0;
00195 mFailByThrow=false;
00196 mFailByThrowOnce=false;
00197 mFailByNullOnce=false;
00198
00199
00200 operator= (orig);
00201 }
00202 ~Map () {delete hash;}
00203
00207 void set (const keyclass& key, const valueclass& value) {
00208 keyclass* nkey = new keyclass (key);
00209 valueclass* nvalue = NULL;
00210 if (isref)
00211 nvalue = const_cast<valueclass*> (&value);
00212 else
00213 nvalue = new valueclass (value);
00214 hash->set (nkey, nvalue);
00215 }
00216
00219 void set (const keyclass& key, const valueclass* value) {
00220 hash->set (new keyclass (key), const_cast<valueclass*> (value));
00221 }
00222
00225 void remove (const keyclass& key) {
00226 hash->remove (key);
00227 }
00228
00230 bool hasKey (const keyclass& key) const {
00231 return int(hash->get (key));
00232 }
00233
00239 const valueclass& operator[] (const keyclass& key) const {
00240 return get (key);
00241 }
00242
00248 valueclass& operator[] (const keyclass& key) {
00249 return const_cast<valueclass&> (get (key));
00250 }
00251
00259 const valueclass& get (const keyclass& key) const {
00260 const valueclass& result = (valueclass&) *hash->get (key);
00261 if ((mFailByThrow || mFailByThrowOnce) && !mFailByNullOnce) {
00262 mFailByThrowOnce = false;
00263 if (isnull(result)) {
00264 try {
00265 const keyclass* dummy = &dynamic_cast<const keyclass&> (key);
00266 dummy=NULL;
00267 } catch (...) {
00268 throw map_item_not_found ("Map item not found");
00269 }
00270 throw map_item_not_found (format("Map item '%s' not found", (CONSTR) key));
00271 }
00272 }
00273 mFailByNullOnce = false;
00274 return result;
00275 }
00276
00284 valueclass& getv (const keyclass& key) {
00285 return const_cast<valueclass&> (get (key));
00286 }
00287
00297 const valueclass& getOr (const keyclass& key, const valueclass& def) const {
00298 valueclass* tmp = (valueclass*) hash->get (key);
00299 return tmp? *tmp : def;
00300 }
00301
00307 const valueclass* getp (const keyclass& key) const {
00308 return (valueclass*) hash->get (key);
00309 }
00310
00316 valueclass* getvp (const keyclass& key) {
00317 return (valueclass*) hash->get (key);
00318 }
00319
00320
00321
00323 virtual DumpContext& operator>> (DumpContext& out) const {
00324 hash->operator>> (out);
00325 return out;
00326 }
00327
00329 virtual ostream& operator>> (ostream& out) const {
00330 hash->operator>> (out);
00331 return out;
00332 }
00333
00335 Map<keyclass,valueclass>& operator+= (const Map<keyclass,valueclass>& other) {
00336 hash->operator+= (*other.hash);
00337 return *this;
00338 }
00339
00341 Map<keyclass,valueclass>& operator= (const Map<keyclass,valueclass>& other) {
00342 hash->empty ();
00343 hash->operator+= (*other.hash);
00344 isref = other.isref;
00345 mFailByThrow=other.mFailByThrow;
00346 mFailByThrowOnce=other.mFailByThrowOnce;
00347 mFailByNullOnce=other.mFailByNullOnce;
00348 return *this;
00349 }
00350
00353 void empty () {
00354 hash->empty ();
00355 }
00356
00359 const GenHash* gethash () const {return hash;}
00360
00362 void check () const {hash->check();}
00363
00371 void failByThrow (bool bythrow=true) {mFailByThrow=bythrow;}
00372
00379 void failByThrowOnce (bool bythrow=true) const {mFailByThrowOnce=bythrow;}
00380
00387 void failByNullOnce (bool bynull=true) const {mFailByNullOnce=bynull;}
00388
00389 private:
00390 GenHash* hash;
00391 bool isref;
00392 bool mFailByThrow;
00393 mutable bool mFailByThrowOnce, mFailByNullOnce;
00394 };
00395
00396 enum mapdefs {MAP_NONE=0, MAP_REF=1};
00397
00398 #define CMap Map
00399
00404 #define getOrDefault(map,key,def)\
00405 (isnull(map[key])? def : map[key])
00406
00407
00408
00410
00411
00412
00413
00414
00416
00432 template <class keyclass, class valueclass>
00433 class MapIter {
00434 public:
00435 MapIter (const Map<keyclass,valueclass>& map) : iter (map.gethash()) {;}
00436
00438 void first () {iter.first();}
00439
00441 void next () {iter.next();}
00442
00446 const keyclass& key () const {return (const keyclass&) iter.getkey();}
00447
00451 keyclass& key () {return (keyclass&) iter.getkeyv();}
00452
00456 const valueclass& value () const {return (const valueclass&) iter.getvalue();}
00457
00461 valueclass& value () {return (valueclass&) iter.getvaluev();}
00462
00466 int exhausted () const {return iter.exhausted();}
00467
00468 protected:
00469 GenHashIter iter;
00470 };
00471
00478 #define forMap(keytype,valuetype,mapname,varname) \
00479 for (MapIter<keytype,valuetype> varname (mapname); !varname.exhausted(); varname.next())
00480
00481
00482
00484
00485
00486
00487
00488
00489
00491
00492
00493 typedef Map<String,String> StringMap;
00494
00495
00496
00497 StringMap readStringMap (const String& filename);
00498
00499
00500 StringMap readStringMap (istream& in, const char* path=NULL);
00501
00502 void writeStringMap (const Map<String,String>& map, ostream& out);
00503
00507 String toString (const StringMap& map);
00508
00514 void splitpairs (StringMap& trg, const String& source, char psep='=', char rsep='&');
00515
00521 String joinpairs (const StringMap& src, char psep='=', char rsep='&');
00522
00523
00531 #define forStringMap(mapname,varname) \
00532 for (MapIter<String,String> varname (mapname); !varname.exhausted(); varname.next())
00533
00534 #endif