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