Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

IDMap_AMOS.cc

Go to the documentation of this file.
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 #include "IDMap_AMOS.hh" 00011 #include <string> 00012 #include <sstream> 00013 #include <cstring> 00014 using namespace AMOS; 00015 using namespace std; 00016 00017 00018 00019 00020 00021 //================================================ HashTriple_t ================ 00022 //----------------------------------------------------- operator= -------------- 00023 IDMap_t::HashTriple_t & IDMap_t::HashTriple_t::operator= 00024 (const HashTriple_t & s) 00025 { 00026 if ( this != &s ) 00027 { 00028 c = s.c; 00029 iid = s.iid; 00030 bid = s.bid; 00031 eid = s.eid; 00032 } 00033 return *this; 00034 } 00035 00036 00037 00038 00039 //================================================ HashNode_t ================== 00040 //----------------------------------------------------- clear ------------------ 00041 void IDMap_t::HashNode_t::clear ( ) 00042 { 00043 if ( triple != NULL ) 00044 if ( -- (triple -> c) == 0 ) 00045 delete triple; 00046 delete next; 00047 00048 triple = NULL; 00049 next = NULL; 00050 } 00051 00052 00053 00054 00055 //================================================ IDMap_t ===================== 00056 const NCode_t IDMap_t::NCODE = M_IDMAP; 00057 const Size_t IDMap_t::DEFAULT_NUM_BUCKETS = 1000; 00058 00059 00060 //----------------------------------------------------- clear ------------------ 00061 void IDMap_t::clear ( ) 00062 { 00063 if ( size_m > 0 ) 00064 { 00065 vector<HashNode_t>::iterator hni; 00066 for ( hni = iid_bucs_m . begin( ); hni != iid_bucs_m . end( ); hni ++ ) 00067 hni -> clearchain( ); 00068 for ( hni = eid_bucs_m . begin( ); hni != eid_bucs_m . end( ); hni ++ ) 00069 hni -> clearchain( ); 00070 size_m = 0; 00071 } 00072 type_m = NULL_NCODE; 00073 } 00074 00075 00076 //----------------------------------------------------- minbuckets ------------- 00077 Size_t IDMap_t::minbuckets (Size_t min) 00078 { 00079 //-- Bucket size constants 00080 const uint8_t NUM_BUCKET_SIZES = 27; 00081 const Size_t BUCKET_SIZES [NUM_BUCKET_SIZES] = 00082 { 00083 53l, 97l, 193l, 389l, 769l, 00084 1543l, 3079l, 6151l, 12289l, 24593l, 00085 49157l, 98317l, 196613l, 393241l, 786433l, 00086 1572869l, 3145739l, 6291469l, 12582917l, 25165843l, 00087 50331653l, 100663319l, 201326611l, 402653189l, 805306457l, 00088 1610612741l, 2147354947l 00089 }; 00090 00091 uint8_t first = 0; 00092 uint8_t len = NUM_BUCKET_SIZES; 00093 uint8_t half, middle; 00094 00095 //-- Binary search for a bucket size greater than hint 00096 while ( len > 0 ) 00097 { 00098 half = len >> 1; 00099 middle = first + half; 00100 if ( BUCKET_SIZES [middle] < min ) 00101 { 00102 first = middle + 1; 00103 len = len - half - 1; 00104 } 00105 else 00106 len = half; 00107 } 00108 if ( first == NUM_BUCKET_SIZES ) 00109 first --; 00110 00111 return BUCKET_SIZES [first]; 00112 } 00113 00114 00115 //----------------------------------------------------- lookupnode ------------- 00116 bool IDMap_t::lookupnode (ID_t key, HashNode_t * & node) const 00117 { 00118 if ( key == NULL_ID ) 00119 { 00120 node = NULL; 00121 return false; 00122 } 00123 for ( node = hashfunc (key); node -> next != NULL; node = node -> next ) 00124 if ( node -> triple -> iid == key ) 00125 return true; 00126 if ( node -> triple == NULL || node -> triple -> iid != key ) 00127 return false; 00128 else 00129 return true; 00130 } 00131 00132 00133 //----------------------------------------------------- lookupnode ------------- 00134 bool IDMap_t::lookupnode (const string & key, HashNode_t * & node) const 00135 { 00136 if ( key . empty( ) ) 00137 { 00138 node = NULL; 00139 return false; 00140 } 00141 for ( node = hashfunc (key); node -> next != NULL; node = node -> next ) 00142 if ( node -> triple -> eid == key ) 00143 return true; 00144 if ( node -> triple == NULL || node -> triple -> eid != key ) 00145 return false; 00146 else 00147 return true; 00148 } 00149 00150 00151 //----------------------------------------------------- removenode ------------- 00152 void IDMap_t::removenode (HashNode_t * curr, HashNode_t * prev) 00153 { 00154 if ( prev == NULL ) 00155 //-- If a root node 00156 { 00157 if ( curr -> next == NULL ) 00158 curr -> clear( ); // free curr's triple 00159 else 00160 { 00161 prev = curr -> next; // this will be the new root 00162 curr -> next = NULL; // as to not delete next on clear 00163 curr -> clear( ); // free curr's triple 00164 *curr = *prev; // overwrite root node 00165 delete prev; // free duplicate node 00166 } 00167 } 00168 else 00169 //-- If not a root node 00170 { 00171 prev -> next = curr -> next; // bypass curr 00172 curr -> next = NULL; // as to not delete next on clear 00173 curr -> clear( ); // free curr's triple 00174 delete curr; // free removed node 00175 } 00176 } 00177 00178 00179 //----------------------------------------------------- concat ----------------- 00180 void IDMap_t::concat (const IDMap_t & s) 00181 { 00182 if ( this != &s ) 00183 { 00184 resize (getSize( ) + s . getSize( )); 00185 00186 //-- Copy all the triples 00187 for ( const_iterator itr = s . begin( ); itr != s . end( ); ++ itr ) 00188 insert (itr -> iid, itr -> eid, itr -> bid); 00189 } 00190 } 00191 00192 00193 //----------------------------------------------------- insert ----------------- 00194 const IDMap_t::HashTriple_t * IDMap_t::insert (ID_t iid, 00195 const string & eid, 00196 ID_t bid) 00197 { 00198 if ( iid == NULL_ID && eid . empty( ) ) return NULL; 00199 00200 HashNode_t * curri, * curre; 00201 00202 if ( lookupnode (iid, curri) ) 00203 { 00204 ostringstream ss; 00205 ss << "Cannot insert int key '" << iid << "' multiple times"; 00206 AMOS_THROW_ARGUMENT (ss . str( )); 00207 } 00208 if ( lookupnode (eid, curre) ) 00209 { 00210 ostringstream ss; 00211 ss << "Cannot insert string key '" << eid << "' multiple times"; 00212 AMOS_THROW_ARGUMENT (ss . str( )); 00213 } 00214 00215 HashTriple_t * currt = new HashTriple_t (iid, eid, bid); 00216 00217 if ( curri != NULL ) 00218 { 00219 if ( curri -> triple != NULL ) 00220 curri = curri -> next = new HashNode_t( ); 00221 curri -> triple = currt; 00222 currt -> c ++; 00223 } 00224 if ( curre != NULL ) 00225 { 00226 if ( curre -> triple != NULL ) 00227 curre = curre -> next = new HashNode_t( ); 00228 curre -> triple = currt; 00229 currt -> c ++; 00230 } 00231 00232 if ( ++ size_m >= getBuckets( ) ) 00233 resize (size_m + 1); 00234 00235 return currt; 00236 } 00237 00238 00239 //----------------------------------------------------- readMessage ------------ 00240 void IDMap_t::readMessage (const Message_t & msg) 00241 { 00242 clear( ); 00243 00244 try { 00245 Size_t size = -1; 00246 istringstream ss; 00247 00248 if ( msg . exists (F_OBJECT) ) 00249 { 00250 string str = msg . getField (F_OBJECT); 00251 00252 if ( str . length( ) != NCODE_SIZE ) 00253 AMOS_THROW_ARGUMENT ("Invalid object type format"); 00254 type_m = Encode (str); 00255 } 00256 00257 if ( msg . exists (F_SIZE) ) 00258 { 00259 ss . str (msg . getField (F_SIZE)); 00260 ss >> size; 00261 if ( !ss ) 00262 AMOS_THROW_ARGUMENT ("Invalid size format"); 00263 ss . clear( ); 00264 00265 resize (size); 00266 } 00267 00268 if ( msg . exists (F_MAP) ) 00269 { 00270 string eid; 00271 ID_t bid, iid; 00272 ss . str (msg . getField (F_MAP)); 00273 00274 while ( ss ) 00275 { 00276 ss >> bid >> iid; 00277 ss . ignore( ); 00278 getline (ss, eid); 00279 if ( ! ss . fail( ) ) 00280 insert (iid, eid, bid); 00281 } 00282 00283 if ( ! ss . eof( ) ) 00284 AMOS_THROW_ARGUMENT ("Invalid map format"); 00285 ss . clear( ); 00286 00287 if ( size >= 0 && size != size_m ) 00288 AMOS_THROW_ARGUMENT ("map and size fields do not agree"); 00289 } 00290 } 00291 catch (ArgumentException_t) { 00292 00293 clear( ); 00294 throw; 00295 } 00296 } 00297 00298 00299 //----------------------------------------------------- remove ----------------- 00300 void IDMap_t::remove (ID_t key) 00301 { 00302 if ( key == NULL_ID ) return; 00303 string eid; 00304 00305 HashNode_t * prev = NULL; 00306 HashNode_t * curr = hashfunc (key); 00307 if ( curr -> triple != NULL ) 00308 for ( ; curr != NULL; curr = curr -> next ) 00309 { 00310 if ( curr -> triple -> iid == key ) 00311 { 00312 size_m --; 00313 if ( curr -> triple -> c > 1 ) 00314 eid = curr -> triple -> eid; 00315 removenode (curr, prev); 00316 break; 00317 } 00318 prev = curr; 00319 } 00320 00321 if ( eid . empty( ) ) 00322 return; 00323 00324 prev = NULL; 00325 curr = hashfunc (eid); 00326 if ( curr -> triple != NULL ) 00327 for ( ; curr != NULL; curr = curr -> next ) 00328 { 00329 if ( curr -> triple -> eid == eid ) 00330 { 00331 removenode (curr, prev); 00332 break; 00333 } 00334 prev = curr; 00335 } 00336 } 00337 00338 00339 //----------------------------------------------------- remove ----------------- 00340 void IDMap_t::remove (const string & key) 00341 { 00342 if ( key . empty( ) ) return; 00343 ID_t iid = NULL_ID; 00344 00345 HashNode_t * prev = NULL; 00346 HashNode_t * curr = hashfunc (key); 00347 if ( curr -> triple != NULL ) 00348 for ( ; curr != NULL; curr = curr -> next ) 00349 { 00350 if ( curr -> triple -> eid == key ) 00351 { 00352 size_m --; 00353 if ( curr -> triple -> c > 1 ) 00354 iid = curr -> triple -> iid; 00355 removenode (curr, prev); 00356 break; 00357 } 00358 prev = curr; 00359 } 00360 00361 if ( iid == NULL_ID ) 00362 return; 00363 00364 prev = NULL; 00365 curr = hashfunc (iid); 00366 if ( curr -> triple != NULL ) 00367 for ( ; curr != NULL; curr = curr -> next ) 00368 { 00369 if ( curr -> triple -> iid == iid ) 00370 { 00371 removenode (curr, prev); 00372 break; 00373 } 00374 prev = curr; 00375 } 00376 } 00377 00378 00379 //----------------------------------------------------- resize ----------------- 00380 void IDMap_t::resize (Size_t min) 00381 { 00382 if ( (min = minbuckets (min)) == getBuckets( ) ) 00383 return; 00384 00385 vector<HashTriple_t *> triples (size_m); 00386 long int pos = 0; 00387 00388 if ( size_m > 0 ) 00389 { 00390 //-- Collect all the triples 00391 for ( iterator itr = begin( ); itr != end ( ); ++ itr ) 00392 { 00393 itr -> c ++; 00394 triples [pos ++] = itr; 00395 } 00396 00397 Size_t size = size_m; 00398 NCode_t type = type_m; 00399 clear( ); 00400 size_m = size; 00401 type_m = type; 00402 } 00403 00404 //-- Resize the bucket vectors 00405 if ( size_m != pos ) 00406 AMOS_THROW ("Unknown fatal error during hash resize"); 00407 iid_bucs_m . resize (min); 00408 eid_bucs_m . resize (min); 00409 00410 //-- Put the triples back in the map via modified insert 00411 HashNode_t * curri, * curre; 00412 vector<HashTriple_t *>::iterator tpi; 00413 for ( tpi = triples . begin( ); tpi != triples . end( ); tpi ++ ) 00414 { 00415 lookupnode ((*tpi) -> iid, curri); 00416 lookupnode ((*tpi) -> eid, curre); 00417 00418 if ( curri != NULL ) 00419 { 00420 if ( curri -> triple != NULL ) 00421 curri = curri -> next = new HashNode_t( ); 00422 curri -> triple = (*tpi); 00423 curri -> triple -> c ++; 00424 } 00425 if ( curre != NULL ) 00426 { 00427 if ( curre -> triple != NULL ) 00428 curre = curre -> next = new HashNode_t( ); 00429 curre -> triple = (*tpi); 00430 curre -> triple -> c ++; 00431 } 00432 00433 (*tpi) -> c --; 00434 } 00435 } 00436 00437 00438 //----------------------------------------------------- writeMessage ----------- 00439 void IDMap_t::writeMessage (Message_t & msg) const 00440 { 00441 msg . clear( ); 00442 00443 try { 00444 ostringstream ss; 00445 00446 msg . setMessageCode (IDMap_t::NCODE); 00447 00448 if ( type_m != NULL_NCODE ) 00449 msg . setField (F_OBJECT, Decode (type_m)); 00450 00451 ss << size_m; 00452 msg . setField (F_SIZE, ss . str( )); 00453 ss . str (NULL_STRING); 00454 00455 if (size_m != 0 ) 00456 { 00457 //-- Output all the triples 00458 string str; 00459 for ( const_iterator itr = begin( ); itr != end( ); ++ itr ) 00460 { 00461 ss << itr -> bid << '\t' << itr -> iid << '\t'; 00462 str . append (ss . str( )); 00463 ss . str (NULL_STRING); 00464 str . append (itr -> eid); 00465 str . push_back (NL_CHAR); 00466 } 00467 00468 msg . setField (F_MAP, str); 00469 } 00470 } 00471 catch (ArgumentException_t) { 00472 00473 msg . clear( ); 00474 throw; 00475 } 00476 } 00477 00478 00479 //----------------------------------------------------- operator= -------------- 00480 IDMap_t & IDMap_t::operator= (const IDMap_t & s) 00481 { 00482 if ( this != &s ) 00483 { 00484 clear( ); 00485 type_m = s . type_m; 00486 concat (s); 00487 } 00488 00489 return *this; 00490 } 00491 00492 00493 //----------------------------------------------------- read ------------------- 00494 void IDMap_t::read (istream & in) 00495 { 00496 Size_t size; 00497 string ncode; 00498 string eid; 00499 ID_t bid, iid; 00500 00501 clear( ); 00502 00503 in >> ncode >> size; 00504 type_m = Encode (ncode); 00505 resize (size); 00506 00507 while ( in ) 00508 { 00509 in >> bid >> iid; 00510 in . ignore( ); 00511 getline (in, eid); 00512 if ( ! in . fail( ) ) 00513 insert (iid, eid, bid); 00514 } 00515 00516 if ( size == size_m && in . eof( ) ) 00517 in . clear( ); 00518 } 00519 00520 00521 //----------------------------------------------------- write ------------------ 00522 void IDMap_t::write (ostream & out) const 00523 { 00524 out << Decode(type_m) << ' ' << size_m << NL_CHAR; 00525 00526 for ( const_iterator itr = begin( ); itr != end( ); ++ itr ) 00527 out << itr -> bid << '\t' << itr -> iid << '\t' << itr -> eid << NL_CHAR; 00528 } 00529 00530 00531 00532 00533 00534 //================================================ iterator ==================== 00535 //------------------------------------------------ iterator -------------------- 00536 IDMap_t::iterator::iterator (vector<HashNode_t> * iid_bucs_p, 00537 vector<HashNode_t> * eid_bucs_p) 00538 : iid_bucs (iid_bucs_p), eid_bucs (eid_bucs_p) 00539 { 00540 if ( iid_bucs -> empty( ) ) 00541 curr = NULL; 00542 else 00543 { 00544 iids = true; 00545 buc = iid_bucs -> begin( ); 00546 curr = &(*buc); 00547 if ( curr -> triple == NULL ) 00548 this->operator++(); 00549 } 00550 } 00551 00552 00553 //------------------------------------------------ operator++ ------------------ 00554 IDMap_t::iterator & IDMap_t::iterator::operator++ ( ) 00555 { 00556 while ( curr != NULL ) 00557 { 00558 curr = curr -> next; 00559 while ( curr == NULL ) 00560 { 00561 ++ buc; 00562 00563 if ( iids && buc >= iid_bucs -> end( ) ) 00564 { 00565 iids = false; 00566 buc = eid_bucs -> begin( ); 00567 } 00568 00569 if ( !iids && buc >= eid_bucs -> end( ) ) 00570 return *this; 00571 00572 if ( buc -> triple != NULL ) 00573 curr = &(*buc); 00574 } 00575 00576 if ( iids || curr -> triple -> c == 1 ) 00577 break; 00578 } 00579 return *this; 00580 } 00581 00582 00583 //------------------------------------------------ const_iterator -------------- 00584 IDMap_t::const_iterator::const_iterator (const vector<HashNode_t> * iid_bucs_p, 00585 const vector<HashNode_t> * eid_bucs_p) 00586 : iid_bucs (iid_bucs_p), eid_bucs (eid_bucs_p) 00587 { 00588 if ( iid_bucs -> empty( ) ) 00589 curr = NULL; 00590 else 00591 { 00592 iids = true; 00593 buc = iid_bucs -> begin( ); 00594 curr = &(*buc); 00595 if ( curr -> triple == NULL ) 00596 this->operator++(); 00597 } 00598 } 00599 00600 00601 //------------------------------------------------ operator++ ------------------ 00602 IDMap_t::const_iterator & IDMap_t::const_iterator::operator++ ( ) 00603 { 00604 while ( curr != NULL ) 00605 { 00606 curr = curr -> next; 00607 while ( curr == NULL ) 00608 { 00609 ++ buc; 00610 00611 if ( iids && buc >= iid_bucs -> end( ) ) 00612 { 00613 iids = false; 00614 buc = eid_bucs -> begin( ); 00615 } 00616 00617 if ( !iids && buc >= eid_bucs -> end( ) ) 00618 return *this; 00619 00620 if ( buc -> triple != NULL ) 00621 curr = &(*buc); 00622 } 00623 00624 if ( iids || curr -> triple -> c == 1 ) 00625 break; 00626 } 00627 return *this; 00628 }

Generated on Tue May 17 15:19:01 2005 for libAMOS by doxygen 1.3.8