00001
00025 #ifndef __MAGIC_MMAP_H__
00026 #define __MAGIC_MMAP_H__
00027
00028 #include <iostream>
00029 #include "magic/mobject.h"
00030 #include "magic/mmagisupp.h"
00031 #include "magic/mpararr.h"
00032
00033 BEGIN_NAMESPACE (MagiC);
00034
00035
00036
00037 class DataOStream;
00038
00039 class MapPair;
00040 class HashBucket;
00041 class HashFunc;
00042 class GenHash;
00043 class GenHashIter;
00044
00045
00047
00048
00049
00050
00051
00052
00053
00055
00058 class MapPair : public Object {
00059 public:
00060 const Comparable* key;
00061 Object* value;
00062 bool isref;
00063 MapPair () {key=NULL; value=NULL; isref=0;}
00064 ~MapPair ();
00065 int match (const Comparable& okey) const {return (*key) == okey;}
00066 DataOStream& operator>> (DataOStream& out) const;
00067 void check () const;
00068
00069 private:
00070 decl_dynamic (MapPair);
00071 };
00072
00073
00075
00076
00077
00078
00079
00080
00081
00083
00086 class HashBucket : public Object {
00087 public:
00088 MapPair pair;
00089 HashBucket* next;
00090
00091 HashBucket ();
00092 ~HashBucket ();
00093 DataOStream& operator>> (DataOStream& out) const;
00094 void check () const;
00095
00096 private:
00097 decl_dynamic (HashBucket);
00098 };
00099
00102 class HashFunc {
00103 public:
00104 virtual void hashfunc (int hashsize) const = 0;
00105 };
00106
00107 EXCEPTIONCLASS (not_found);
00108
00111 class GenHash : public Object {
00112 public:
00113
00114 GenHash (int hsize=64, int flags=0) {make (NULL, hsize, flags);}
00115 GenHash (HashFunc* hfunc, int hsize=16, int flags=0) {
00116 make (hfunc, hsize, flags);
00117 }
00118 void make (HashFunc* hashfunc, int hsize, int flags);
00119
00120 void set (const Comparable* key, Object* value);
00121 const Object* get (const Comparable& key) const throw (not_found);
00122 DataOStream& operator>> (DataOStream& out) const;
00123 TextOStream& operator>> (TextOStream& out) const;
00124 ostream& operator>> (ostream& out) const;
00125 void empty ();
00126 void remove (const Comparable& key);
00127 void operator+= (const GenHash& other);
00128
00129 void check () const;
00130
00131 protected:
00132 Array<HashBucket> hash;
00133 int hashsize;
00134 HashFunc* hashfunc;
00135 bool isref;
00136
00137 private:
00138 decl_dynamic (GenHash);
00139 friend class GenHashIter;
00140 };
00141
00144 class GenHashIter {
00145 public:
00146
00147 GenHashIter (const GenHash* hash);
00148
00149 void first ();
00150 void next ();
00151 Comparable& getkeyv ();
00152 Object& getvaluev ();
00153 const Comparable& getkey () const;
00154 const Object& getvalue () const;
00155 int exhausted () const {return exh;}
00156
00157 protected:
00158 const GenHash* hash;
00159 int bucket;
00160 HashBucket* currbucket;
00161 int exh;
00162 };
00163
00164 EXCEPTIONCLASS (map_item_not_found);
00165
00167
00168
00169
00170
00171
00172
00173
00175
00195 template <class keyclass, class valueclass>
00196 class Map : public Object {
00197 public:
00200 Map () {
00201 hash = new GenHash ();
00202 isref = 0;
00203 mFailByThrow=false;
00204 mFailByThrowOnce=false;
00205 mFailByNullOnce=false;
00206 }
00216 Map (int hashsize, int flags) {
00217 hash = new GenHash (hashsize, flags);
00218 isref = flags & MAP_REF;
00219 mFailByThrow=false;
00220 mFailByThrowOnce=false;
00221 mFailByNullOnce=false;
00222 }
00223 Map (const Map& orig) {
00224 hash = new GenHash ();
00225 isref = 0;
00226 mFailByThrow=false;
00227 mFailByThrowOnce=false;
00228 mFailByNullOnce=false;
00229
00230
00231 operator= (orig);
00232 }
00233 ~Map () {delete hash;}
00234
00238 void set (const keyclass& key, const valueclass& value) {
00239 keyclass* nkey = new keyclass (key);
00240 valueclass* nvalue = NULL;
00241 if (isref)
00242 nvalue = const_cast<valueclass*> (&value);
00243 else
00244 nvalue = new valueclass (value);
00245 hash->set (nkey, nvalue);
00246 }
00247
00250 void set (const keyclass& key, const valueclass* value) {
00251 hash->set (new keyclass (key), const_cast<valueclass*> (value));
00252 }
00253
00256 void remove (const keyclass& key) {
00257 hash->remove (key);
00258 }
00259
00261 bool hasKey (const keyclass& key) const {
00262 return int(hash->get (key));
00263 }
00264
00270 const valueclass& operator[] (const keyclass& key) const {
00271 return get (key);
00272 }
00273
00279 valueclass& operator[] (const keyclass& key) {
00280 return const_cast<valueclass&> (get (key));
00281 }
00282
00290 const valueclass& get (const keyclass& key) const {
00291 const valueclass* pResult = (valueclass*) hash->get (key);
00292 if ((mFailByThrow || mFailByThrowOnce) && !mFailByNullOnce) {
00293 if (pResult == NULL) {
00294 try {
00295 const keyclass* dummy = &dynamic_cast<const keyclass&> (key);
00296 dummy = NULL;
00297 } catch (...) {
00298 throw map_item_not_found ("Map item not found");
00299 }
00300 throw map_item_not_found (format("Map item '%s' not found", (CONSTR) key));
00301 }
00302 }
00303 mFailByThrowOnce = false;
00304 mFailByNullOnce = false;
00305 return *pResult;
00306 }
00307
00315 valueclass& getv (const keyclass& key) {
00316 return const_cast<valueclass&> (get (key));
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 const valueclass& getOr (const keyclass& key, const valueclass& def) const {
00330 valueclass* tmp = (valueclass*) hash->get (key);
00331 return tmp? *tmp : def;
00332 }
00333
00339 const valueclass* getp (const keyclass& key) const {
00340 return (valueclass*) hash->get (key);
00341 }
00342
00348 valueclass* getvp (const keyclass& key) {
00349 return (valueclass*) hash->get (key);
00350 }
00351
00352
00353
00355 virtual DataOStream& operator>> (DataOStream& out) const {
00356 hash->operator>> (out);
00357 return out;
00358 }
00359
00361 virtual ostream& operator>> (ostream& out) const {
00362 hash->operator>> (out);
00363 return out;
00364 }
00365
00367 virtual TextOStream& operator>> (TextOStream& out) const {
00368 hash->operator>> (out);
00369 return out;
00370 }
00371
00373 Map<keyclass,valueclass>& operator+= (const Map<keyclass,valueclass>& other) {
00374 hash->operator+= (*other.hash);
00375 return *this;
00376 }
00377
00379 Map<keyclass,valueclass>& operator= (const Map<keyclass,valueclass>& other) {
00380 hash->empty ();
00381 hash->operator+= (*other.hash);
00382 isref = other.isref;
00383 mFailByThrow=other.mFailByThrow;
00384 mFailByThrowOnce=other.mFailByThrowOnce;
00385 mFailByNullOnce=other.mFailByNullOnce;
00386 return *this;
00387 }
00388
00391 void empty () {
00392 hash->empty ();
00393 }
00394
00397 const GenHash* gethash () const {return hash;}
00398
00400 void check () const {hash->check();}
00401
00409 void failByThrow (bool bythrow=true) {mFailByThrow=bythrow;}
00410
00417 void failByThrowOnce (bool bythrow=true) const {mFailByThrowOnce=bythrow;}
00418
00425 void failByNullOnce (bool bynull=true) const {mFailByNullOnce=bynull;}
00426
00427 private:
00428 GenHash* hash;
00429 bool isref;
00430 bool mFailByThrow;
00431 mutable bool mFailByThrowOnce, mFailByNullOnce;
00432 };
00433
00434 enum mapdefs {MAP_NONE=0, MAP_REF=1};
00435
00436 #define CMap Map
00437
00443 #define getOrDefault(map,key,def)\
00444 (map.getp(key)? *map.getp(key):def)
00445
00446
00447
00449
00450
00451
00452
00453
00455
00471 template <class keyclass, class valueclass>
00472 class MapIter {
00473 public:
00474 MapIter (const Map<keyclass,valueclass>& map) : iter (map.gethash()) {;}
00475
00477 void first () {iter.first();}
00478
00480 void next () {iter.next();}
00481
00485 const keyclass& key () const {return (const keyclass&) iter.getkey();}
00486
00490 keyclass& key () {return (keyclass&) iter.getkeyv();}
00491
00495 const valueclass& value () const {return (const valueclass&) iter.getvalue();}
00496
00500 valueclass& value () {return (valueclass&) iter.getvaluev();}
00501
00505 int exhausted () const {return iter.exhausted();}
00506
00507 protected:
00508 GenHashIter iter;
00509 };
00510
00517 #define forMap(keytype,valuetype,mapname,varname) \
00518 for (MapIter<keytype,valuetype> varname (mapname); !varname.exhausted(); varname.next())
00519
00520
00521
00523
00524
00525
00526
00527
00528
00530
00531
00532 typedef Map<String,String> StringMap;
00533
00534
00535
00536 StringMap readStringMap (const String& filename);
00537
00538
00539 StringMap readStringMap (TextIStream& in, const char* path=NULL);
00540
00541 void writeStringMap (const Map<String,String>& map, TextOStream& out);
00542
00546 String toString (const StringMap& map);
00547
00553 void splitpairs (StringMap& trg, const String& source, char psep='=', char rsep='&');
00554
00560 String joinpairs (const StringMap& src, char psep='=', char rsep='&');
00561
00562
00570 #define forStringMap(mapname,varname) \
00571 for (MapIter<String,String> varname (mapname); !varname.exhausted(); varname.next())
00572
00573 END_NAMESPACE;
00574
00575 #endif
00576