Back to index

lightning-sunbird  0.9+nobinonly
morkBead.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef _MDB_
00039 #include "mdb.h"
00040 #endif
00041 
00042 #ifndef _MORK_
00043 #include "mork.h"
00044 #endif
00045 
00046 #ifndef _MORKNODE_
00047 #include "morkNode.h"
00048 #endif
00049 
00050 #ifndef _MORKENV_
00051 #include "morkEnv.h"
00052 #endif
00053 
00054 #ifndef _MORKBEAD_
00055 #include "morkBead.h"
00056 #endif
00057 
00058 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00059 
00060 // ````` ````` ````` ````` ````` 
00061 // { ===== begin morkNode interface =====
00062 
00063 /*public virtual*/ void
00064 morkBead::CloseMorkNode(morkEnv* ev) // CloseBead() only if open
00065 {
00066   if ( this->IsOpenNode() )
00067   {
00068     this->MarkClosing();
00069     this->CloseBead(ev);
00070     this->MarkShut();
00071   }
00072 }
00073 
00074 /*public virtual*/
00075 morkBead::~morkBead() // assert CloseBead() executed earlier
00076 {
00077   MORK_ASSERT(mBead_Color==0 || mNode_Usage == morkUsage_kStack );
00078 }
00079 
00080 /*public non-poly*/
00081 morkBead::morkBead(mork_color inBeadColor)
00082 : morkNode( morkUsage_kStack )
00083 , mBead_Color( inBeadColor )
00084 {
00085 }
00086 
00087 /*public non-poly*/
00088 morkBead::morkBead(const morkUsage& inUsage, nsIMdbHeap* ioHeap, 
00089   mork_color inBeadColor)
00090 : morkNode( inUsage, ioHeap )
00091 , mBead_Color( inBeadColor )
00092 {
00093 }
00094 
00095 /*public non-poly*/
00096 morkBead::morkBead(morkEnv* ev,
00097   const morkUsage& inUsage, nsIMdbHeap* ioHeap, mork_color inBeadColor)
00098 : morkNode(ev, inUsage, ioHeap)
00099 , mBead_Color( inBeadColor )
00100 {
00101   if ( ev->Good() )
00102   {
00103     if ( ev->Good() )
00104       mNode_Derived = morkDerived_kBead;
00105   }
00106 }
00107 
00108 /*public non-poly*/ void
00109 morkBead::CloseBead(morkEnv* ev) // called by CloseMorkNode();
00110 {
00111   if ( this )
00112   {
00113     if ( this->IsNode() )
00114     {
00115       if ( !this->IsShutNode() )
00116       {
00117         mBead_Color = 0;
00118         this->MarkShut();
00119       }
00120     }
00121     else
00122       this->NonNodeError(ev);
00123   }
00124   else
00125     ev->NilPointerError();
00126 }
00127 
00128 // } ===== end morkNode methods =====
00129 // ````` ````` ````` ````` ````` 
00130 
00131 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00132 
00133 // ````` ````` ````` ````` ````` 
00134 // { ===== begin morkNode interface =====
00135 
00136 /*public virtual*/ void
00137 morkBeadMap::CloseMorkNode(morkEnv* ev) // CloseBeadMap() only if open
00138 {
00139   if ( this->IsOpenNode() )
00140   {
00141     this->MarkClosing();
00142     this->CloseBeadMap(ev);
00143     this->MarkShut();
00144   }
00145 }
00146 
00147 /*public virtual*/
00148 morkBeadMap::~morkBeadMap() // assert CloseBeadMap() executed earlier
00149 {
00150   MORK_ASSERT(this->IsShutNode());
00151 }
00152 
00153 /*public non-poly*/
00154 morkBeadMap::morkBeadMap(morkEnv* ev,
00155   const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
00156 : morkMap(ev, inUsage, ioHeap, sizeof(morkBead*), /*inValSize*/ 0,
00157   /*slotCount*/ 11, ioSlotHeap, /*holdChanges*/ morkBool_kFalse)
00158 {
00159   if ( ev->Good() )
00160     mNode_Derived = morkDerived_kBeadMap;
00161 }
00162 
00163 /*public non-poly*/ void
00164 morkBeadMap::CloseBeadMap(morkEnv* ev) // called by CloseMorkNode();
00165 {
00166   if ( this )
00167   {
00168     if ( this->IsNode() )
00169     {
00170       this->CutAllBeads(ev);
00171       this->CloseMap(ev);
00172       this->MarkShut();
00173     }
00174     else
00175       this->NonNodeError(ev);
00176   }
00177   else
00178     ev->NilPointerError();
00179 }
00180 
00181 // } ===== end morkNode methods =====
00182 // ````` ````` ````` ````` ````` 
00183 
00184 mork_bool
00185 morkBeadMap::AddBead(morkEnv* ev, morkBead* ioBead)
00186   // the AddBead() boolean return equals ev->Good().
00187 {
00188   if ( ioBead && ev->Good() )
00189   {
00190     morkBead* oldBead = 0; // old key in the map
00191 
00192     mork_bool put = this->Put(ev, &ioBead, /*val*/ (void*) 0,
00193       /*key*/ &oldBead, /*val*/ (void*) 0, (mork_change**) 0);
00194       
00195     if ( put ) // replaced an existing key?
00196     {
00197       if ( oldBead != ioBead ) // new bead was not already in table?
00198         ioBead->AddStrongRef(ev); // now there's another ref
00199         
00200       if ( oldBead && oldBead != ioBead ) // need to release old node?
00201         oldBead->CutStrongRef(ev);
00202     }
00203     else
00204       ioBead->AddStrongRef(ev); // another ref if not already in table
00205   }
00206   else if ( !ioBead )
00207     ev->NilPointerError();
00208     
00209   return ev->Good();
00210 }
00211 
00212 mork_bool
00213 morkBeadMap::CutBead(morkEnv* ev, mork_color inColor)
00214 {
00215   morkBead* oldBead = 0; // old key in the map
00216   morkBead bead(inColor);
00217   morkBead* key = &bead;
00218   
00219   mork_bool outCutNode = this->Cut(ev, &key, 
00220     /*key*/ &oldBead, /*val*/ (void*) 0, (mork_change**) 0);
00221     
00222   if ( oldBead )
00223     oldBead->CutStrongRef(ev);
00224   
00225   bead.CloseBead(ev);
00226   return outCutNode;
00227 }
00228 
00229 morkBead*
00230 morkBeadMap::GetBead(morkEnv* ev, mork_color inColor)
00231   // Note the returned bead does NOT have an increase in refcount for this.
00232 {
00233   morkBead* oldBead = 0; // old key in the map
00234   morkBead bead(inColor);
00235   morkBead* key = &bead;
00236 
00237   this->Get(ev, &key, /*key*/ &oldBead, /*val*/ (void*) 0, (mork_change**) 0);
00238   
00239   bead.CloseBead(ev);
00240   return oldBead;
00241 }
00242 
00243 mork_num
00244 morkBeadMap::CutAllBeads(morkEnv* ev)
00245   // CutAllBeads() releases all the referenced beads.
00246 {
00247   mork_num outSlots = mMap_Slots;
00248   
00249   morkBeadMapIter i(ev, this);
00250   morkBead* b = i.FirstBead(ev);
00251 
00252   while ( b )
00253   {
00254     b->CutStrongRef(ev);
00255     i.CutHereBead(ev);
00256     b = i.NextBead(ev);
00257   }
00258   
00259   return outSlots;
00260 }
00261 
00262 
00263 // { ===== begin morkMap poly interface =====
00264 /*virtual*/ mork_bool
00265 morkBeadMap::Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const
00266 {
00267   MORK_USED_1(ev);
00268   return (*(const morkBead**) inKeyA)->BeadEqual(
00269     *(const morkBead**) inKeyB);
00270 }
00271 
00272 /*virtual*/ mork_u4
00273 morkBeadMap::Hash(morkEnv* ev, const void* inKey) const
00274 {
00275   MORK_USED_1(ev);
00276     return (*(const morkBead**) inKey)->BeadHash();
00277 }
00278 // } ===== end morkMap poly interface =====
00279 
00280 
00281 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00282 
00283  
00284 morkBead* morkBeadMapIter::FirstBead(morkEnv* ev)
00285 {
00286   morkBead* bead = 0;
00287   this->First(ev, &bead, /*val*/ (void*) 0);
00288   return bead;
00289 }
00290 
00291 morkBead* morkBeadMapIter::NextBead(morkEnv* ev)
00292 {
00293   morkBead* bead = 0;
00294   this->Next(ev, &bead, /*val*/ (void*) 0);
00295   return bead;
00296 }
00297 
00298 morkBead* morkBeadMapIter::HereBead(morkEnv* ev)
00299 {
00300   morkBead* bead = 0;
00301   this->Here(ev, &bead, /*val*/ (void*) 0);
00302   return bead;
00303 }
00304 
00305 void morkBeadMapIter::CutHereBead(morkEnv* ev)
00306 {
00307   this->CutHere(ev, /*key*/ (void*) 0, /*val*/ (void*) 0);
00308 }
00309 
00310 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00311 
00312 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00313 
00314 // ````` ````` ````` ````` ````` 
00315 // { ===== begin morkNode interface =====
00316 
00317 /*public virtual*/ void
00318 morkBeadProbeMap::CloseMorkNode(morkEnv* ev) // CloseBeadProbeMap() if open
00319 {
00320   if ( this->IsOpenNode() )
00321   {
00322     this->MarkClosing();
00323     this->CloseBeadProbeMap(ev);
00324     this->MarkShut();
00325   }
00326 }
00327 
00328 /*public virtual*/
00329 morkBeadProbeMap::~morkBeadProbeMap() // assert CloseBeadProbeMap() earlier
00330 {
00331   MORK_ASSERT(this->IsShutNode());
00332 }
00333 
00334 
00335 /*public non-poly*/
00336 morkBeadProbeMap::morkBeadProbeMap(morkEnv* ev, const morkUsage& inUsage,
00337     nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
00338 : morkProbeMap(ev, inUsage, ioHeap,
00339   /*inKeySize*/ sizeof(morkBead*), /*inValSize*/ 0,
00340   ioSlotHeap, /*startSlotCount*/ 11, 
00341   /*inZeroIsClearKey*/ morkBool_kTrue)
00342 {
00343   if ( ev->Good() )
00344     mNode_Derived = morkDerived_kBeadProbeMap;
00345 }
00346 
00347 /*public non-poly*/ void
00348 morkBeadProbeMap::CloseBeadProbeMap(morkEnv* ev) // called by CloseMorkNode();
00349 {
00350   if ( this )
00351   {
00352     if ( this->IsNode() )
00353     {
00354       this->CutAllBeads(ev);
00355       this->CloseProbeMap(ev);
00356       this->MarkShut();
00357     }
00358     else
00359       this->NonNodeError(ev);
00360   }
00361   else
00362     ev->NilPointerError();
00363 }
00364 
00365 // } ===== end morkNode methods =====
00366 // ````` ````` ````` ````` ````` 
00367 
00368 /*virtual*/ mork_test // hit(a,b) implies hash(a) == hash(b)
00369 morkBeadProbeMap::MapTest(morkEnv* ev, const void* inMapKey,
00370   const void* inAppKey) const
00371 {
00372   MORK_USED_1(ev);
00373   const morkBead* key = *(const morkBead**) inMapKey;
00374   if ( key )
00375   {
00376     mork_bool hit = key->BeadEqual(*(const morkBead**) inAppKey);
00377     return ( hit ) ? morkTest_kHit : morkTest_kMiss;
00378   }
00379   else
00380     return morkTest_kVoid;
00381 }
00382 
00383 /*virtual*/ mork_u4 // hit(a,b) implies hash(a) == hash(b)
00384 morkBeadProbeMap::MapHash(morkEnv* ev, const void* inAppKey) const
00385 {
00386   const morkBead* key = *(const morkBead**) inAppKey;
00387   if ( key )
00388     return key->BeadHash();
00389   else
00390   {
00391     ev->NilPointerWarning();
00392     return 0;
00393   }
00394 }
00395 
00396 /*virtual*/ mork_u4 
00397 morkBeadProbeMap::ProbeMapHashMapKey(morkEnv* ev,
00398   const void* inMapKey) const
00399 {
00400   const morkBead* key = *(const morkBead**) inMapKey;
00401   if ( key )
00402     return key->BeadHash();
00403   else
00404   {
00405     ev->NilPointerWarning();
00406     return 0;
00407   }
00408 }
00409 
00410 mork_bool
00411 morkBeadProbeMap::AddBead(morkEnv* ev, morkBead* ioBead)
00412 {
00413   if ( ioBead && ev->Good() )
00414   {
00415     morkBead* bead = 0; // old key in the map
00416     
00417     mork_bool put = this->MapAtPut(ev, &ioBead, /*val*/ (void*) 0, 
00418       /*key*/ &bead, /*val*/ (void*) 0);
00419           
00420     if ( put ) // replaced an existing key?
00421     {
00422       if ( bead != ioBead ) // new bead was not already in table?
00423         ioBead->AddStrongRef(ev); // now there's another ref
00424         
00425       if ( bead && bead != ioBead ) // need to release old node?
00426         bead->CutStrongRef(ev);
00427     }
00428     else
00429       ioBead->AddStrongRef(ev); // now there's another ref
00430   }
00431   else if ( !ioBead )
00432     ev->NilPointerError();
00433     
00434   return ev->Good();
00435 }
00436 
00437 morkBead*
00438 morkBeadProbeMap::GetBead(morkEnv* ev, mork_color inColor)
00439 {
00440   morkBead* oldBead = 0; // old key in the map
00441   morkBead bead(inColor);
00442   morkBead* key = &bead;
00443 
00444   this->MapAt(ev, &key, &oldBead, /*val*/ (void*) 0);
00445   
00446   bead.CloseBead(ev);
00447   return oldBead;
00448 }
00449 
00450 mork_num
00451 morkBeadProbeMap::CutAllBeads(morkEnv* ev)
00452   // CutAllBeads() releases all the referenced bead values.
00453 {
00454   mork_num outSlots = sMap_Slots;
00455   
00456   morkBeadProbeMapIter i(ev, this);
00457   morkBead* b = i.FirstBead(ev);
00458 
00459   while ( b )
00460   {
00461     b->CutStrongRef(ev);
00462     b = i.NextBead(ev);
00463   }
00464   this->MapCutAll(ev);
00465   
00466   return outSlots;
00467 }
00468 
00469 
00470 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00471 
00472