1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef _MDB_
7 #  include "mdb.h"
8 #endif
9 
10 #ifndef _MORK_
11 #  include "mork.h"
12 #endif
13 
14 #ifndef _MORKNODE_
15 #  include "morkNode.h"
16 #endif
17 
18 #ifndef _MORKENV_
19 #  include "morkEnv.h"
20 #endif
21 
22 #ifndef _MORKBEAD_
23 #  include "morkBead.h"
24 #endif
25 
26 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
27 
28 // ````` ````` ````` ````` `````
29 // { ===== begin morkNode interface =====
30 
CloseMorkNode(morkEnv * ev)31 /*public virtual*/ void morkBead::CloseMorkNode(
32     morkEnv* ev)  // CloseBead() only if open
33 {
34   if (this->IsOpenNode()) {
35     this->MarkClosing();
36     this->CloseBead(ev);
37     this->MarkShut();
38   }
39 }
40 
41 /*public virtual*/
~morkBead()42 morkBead::~morkBead()  // assert CloseBead() executed earlier
43 {
44   MORK_ASSERT(mBead_Color == 0 || mNode_Usage == morkUsage_kStack);
45 }
46 
47 /*public non-poly*/
morkBead(mork_color inBeadColor)48 morkBead::morkBead(mork_color inBeadColor)
49     : morkNode(morkUsage_kStack), mBead_Color(inBeadColor) {}
50 
51 /*public non-poly*/
morkBead(const morkUsage & inUsage,nsIMdbHeap * ioHeap,mork_color inBeadColor)52 morkBead::morkBead(const morkUsage& inUsage, nsIMdbHeap* ioHeap,
53                    mork_color inBeadColor)
54     : morkNode(inUsage, ioHeap), mBead_Color(inBeadColor) {}
55 
56 /*public non-poly*/
morkBead(morkEnv * ev,const morkUsage & inUsage,nsIMdbHeap * ioHeap,mork_color inBeadColor)57 morkBead::morkBead(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
58                    mork_color inBeadColor)
59     : morkNode(ev, inUsage, ioHeap), mBead_Color(inBeadColor) {
60   if (ev->Good()) {
61     if (ev->Good()) mNode_Derived = morkDerived_kBead;
62   }
63 }
64 
CloseBead(morkEnv * ev)65 /*public non-poly*/ void morkBead::CloseBead(
66     morkEnv* ev)  // called by CloseMorkNode();
67 {
68   if (this->IsNode()) {
69     if (!this->IsShutNode()) {
70       mBead_Color = 0;
71       this->MarkShut();
72     }
73   } else
74     this->NonNodeError(ev);
75 }
76 
77 // } ===== end morkNode methods =====
78 // ````` ````` ````` ````` `````
79 
80 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
81 
82 // ````` ````` ````` ````` `````
83 // { ===== begin morkNode interface =====
84 
CloseMorkNode(morkEnv * ev)85 /*public virtual*/ void morkBeadMap::CloseMorkNode(
86     morkEnv* ev)  // CloseBeadMap() only if open
87 {
88   if (this->IsOpenNode()) {
89     this->MarkClosing();
90     this->CloseBeadMap(ev);
91     this->MarkShut();
92   }
93 }
94 
95 /*public virtual*/
~morkBeadMap()96 morkBeadMap::~morkBeadMap()  // assert CloseBeadMap() executed earlier
97 {
98   MORK_ASSERT(this->IsShutNode());
99 }
100 
101 /*public non-poly*/
morkBeadMap(morkEnv * ev,const morkUsage & inUsage,nsIMdbHeap * ioHeap,nsIMdbHeap * ioSlotHeap)102 morkBeadMap::morkBeadMap(morkEnv* ev, const morkUsage& inUsage,
103                          nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
104     : morkMap(ev, inUsage, ioHeap, sizeof(morkBead*), /*inValSize*/ 0,
105               /*slotCount*/ 11, ioSlotHeap, /*holdChanges*/ morkBool_kFalse) {
106   if (ev->Good()) mNode_Derived = morkDerived_kBeadMap;
107 }
108 
CloseBeadMap(morkEnv * ev)109 /*public non-poly*/ void morkBeadMap::CloseBeadMap(
110     morkEnv* ev)  // called by CloseMorkNode();
111 {
112   if (this->IsNode()) {
113     this->CutAllBeads(ev);
114     this->CloseMap(ev);
115     this->MarkShut();
116   } else
117     this->NonNodeError(ev);
118 }
119 
120 // } ===== end morkNode methods =====
121 // ````` ````` ````` ````` `````
122 
AddBead(morkEnv * ev,morkBead * ioBead)123 mork_bool morkBeadMap::AddBead(morkEnv* ev, morkBead* ioBead)
124 // the AddBead() boolean return equals ev->Good().
125 {
126   if (ioBead && ev->Good()) {
127     morkBead* oldBead = 0;  // old key in the map
128 
129     mork_bool put =
130         this->Put(ev, &ioBead, /*val*/ (void*)0,
131                   /*key*/ &oldBead, /*val*/ (void*)0, (mork_change**)0);
132 
133     if (put)  // replaced an existing key?
134     {
135       if (oldBead != ioBead)       // new bead was not already in table?
136         ioBead->AddStrongRef(ev);  // now there's another ref
137 
138       if (oldBead && oldBead != ioBead)  // need to release old node?
139         oldBead->CutStrongRef(ev);
140     } else
141       ioBead->AddStrongRef(ev);  // another ref if not already in table
142   } else if (!ioBead)
143     ev->NilPointerError();
144 
145   return ev->Good();
146 }
147 
CutBead(morkEnv * ev,mork_color inColor)148 mork_bool morkBeadMap::CutBead(morkEnv* ev, mork_color inColor) {
149   morkBead* oldBead = 0;  // old key in the map
150   morkBead bead(inColor);
151   morkBead* key = &bead;
152 
153   mork_bool outCutNode =
154       this->Cut(ev, &key,
155                 /*key*/ &oldBead, /*val*/ (void*)0, (mork_change**)0);
156 
157   if (oldBead) oldBead->CutStrongRef(ev);
158 
159   bead.CloseBead(ev);
160   return outCutNode;
161 }
162 
GetBead(morkEnv * ev,mork_color inColor)163 morkBead* morkBeadMap::GetBead(morkEnv* ev, mork_color inColor)
164 // Note the returned bead does NOT have an increase in refcount for this.
165 {
166   morkBead* oldBead = 0;  // old key in the map
167   morkBead bead(inColor);
168   morkBead* key = &bead;
169 
170   this->Get(ev, &key, /*key*/ &oldBead, /*val*/ (void*)0, (mork_change**)0);
171 
172   bead.CloseBead(ev);
173   return oldBead;
174 }
175 
CutAllBeads(morkEnv * ev)176 mork_num morkBeadMap::CutAllBeads(morkEnv* ev)
177 // CutAllBeads() releases all the referenced beads.
178 {
179   mork_num outSlots = mMap_Slots;
180 
181   morkBeadMapIter i(ev, this);
182   morkBead* b = i.FirstBead(ev);
183 
184   while (b) {
185     b->CutStrongRef(ev);
186     i.CutHereBead(ev);
187     b = i.NextBead(ev);
188   }
189 
190   return outSlots;
191 }
192 
193 // { ===== begin morkMap poly interface =====
Equal(morkEnv * ev,const void * inKeyA,const void * inKeyB) const194 /*virtual*/ mork_bool morkBeadMap::Equal(morkEnv* ev, const void* inKeyA,
195                                          const void* inKeyB) const {
196   MORK_USED_1(ev);
197   return (*(const morkBead**)inKeyA)->BeadEqual(*(const morkBead**)inKeyB);
198 }
199 
Hash(morkEnv * ev,const void * inKey) const200 /*virtual*/ mork_u4 morkBeadMap::Hash(morkEnv* ev, const void* inKey) const {
201   MORK_USED_1(ev);
202   return (*(const morkBead**)inKey)->BeadHash();
203 }
204 // } ===== end morkMap poly interface =====
205 
206 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
207 
FirstBead(morkEnv * ev)208 morkBead* morkBeadMapIter::FirstBead(morkEnv* ev) {
209   morkBead* bead = 0;
210   this->First(ev, &bead, /*val*/ (void*)0);
211   return bead;
212 }
213 
NextBead(morkEnv * ev)214 morkBead* morkBeadMapIter::NextBead(morkEnv* ev) {
215   morkBead* bead = 0;
216   this->Next(ev, &bead, /*val*/ (void*)0);
217   return bead;
218 }
219 
HereBead(morkEnv * ev)220 morkBead* morkBeadMapIter::HereBead(morkEnv* ev) {
221   morkBead* bead = 0;
222   this->Here(ev, &bead, /*val*/ (void*)0);
223   return bead;
224 }
225 
CutHereBead(morkEnv * ev)226 void morkBeadMapIter::CutHereBead(morkEnv* ev) {
227   this->CutHere(ev, /*key*/ (void*)0, /*val*/ (void*)0);
228 }
229 
230 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
231 
232 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
233 
234 // ````` ````` ````` ````` `````
235 // { ===== begin morkNode interface =====
236 
CloseMorkNode(morkEnv * ev)237 /*public virtual*/ void morkBeadProbeMap::CloseMorkNode(
238     morkEnv* ev)  // CloseBeadProbeMap() if open
239 {
240   if (this->IsOpenNode()) {
241     this->MarkClosing();
242     this->CloseBeadProbeMap(ev);
243     this->MarkShut();
244   }
245 }
246 
247 /*public virtual*/
~morkBeadProbeMap()248 morkBeadProbeMap::~morkBeadProbeMap()  // assert CloseBeadProbeMap() earlier
249 {
250   MORK_ASSERT(this->IsShutNode());
251 }
252 
253 /*public non-poly*/
morkBeadProbeMap(morkEnv * ev,const morkUsage & inUsage,nsIMdbHeap * ioHeap,nsIMdbHeap * ioSlotHeap)254 morkBeadProbeMap::morkBeadProbeMap(morkEnv* ev, const morkUsage& inUsage,
255                                    nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
256     : morkProbeMap(ev, inUsage, ioHeap,
257                    /*inKeySize*/ sizeof(morkBead*), /*inValSize*/ 0, ioSlotHeap,
258                    /*startSlotCount*/ 11,
259                    /*inZeroIsClearKey*/ morkBool_kTrue) {
260   if (ev->Good()) mNode_Derived = morkDerived_kBeadProbeMap;
261 }
262 
CloseBeadProbeMap(morkEnv * ev)263 /*public non-poly*/ void morkBeadProbeMap::CloseBeadProbeMap(
264     morkEnv* ev)  // called by CloseMorkNode();
265 {
266   if (this->IsNode()) {
267     this->CutAllBeads(ev);
268     this->CloseProbeMap(ev);
269     this->MarkShut();
270   } else
271     this->NonNodeError(ev);
272 }
273 
274 // } ===== end morkNode methods =====
275 // ````` ````` ````` ````` `````
276 
277 /*virtual*/ mork_test  // hit(a,b) implies hash(a) == hash(b)
MapTest(morkEnv * ev,const void * inMapKey,const void * inAppKey) const278 morkBeadProbeMap::MapTest(morkEnv* ev, const void* inMapKey,
279                           const void* inAppKey) const {
280   MORK_USED_1(ev);
281   const morkBead* key = *(const morkBead**)inMapKey;
282   if (key) {
283     mork_bool hit = key->BeadEqual(*(const morkBead**)inAppKey);
284     return (hit) ? morkTest_kHit : morkTest_kMiss;
285   } else
286     return morkTest_kVoid;
287 }
288 
289 /*virtual*/ mork_u4  // hit(a,b) implies hash(a) == hash(b)
MapHash(morkEnv * ev,const void * inAppKey) const290 morkBeadProbeMap::MapHash(morkEnv* ev, const void* inAppKey) const {
291   const morkBead* key = *(const morkBead**)inAppKey;
292   if (key)
293     return key->BeadHash();
294   else {
295     ev->NilPointerWarning();
296     return 0;
297   }
298 }
299 
ProbeMapHashMapKey(morkEnv * ev,const void * inMapKey) const300 /*virtual*/ mork_u4 morkBeadProbeMap::ProbeMapHashMapKey(
301     morkEnv* ev, const void* inMapKey) const {
302   const morkBead* key = *(const morkBead**)inMapKey;
303   if (key)
304     return key->BeadHash();
305   else {
306     ev->NilPointerWarning();
307     return 0;
308   }
309 }
310 
AddBead(morkEnv * ev,morkBead * ioBead)311 mork_bool morkBeadProbeMap::AddBead(morkEnv* ev, morkBead* ioBead) {
312   if (ioBead && ev->Good()) {
313     morkBead* bead = 0;  // old key in the map
314 
315     mork_bool put = this->MapAtPut(ev, &ioBead, /*val*/ (void*)0,
316                                    /*key*/ &bead, /*val*/ (void*)0);
317 
318     if (put)  // replaced an existing key?
319     {
320       if (bead != ioBead)          // new bead was not already in table?
321         ioBead->AddStrongRef(ev);  // now there's another ref
322 
323       if (bead && bead != ioBead)  // need to release old node?
324         bead->CutStrongRef(ev);
325     } else
326       ioBead->AddStrongRef(ev);  // now there's another ref
327   } else if (!ioBead)
328     ev->NilPointerError();
329 
330   return ev->Good();
331 }
332 
GetBead(morkEnv * ev,mork_color inColor)333 morkBead* morkBeadProbeMap::GetBead(morkEnv* ev, mork_color inColor) {
334   morkBead* oldBead = 0;  // old key in the map
335   morkBead bead(inColor);
336   morkBead* key = &bead;
337 
338   this->MapAt(ev, &key, &oldBead, /*val*/ (void*)0);
339 
340   bead.CloseBead(ev);
341   return oldBead;
342 }
343 
CutAllBeads(morkEnv * ev)344 mork_num morkBeadProbeMap::CutAllBeads(morkEnv* ev)
345 // CutAllBeads() releases all the referenced bead values.
346 {
347   mork_num outSlots = sMap_Slots;
348 
349   morkBeadProbeMapIter i(ev, this);
350   morkBead* b = i.FirstBead(ev);
351 
352   while (b) {
353     b->CutStrongRef(ev);
354     b = i.NextBead(ev);
355   }
356   this->MapCutAll(ev);
357 
358   return outSlots;
359 }
360 
361 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
362