/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _MDB_ # include "mdb.h" #endif #ifndef _MORK_ # include "mork.h" #endif #ifndef _MORKNODE_ # include "morkNode.h" #endif #ifndef _MORKENV_ # include "morkEnv.h" #endif #ifndef _MORKBEAD_ # include "morkBead.h" #endif // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` // { ===== begin morkNode interface ===== /*public virtual*/ void morkBead::CloseMorkNode( morkEnv* ev) // CloseBead() only if open { if (this->IsOpenNode()) { this->MarkClosing(); this->CloseBead(ev); this->MarkShut(); } } /*public virtual*/ morkBead::~morkBead() // assert CloseBead() executed earlier { MORK_ASSERT(mBead_Color == 0 || mNode_Usage == morkUsage_kStack); } /*public non-poly*/ morkBead::morkBead(mork_color inBeadColor) : morkNode(morkUsage_kStack), mBead_Color(inBeadColor) {} /*public non-poly*/ morkBead::morkBead(const morkUsage& inUsage, nsIMdbHeap* ioHeap, mork_color inBeadColor) : morkNode(inUsage, ioHeap), mBead_Color(inBeadColor) {} /*public non-poly*/ morkBead::morkBead(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, mork_color inBeadColor) : morkNode(ev, inUsage, ioHeap), mBead_Color(inBeadColor) { if (ev->Good()) { if (ev->Good()) mNode_Derived = morkDerived_kBead; } } /*public non-poly*/ void morkBead::CloseBead( morkEnv* ev) // called by CloseMorkNode(); { if (this->IsNode()) { if (!this->IsShutNode()) { mBead_Color = 0; this->MarkShut(); } } else this->NonNodeError(ev); } // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` // { ===== begin morkNode interface ===== /*public virtual*/ void morkBeadMap::CloseMorkNode( morkEnv* ev) // CloseBeadMap() only if open { if (this->IsOpenNode()) { this->MarkClosing(); this->CloseBeadMap(ev); this->MarkShut(); } } /*public virtual*/ morkBeadMap::~morkBeadMap() // assert CloseBeadMap() executed earlier { MORK_ASSERT(this->IsShutNode()); } /*public non-poly*/ morkBeadMap::morkBeadMap(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap) : morkMap(ev, inUsage, ioHeap, sizeof(morkBead*), /*inValSize*/ 0, /*slotCount*/ 11, ioSlotHeap, /*holdChanges*/ morkBool_kFalse) { if (ev->Good()) mNode_Derived = morkDerived_kBeadMap; } /*public non-poly*/ void morkBeadMap::CloseBeadMap( morkEnv* ev) // called by CloseMorkNode(); { if (this->IsNode()) { this->CutAllBeads(ev); this->CloseMap(ev); this->MarkShut(); } else this->NonNodeError(ev); } // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` mork_bool morkBeadMap::AddBead(morkEnv* ev, morkBead* ioBead) // the AddBead() boolean return equals ev->Good(). { if (ioBead && ev->Good()) { morkBead* oldBead = 0; // old key in the map mork_bool put = this->Put(ev, &ioBead, /*val*/ (void*)0, /*key*/ &oldBead, /*val*/ (void*)0, (mork_change**)0); if (put) // replaced an existing key? { if (oldBead != ioBead) // new bead was not already in table? ioBead->AddStrongRef(ev); // now there's another ref if (oldBead && oldBead != ioBead) // need to release old node? oldBead->CutStrongRef(ev); } else ioBead->AddStrongRef(ev); // another ref if not already in table } else if (!ioBead) ev->NilPointerError(); return ev->Good(); } mork_bool morkBeadMap::CutBead(morkEnv* ev, mork_color inColor) { morkBead* oldBead = 0; // old key in the map morkBead bead(inColor); morkBead* key = &bead; mork_bool outCutNode = this->Cut(ev, &key, /*key*/ &oldBead, /*val*/ (void*)0, (mork_change**)0); if (oldBead) oldBead->CutStrongRef(ev); bead.CloseBead(ev); return outCutNode; } morkBead* morkBeadMap::GetBead(morkEnv* ev, mork_color inColor) // Note the returned bead does NOT have an increase in refcount for this. { morkBead* oldBead = 0; // old key in the map morkBead bead(inColor); morkBead* key = &bead; this->Get(ev, &key, /*key*/ &oldBead, /*val*/ (void*)0, (mork_change**)0); bead.CloseBead(ev); return oldBead; } mork_num morkBeadMap::CutAllBeads(morkEnv* ev) // CutAllBeads() releases all the referenced beads. { mork_num outSlots = mMap_Slots; morkBeadMapIter i(ev, this); morkBead* b = i.FirstBead(ev); while (b) { b->CutStrongRef(ev); i.CutHereBead(ev); b = i.NextBead(ev); } return outSlots; } // { ===== begin morkMap poly interface ===== /*virtual*/ mork_bool morkBeadMap::Equal(morkEnv* ev, const void* inKeyA, const void* inKeyB) const { MORK_USED_1(ev); return (*(const morkBead**)inKeyA)->BeadEqual(*(const morkBead**)inKeyB); } /*virtual*/ mork_u4 morkBeadMap::Hash(morkEnv* ev, const void* inKey) const { MORK_USED_1(ev); return (*(const morkBead**)inKey)->BeadHash(); } // } ===== end morkMap poly interface ===== // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 morkBead* morkBeadMapIter::FirstBead(morkEnv* ev) { morkBead* bead = 0; this->First(ev, &bead, /*val*/ (void*)0); return bead; } morkBead* morkBeadMapIter::NextBead(morkEnv* ev) { morkBead* bead = 0; this->Next(ev, &bead, /*val*/ (void*)0); return bead; } morkBead* morkBeadMapIter::HereBead(morkEnv* ev) { morkBead* bead = 0; this->Here(ev, &bead, /*val*/ (void*)0); return bead; } void morkBeadMapIter::CutHereBead(morkEnv* ev) { this->CutHere(ev, /*key*/ (void*)0, /*val*/ (void*)0); } // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` // { ===== begin morkNode interface ===== /*public virtual*/ void morkBeadProbeMap::CloseMorkNode( morkEnv* ev) // CloseBeadProbeMap() if open { if (this->IsOpenNode()) { this->MarkClosing(); this->CloseBeadProbeMap(ev); this->MarkShut(); } } /*public virtual*/ morkBeadProbeMap::~morkBeadProbeMap() // assert CloseBeadProbeMap() earlier { MORK_ASSERT(this->IsShutNode()); } /*public non-poly*/ morkBeadProbeMap::morkBeadProbeMap(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap) : morkProbeMap(ev, inUsage, ioHeap, /*inKeySize*/ sizeof(morkBead*), /*inValSize*/ 0, ioSlotHeap, /*startSlotCount*/ 11, /*inZeroIsClearKey*/ morkBool_kTrue) { if (ev->Good()) mNode_Derived = morkDerived_kBeadProbeMap; } /*public non-poly*/ void morkBeadProbeMap::CloseBeadProbeMap( morkEnv* ev) // called by CloseMorkNode(); { if (this->IsNode()) { this->CutAllBeads(ev); this->CloseProbeMap(ev); this->MarkShut(); } else this->NonNodeError(ev); } // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` /*virtual*/ mork_test // hit(a,b) implies hash(a) == hash(b) morkBeadProbeMap::MapTest(morkEnv* ev, const void* inMapKey, const void* inAppKey) const { MORK_USED_1(ev); const morkBead* key = *(const morkBead**)inMapKey; if (key) { mork_bool hit = key->BeadEqual(*(const morkBead**)inAppKey); return (hit) ? morkTest_kHit : morkTest_kMiss; } else return morkTest_kVoid; } /*virtual*/ mork_u4 // hit(a,b) implies hash(a) == hash(b) morkBeadProbeMap::MapHash(morkEnv* ev, const void* inAppKey) const { const morkBead* key = *(const morkBead**)inAppKey; if (key) return key->BeadHash(); else { ev->NilPointerWarning(); return 0; } } /*virtual*/ mork_u4 morkBeadProbeMap::ProbeMapHashMapKey( morkEnv* ev, const void* inMapKey) const { const morkBead* key = *(const morkBead**)inMapKey; if (key) return key->BeadHash(); else { ev->NilPointerWarning(); return 0; } } mork_bool morkBeadProbeMap::AddBead(morkEnv* ev, morkBead* ioBead) { if (ioBead && ev->Good()) { morkBead* bead = 0; // old key in the map mork_bool put = this->MapAtPut(ev, &ioBead, /*val*/ (void*)0, /*key*/ &bead, /*val*/ (void*)0); if (put) // replaced an existing key? { if (bead != ioBead) // new bead was not already in table? ioBead->AddStrongRef(ev); // now there's another ref if (bead && bead != ioBead) // need to release old node? bead->CutStrongRef(ev); } else ioBead->AddStrongRef(ev); // now there's another ref } else if (!ioBead) ev->NilPointerError(); return ev->Good(); } morkBead* morkBeadProbeMap::GetBead(morkEnv* ev, mork_color inColor) { morkBead* oldBead = 0; // old key in the map morkBead bead(inColor); morkBead* key = &bead; this->MapAt(ev, &key, &oldBead, /*val*/ (void*)0); bead.CloseBead(ev); return oldBead; } mork_num morkBeadProbeMap::CutAllBeads(morkEnv* ev) // CutAllBeads() releases all the referenced bead values. { mork_num outSlots = sMap_Slots; morkBeadProbeMapIter i(ev, this); morkBead* b = i.FirstBead(ev); while (b) { b->CutStrongRef(ev); b = i.NextBead(ev); } this->MapCutAll(ev); return outSlots; } // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789