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 #include "magic/mobject.h"
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <fstream.h>
00029 #include "magic/mmap.h"
00030 #include "magic/mstream.h"
00031 #include "magic/mclass.h"
00032
00033 decl_module (map);
00034
00035
00036
00037
00038
00040
00041
00042
00043
00044
00045
00046
00048
00049 impl_dynamic (MapPair, {Object});
00050
00051 MapPair::~MapPair () {
00052 delete key;
00053 key = NULL;
00054 if (!isref)
00055 delete value;
00056 value = NULL;
00057 }
00058
00059 DumpContext& MapPair::operator>> (DumpContext& out) const {
00060 if (key)
00061 out.name("key") << *key;
00062 if (value)
00063 out.name("value") << *value;
00064 return out;
00065 }
00066
00067 void MapPair::check () const {
00068 ASSERT (value!=(void*)0x1);
00069 }
00070
00071
00072
00074
00075
00076
00077
00078
00079
00080
00082
00083 impl_dynamic (HashBucket, {Object});
00084
00085 HashBucket::HashBucket () {
00086 next=NULL;
00087 }
00088
00089 HashBucket::~HashBucket () {
00090 delete next;
00091 next = NULL;
00092 }
00093
00094 DumpContext& HashBucket::operator>> (DumpContext& out) const {
00095 out << pair;
00096 return out;
00097 }
00098
00099 void HashBucket::check () const {
00100 pair.check ();
00101 if (next)
00102 next->check ();
00103 }
00104
00105
00106
00108
00109
00110
00111
00112
00113
00114
00116
00117 impl_dynamic (GenHash, {Object});
00118
00119 void GenHash::make (HashFunc* hfunc, int hsize, int flags) {
00120 hashsize = hsize;
00121 hash.resize (hashsize);
00122 hashfunc = hfunc;
00123 isref = flags;
00124 }
00125
00126 void GenHash::set (const Comparable* key, Object* value) {
00127
00128
00129 int hval = key->hashfunc (hashsize);
00130
00131
00132 HashBucket* bucket = hash.getp (hval);
00133
00134
00135 if (bucket)
00136
00137 for (;bucket; bucket=bucket->next) {
00138
00139 if (bucket->pair.match (*key)) {
00140
00141 delete bucket->pair.value;
00142 delete key;
00143 break;
00144 }
00145
00146
00147
00148 if (!bucket->next) {
00149
00150 bucket->next = new HashBucket;
00151 bucket = bucket->next;
00152 bucket->pair.key = key;
00153 bucket->pair.isref = isref;
00154 break;
00155 }
00156 }
00157 else {
00158
00159 hash.put (bucket = new HashBucket, hval);
00160 bucket->pair.key = key;
00161 }
00162
00163
00164 bucket->pair.value = value;
00165 }
00166
00167 ostream& GenHash::operator>> (ostream& out) const {
00168 for (GenHashIter iter (this); !iter.exhausted(); iter.next())
00169 out << iter.getkey() << "=" << iter.getvalue() << "\n";
00170 return out;
00171 }
00172
00173 const Object* GenHash::get (const Comparable& key) const throw (not_found) {
00174 for (const HashBucket* sanko = hash.getp (key.hashfunc(hashsize)); sanko; sanko=sanko->next) {
00175 ASSERT (sanko->pair.key != (void*)0x1);
00176 ASSERT (sanko->pair.value != (void*)0x1);
00177 if (sanko->pair.match (key))
00178 return sanko->pair.value;
00179 }
00180
00181 return NULL;
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 }
00197
00198 void GenHash::empty () {
00199 hash.empty ();
00200 }
00201
00202 void GenHash::remove (const Comparable& key) {
00203 HashBucket* prev = NULL;
00204 int bucket = key.hashfunc (hashsize);
00205 for (HashBucket* sanko = hash.getp (bucket); sanko; sanko=sanko->next) {
00206 if (sanko->pair.match (key)) {
00207 if (prev) {
00208
00209 prev->next = sanko->next;
00210 sanko->next = NULL;
00211 delete sanko;
00212 } else {
00213
00214
00215 if (sanko->next) {
00216
00217 HashBucket* next = sanko->next;
00218 sanko->next = NULL;
00219 hash.put (next, bucket);
00220 delete sanko;
00221 } else {
00222
00223 hash.remove (bucket);
00224
00225 }
00226 }
00227 break;
00228 }
00229 prev = sanko;
00230 }
00231 }
00232
00233 void GenHash::operator+= (const GenHash& other) {
00234 for (GenHashIter i (&other); !i.exhausted(); i.next())
00235 set (static_cast<Comparable*> (i.getkey().clone ()), i.getvalue().clone ());
00236 }
00237
00238 DumpContext& GenHash::operator>> (DumpContext& out) const {
00239 out.name ("hashsize") << hashsize;
00240 out.name ("isref") << (int)isref;
00241 out.name ("hash") << hash;
00242 return out;
00243 }
00244
00245 void GenHash::check () const {
00246 for (int i=0; i<hash.size; i++)
00247 if (hash.getp(i))
00248 hash[i].check ();
00249 }
00250
00251
00252
00254
00255
00256
00257
00258
00259
00260
00262
00263 GenHashIter::GenHashIter (const GenHash* ghash) {
00264 hash = ghash;
00265 first ();
00266 }
00267
00268 void GenHashIter::first () {
00269 bucket = 0;
00270 currbucket = NULL;
00271 exh = 0;
00272 next ();
00273 }
00274
00275 void GenHashIter::next () {
00276 if (currbucket) {
00277 if ((currbucket = currbucket->next))
00278 return;
00279 else
00280 bucket++;
00281 }
00282
00283 while (bucket<hash->hash.size && (currbucket=(HashBucket*)(hash->hash.getp (bucket))) == NULL)
00284 bucket++;
00285
00286 if (bucket>=hash->hash.size)
00287 exh = 1;
00288 }
00289
00290 Comparable& GenHashIter::getkeyv () {
00291 if (currbucket)
00292 return const_cast<Comparable&> (*(currbucket->pair.key));
00293 else
00294 return *(Comparable*)NULL;
00295 }
00296
00297 Object& GenHashIter::getvaluev () {
00298 if (currbucket)
00299 return *(currbucket->pair.value);
00300 else
00301 return *(Object*) NULL;
00302 }
00303
00304 const Comparable& GenHashIter::getkey () const {
00305 if (currbucket)
00306 return *(currbucket->pair.key);
00307 else
00308 return *(const Comparable*) NULL;
00309 }
00310
00311 const Object& GenHashIter::getvalue () const {
00312 if (currbucket)
00313 return *(currbucket->pair.value);
00314 else
00315 return *(const Object*) NULL;
00316 }
00317
00318
00319
00321
00322
00323
00324
00325
00326
00327
00329
00330 void splitpairs (CMap<String,String>& trg, const String& source,
00331 char psep='=', char rsep='&') {
00332
00333
00334 trg.empty ();
00335
00336
00337 Array<String> tmp;
00338 source.split (tmp, rsep);
00339
00340
00341 for (int i=0; i<tmp.size; i++) {
00342
00343 int pos = tmp[i].find (psep);
00344 String left = tmp[i].left (pos);
00345 String right = tmp[i].mid (pos+1);
00346 trg.set (left, right);
00347 }
00348 }
00349
00350 String joinpairs (const CMap<String,String>& src, char psep='=', char rsep='&') {
00351 Array<String> arr;
00352 forStringMap (src, i)
00353 arr.add (new String (format ("%s%c%s", (CONSTR)i.key(), psep, (CONSTR)i.value())));
00354
00355 String result;
00356 result.join (arr, rsep);
00357 return result;
00358 }
00359
00360
00361 String toString (const StringMap& map) {
00362 String result = "{";
00363 bool first=true;
00364 forStringMap (map, i) {
00365 if (first)
00366 first = false;
00367 else
00368 result += ", ";
00369 result += i.key() + "=\042" + i.value() + "\042";
00370 }
00371 result += "}";
00372
00373 return result;
00374 }
00375
00376
00377
00379
00380
00381
00382
00383
00384
00386
00387 StringMap readStringMap (const String& filename) {
00388 ifstream in ((CONSTR) filename);
00389 if (!in)
00390 throw file_not_found (strformat ("Could not open file '%s' for reading StringMap", (CONSTR) filename));
00391
00392
00393 String path = "./";
00394 if (filename.findRev("/")!=-1)
00395 path = filename.mid(0, filename.findRev("/")+1);
00396
00397
00398 return readStringMap (in, path);
00399 }
00400
00401 StringMap readStringMap (istream& in, const char* path=NULL) {
00402 StringMap result;
00403 String paramStr;
00404 String section="";
00405 String buffer;
00406 Array<String> regpar;
00407 Array<String> pair;
00408
00409 while (getS (in, buffer, '\n')) {
00410 buffer.chop();
00411
00412
00413
00414 if (buffer == "# end-of-map")
00415 break;
00416
00417 if (buffer.regmatch ("^INCLUDE\\:? *(.+)", regpar)) {
00418
00419 String curPath="./";
00420 if (path)
00421 curPath = path;
00422
00423
00424 result += readStringMap (curPath+regpar[1]);
00425
00426 } else if (buffer.regmatch ("^\\[([a-zA-Z0-9]*)\\]", regpar)) {
00427
00428 section = (regpar[1]=="]")? String():regpar[1];
00429
00430 } else if (buffer.regmatch ("^[ \t]*\\#")) {
00431
00432 continue;
00433 } else {
00434
00435 buffer.split (pair, '=');
00436 if (pair.size==2) {
00437
00438 pair[0].chop();
00439 pair[1].chop();
00440
00441
00442 if (!isempty(pair[0]) && !isempty(pair[1])) {
00443
00444 if (!isempty(section))
00445 pair[0] = section+"."+pair[0];
00446 result.set (pair[0], pair[1]);
00447 }
00448 }
00449 }
00450 }
00451
00452 return result;
00453 }
00454
00455 void writeStringMap (const StringMap& map, ostream& out) {
00456
00457
00458
00459 out << "[]\n";
00460
00461 forStringMap (map, mapi)
00462 out << mapi.key() << "=" << mapi.value() << "\n";
00463 }
00464
00465