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 _MORKBLOB_
15 # include "morkBlob.h"
16 #endif
17
18 #ifndef _MORKATOM_
19 # include "morkAtom.h"
20 #endif
21
22 #ifndef _MORKENV_
23 # include "morkEnv.h"
24 #endif
25
26 #ifndef _MORKATOMSPACE_
27 # include "morkAtomSpace.h"
28 #endif
29
30 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
31
32 /* static */
GetYarn(const morkAtom * atom,mdbYarn * outYarn)33 mork_bool morkAtom::GetYarn(const morkAtom* atom, mdbYarn* outYarn) {
34 const void* source = 0;
35 mdb_fill fill = 0;
36 mdb_cscode form = 0;
37 outYarn->mYarn_More = 0;
38
39 if (atom) {
40 if (atom->IsWeeBook()) {
41 morkWeeBookAtom* weeBook = (morkWeeBookAtom*)atom;
42 source = weeBook->mWeeBookAtom_Body;
43 fill = weeBook->mAtom_Size;
44 } else if (atom->IsBigBook()) {
45 morkBigBookAtom* bigBook = (morkBigBookAtom*)atom;
46 source = bigBook->mBigBookAtom_Body;
47 fill = bigBook->mBigBookAtom_Size;
48 form = bigBook->mBigBookAtom_Form;
49 } else if (atom->IsWeeAnon()) {
50 morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*)atom;
51 source = weeAnon->mWeeAnonAtom_Body;
52 fill = weeAnon->mAtom_Size;
53 } else if (atom->IsBigAnon()) {
54 morkBigAnonAtom* bigAnon = (morkBigAnonAtom*)atom;
55 source = bigAnon->mBigAnonAtom_Body;
56 fill = bigAnon->mBigAnonAtom_Size;
57 form = bigAnon->mBigAnonAtom_Form;
58 }
59 }
60
61 if (source && fill) // have an atom with nonempty content?
62 {
63 // if we have too many bytes, and yarn seems growable:
64 if (fill > outYarn->mYarn_Size && outYarn->mYarn_Grow) // try grow?
65 (*outYarn->mYarn_Grow)(outYarn, (mdb_size)fill); // request bigger
66
67 mdb_size size = outYarn->mYarn_Size; // max dest size
68 if (fill > size) // too much atom content?
69 {
70 outYarn->mYarn_More = fill - size; // extra atom bytes omitted
71 fill = size; // copy no more bytes than size of yarn buffer
72 }
73 void* dest = outYarn->mYarn_Buf; // where bytes are going
74 if (!dest) // nil destination address buffer?
75 fill = 0; // we can't write any content at all
76
77 if (fill) // anything to copy?
78 MORK_MEMCPY(dest, source, fill); // copy fill bytes to yarn
79
80 outYarn->mYarn_Fill = fill; // tell yarn size of copied content
81 } else // no content to put into the yarn
82 {
83 outYarn->mYarn_Fill = 0; // tell yarn that atom has no bytes
84 }
85 outYarn->mYarn_Form = form; // always update the form slot
86
87 return (source != 0);
88 }
89
90 /* static */
AliasYarn(const morkAtom * atom,mdbYarn * outYarn)91 mork_bool morkAtom::AliasYarn(const morkAtom* atom, mdbYarn* outYarn) {
92 outYarn->mYarn_More = 0;
93 outYarn->mYarn_Form = 0;
94
95 if (atom) {
96 if (atom->IsWeeBook()) {
97 morkWeeBookAtom* weeBook = (morkWeeBookAtom*)atom;
98 outYarn->mYarn_Buf = weeBook->mWeeBookAtom_Body;
99 outYarn->mYarn_Fill = weeBook->mAtom_Size;
100 outYarn->mYarn_Size = weeBook->mAtom_Size;
101 } else if (atom->IsBigBook()) {
102 morkBigBookAtom* bigBook = (morkBigBookAtom*)atom;
103 outYarn->mYarn_Buf = bigBook->mBigBookAtom_Body;
104 outYarn->mYarn_Fill = bigBook->mBigBookAtom_Size;
105 outYarn->mYarn_Size = bigBook->mBigBookAtom_Size;
106 outYarn->mYarn_Form = bigBook->mBigBookAtom_Form;
107 } else if (atom->IsWeeAnon()) {
108 morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*)atom;
109 outYarn->mYarn_Buf = weeAnon->mWeeAnonAtom_Body;
110 outYarn->mYarn_Fill = weeAnon->mAtom_Size;
111 outYarn->mYarn_Size = weeAnon->mAtom_Size;
112 } else if (atom->IsBigAnon()) {
113 morkBigAnonAtom* bigAnon = (morkBigAnonAtom*)atom;
114 outYarn->mYarn_Buf = bigAnon->mBigAnonAtom_Body;
115 outYarn->mYarn_Fill = bigAnon->mBigAnonAtom_Size;
116 outYarn->mYarn_Size = bigAnon->mBigAnonAtom_Size;
117 outYarn->mYarn_Form = bigAnon->mBigAnonAtom_Form;
118 } else
119 atom = 0; // show desire to put empty content in yarn
120 }
121
122 if (!atom) // empty content for yarn?
123 {
124 outYarn->mYarn_Buf = 0;
125 outYarn->mYarn_Fill = 0;
126 outYarn->mYarn_Size = 0;
127 // outYarn->mYarn_Grow = 0; // please don't modify the Grow slot
128 }
129 return (atom != 0);
130 }
131
GetBookAtomAid() const132 mork_aid morkAtom::GetBookAtomAid() const // zero or book atom's ID
133 {
134 return (this->IsBook()) ? ((morkBookAtom*)this)->mBookAtom_Id : 0;
135 }
136
GetBookAtomSpaceScope(morkEnv * ev) const137 mork_scope morkAtom::GetBookAtomSpaceScope(
138 morkEnv* ev) const // zero or book's space's scope
139 {
140 mork_scope outScope = 0;
141 if (this->IsBook()) {
142 const morkBookAtom* bookAtom = (const morkBookAtom*)this;
143 morkAtomSpace* space = bookAtom->mBookAtom_Space;
144 if (space->IsAtomSpace())
145 outScope = space->SpaceScope();
146 else
147 space->NonAtomSpaceTypeError(ev);
148 }
149
150 return outScope;
151 }
152
MakeCellUseForever(morkEnv * ev)153 void morkAtom::MakeCellUseForever(morkEnv* ev) {
154 MORK_USED_1(ev);
155 mAtom_CellUses = morkAtom_kForeverCellUses;
156 }
157
AddCellUse(morkEnv * ev)158 mork_u1 morkAtom::AddCellUse(morkEnv* ev) {
159 MORK_USED_1(ev);
160 if (mAtom_CellUses < morkAtom_kMaxCellUses) // not already maxed out?
161 ++mAtom_CellUses;
162
163 return mAtom_CellUses;
164 }
165
CutCellUse(morkEnv * ev)166 mork_u1 morkAtom::CutCellUse(morkEnv* ev) {
167 if (mAtom_CellUses) // any outstanding uses to cut?
168 {
169 if (mAtom_CellUses < morkAtom_kMaxCellUses) // not frozen at max?
170 --mAtom_CellUses;
171 } else
172 this->CellUsesUnderflowWarning(ev);
173
174 return mAtom_CellUses;
175 }
176
CellUsesUnderflowWarning(morkEnv * ev)177 /*static*/ void morkAtom::CellUsesUnderflowWarning(morkEnv* ev) {
178 ev->NewWarning("mAtom_CellUses underflow");
179 }
180
BadAtomKindError(morkEnv * ev)181 /*static*/ void morkAtom::BadAtomKindError(morkEnv* ev) {
182 ev->NewError("bad mAtom_Kind");
183 }
184
ZeroAidError(morkEnv * ev)185 /*static*/ void morkAtom::ZeroAidError(morkEnv* ev) {
186 ev->NewError("zero atom ID");
187 }
188
AtomSizeOverflowError(morkEnv * ev)189 /*static*/ void morkAtom::AtomSizeOverflowError(morkEnv* ev) {
190 ev->NewError("atom mAtom_Size overflow");
191 }
192
InitRowOidAtom(morkEnv * ev,const mdbOid & inOid)193 void morkOidAtom::InitRowOidAtom(morkEnv* ev, const mdbOid& inOid) {
194 MORK_USED_1(ev);
195 mAtom_CellUses = 0;
196 mAtom_Kind = morkAtom_kKindRowOid;
197 mAtom_Change = morkChange_kNil;
198 mAtom_Size = 0;
199 mOidAtom_Oid = inOid; // bitwise copy
200 }
201
InitTableOidAtom(morkEnv * ev,const mdbOid & inOid)202 void morkOidAtom::InitTableOidAtom(morkEnv* ev, const mdbOid& inOid) {
203 MORK_USED_1(ev);
204 mAtom_CellUses = 0;
205 mAtom_Kind = morkAtom_kKindTableOid;
206 mAtom_Change = morkChange_kNil;
207 mAtom_Size = 0;
208 mOidAtom_Oid = inOid; // bitwise copy
209 }
210
InitWeeAnonAtom(morkEnv * ev,const morkBuf & inBuf)211 void morkWeeAnonAtom::InitWeeAnonAtom(morkEnv* ev, const morkBuf& inBuf) {
212 mAtom_Kind = 0;
213 mAtom_Change = morkChange_kNil;
214 if (inBuf.mBuf_Fill <= morkAtom_kMaxByteSize) {
215 mAtom_CellUses = 0;
216 mAtom_Kind = morkAtom_kKindWeeAnon;
217 mork_size size = inBuf.mBuf_Fill;
218 mAtom_Size = (mork_u1)size;
219 if (size && inBuf.mBuf_Body)
220 MORK_MEMCPY(mWeeAnonAtom_Body, inBuf.mBuf_Body, size);
221
222 mWeeAnonAtom_Body[size] = 0;
223 } else
224 this->AtomSizeOverflowError(ev);
225 }
226
InitBigAnonAtom(morkEnv * ev,const morkBuf & inBuf,mork_cscode inForm)227 void morkBigAnonAtom::InitBigAnonAtom(morkEnv* ev, const morkBuf& inBuf,
228 mork_cscode inForm) {
229 MORK_USED_1(ev);
230 mAtom_CellUses = 0;
231 mAtom_Kind = morkAtom_kKindBigAnon;
232 mAtom_Change = morkChange_kNil;
233 mAtom_Size = 0;
234 mBigAnonAtom_Form = inForm;
235 mork_size size = inBuf.mBuf_Fill;
236 mBigAnonAtom_Size = size;
237 if (size && inBuf.mBuf_Body)
238 MORK_MEMCPY(mBigAnonAtom_Body, inBuf.mBuf_Body, size);
239
240 mBigAnonAtom_Body[size] = 0;
241 }
242
NonBookAtomTypeError(morkEnv * ev)243 /*static*/ void morkBookAtom::NonBookAtomTypeError(morkEnv* ev) {
244 ev->NewError("non morkBookAtom");
245 }
246
HashFormAndBody(morkEnv * ev) const247 mork_u4 morkBookAtom::HashFormAndBody(morkEnv* ev) const {
248 // This hash is obviously a variation of the dragon book string hash.
249 // (I won't bother to explain or rationalize this usage for you.)
250
251 mork_u4 outHash = 0; // hash value returned
252 unsigned char c; // next character
253 const mork_u1* body; // body of bytes to hash
254 mork_size size = 0; // the number of bytes to hash
255
256 if (this->IsWeeBook()) {
257 size = mAtom_Size;
258 body = ((const morkWeeBookAtom*)this)->mWeeBookAtom_Body;
259 } else if (this->IsBigBook()) {
260 size = ((const morkBigBookAtom*)this)->mBigBookAtom_Size;
261 body = ((const morkBigBookAtom*)this)->mBigBookAtom_Body;
262 } else if (this->IsFarBook()) {
263 size = ((const morkFarBookAtom*)this)->mFarBookAtom_Size;
264 body = ((const morkFarBookAtom*)this)->mFarBookAtom_Body;
265 } else {
266 this->NonBookAtomTypeError(ev);
267 return 0;
268 }
269
270 const mork_u1* end = body + size;
271 while (body < end) {
272 c = *body++;
273 outHash <<= 4;
274 outHash += c;
275 mork_u4 top = outHash & 0xF0000000L; // top four bits
276 if (top) // any of high four bits equal to one?
277 {
278 outHash ^= (top >> 24); // fold down high bits
279 outHash ^= top; // zero top four bits
280 }
281 }
282
283 return outHash;
284 }
285
EqualFormAndBody(morkEnv * ev,const morkBookAtom * inAtom) const286 mork_bool morkBookAtom::EqualFormAndBody(morkEnv* ev,
287 const morkBookAtom* inAtom) const {
288 mork_bool outEqual = morkBool_kFalse;
289
290 const mork_u1* body = 0; // body of inAtom bytes to compare
291 mork_size size; // the number of inAtom bytes to compare
292 mork_cscode form; // nominal charset for ioAtom
293
294 if (inAtom->IsWeeBook()) {
295 size = inAtom->mAtom_Size;
296 body = ((const morkWeeBookAtom*)inAtom)->mWeeBookAtom_Body;
297 form = 0;
298 } else if (inAtom->IsBigBook()) {
299 size = ((const morkBigBookAtom*)inAtom)->mBigBookAtom_Size;
300 body = ((const morkBigBookAtom*)inAtom)->mBigBookAtom_Body;
301 form = ((const morkBigBookAtom*)inAtom)->mBigBookAtom_Form;
302 } else if (inAtom->IsFarBook()) {
303 size = ((const morkFarBookAtom*)inAtom)->mFarBookAtom_Size;
304 body = ((const morkFarBookAtom*)inAtom)->mFarBookAtom_Body;
305 form = ((const morkFarBookAtom*)inAtom)->mFarBookAtom_Form;
306 } else {
307 inAtom->NonBookAtomTypeError(ev);
308 return morkBool_kFalse;
309 }
310
311 const mork_u1* thisBody = 0; // body of bytes in this to compare
312 mork_size thisSize; // the number of bytes in this to compare
313 mork_cscode thisForm; // nominal charset for this atom
314
315 if (this->IsWeeBook()) {
316 thisSize = mAtom_Size;
317 thisBody = ((const morkWeeBookAtom*)this)->mWeeBookAtom_Body;
318 thisForm = 0;
319 } else if (this->IsBigBook()) {
320 thisSize = ((const morkBigBookAtom*)this)->mBigBookAtom_Size;
321 thisBody = ((const morkBigBookAtom*)this)->mBigBookAtom_Body;
322 thisForm = ((const morkBigBookAtom*)this)->mBigBookAtom_Form;
323 } else if (this->IsFarBook()) {
324 thisSize = ((const morkFarBookAtom*)this)->mFarBookAtom_Size;
325 thisBody = ((const morkFarBookAtom*)this)->mFarBookAtom_Body;
326 thisForm = ((const morkFarBookAtom*)this)->mFarBookAtom_Form;
327 } else {
328 this->NonBookAtomTypeError(ev);
329 return morkBool_kFalse;
330 }
331
332 // if atoms are empty, form is irrelevant
333 if (body && thisBody && size == thisSize && (!size || form == thisForm))
334 outEqual = (MORK_MEMCMP(body, thisBody, size) == 0);
335
336 return outEqual;
337 }
338
CutBookAtomFromSpace(morkEnv * ev)339 void morkBookAtom::CutBookAtomFromSpace(morkEnv* ev) {
340 morkAtomSpace* space = mBookAtom_Space;
341 if (space) {
342 mBookAtom_Space = 0;
343 space->mAtomSpace_AtomBodies.CutAtom(ev, this);
344 space->mAtomSpace_AtomAids.CutAtom(ev, this);
345 } else
346 ev->NilPointerError();
347 }
348
morkWeeBookAtom(mork_aid inAid)349 morkWeeBookAtom::morkWeeBookAtom(mork_aid inAid) {
350 mAtom_Kind = morkAtom_kKindWeeBook;
351 mAtom_CellUses = 0;
352 mAtom_Change = morkChange_kNil;
353 mAtom_Size = 0;
354
355 mBookAtom_Space = 0;
356 mBookAtom_Id = inAid;
357
358 mWeeBookAtom_Body[0] = 0;
359 }
360
InitWeeBookAtom(morkEnv * ev,const morkBuf & inBuf,morkAtomSpace * ioSpace,mork_aid inAid)361 void morkWeeBookAtom::InitWeeBookAtom(morkEnv* ev, const morkBuf& inBuf,
362 morkAtomSpace* ioSpace, mork_aid inAid) {
363 mAtom_Kind = 0;
364 mAtom_Change = morkChange_kNil;
365 if (ioSpace) {
366 if (inAid) {
367 if (inBuf.mBuf_Fill <= morkAtom_kMaxByteSize) {
368 mAtom_CellUses = 0;
369 mAtom_Kind = morkAtom_kKindWeeBook;
370 mBookAtom_Space = ioSpace;
371 mBookAtom_Id = inAid;
372 mork_size size = inBuf.mBuf_Fill;
373 mAtom_Size = (mork_u1)size;
374 if (size && inBuf.mBuf_Body)
375 MORK_MEMCPY(mWeeBookAtom_Body, inBuf.mBuf_Body, size);
376
377 mWeeBookAtom_Body[size] = 0;
378 } else
379 this->AtomSizeOverflowError(ev);
380 } else
381 this->ZeroAidError(ev);
382 } else
383 ev->NilPointerError();
384 }
385
InitBigBookAtom(morkEnv * ev,const morkBuf & inBuf,mork_cscode inForm,morkAtomSpace * ioSpace,mork_aid inAid)386 void morkBigBookAtom::InitBigBookAtom(morkEnv* ev, const morkBuf& inBuf,
387 mork_cscode inForm,
388 morkAtomSpace* ioSpace, mork_aid inAid) {
389 mAtom_Kind = 0;
390 mAtom_Change = morkChange_kNil;
391 if (ioSpace) {
392 if (inAid) {
393 mAtom_CellUses = 0;
394 mAtom_Kind = morkAtom_kKindBigBook;
395 mAtom_Size = 0;
396 mBookAtom_Space = ioSpace;
397 mBookAtom_Id = inAid;
398 mBigBookAtom_Form = inForm;
399 mork_size size = inBuf.mBuf_Fill;
400 mBigBookAtom_Size = size;
401 if (size && inBuf.mBuf_Body)
402 MORK_MEMCPY(mBigBookAtom_Body, inBuf.mBuf_Body, size);
403
404 mBigBookAtom_Body[size] = 0;
405 } else
406 this->ZeroAidError(ev);
407 } else
408 ev->NilPointerError();
409 }
410
InitFarBookAtom(morkEnv * ev,const morkBuf & inBuf,mork_cscode inForm,morkAtomSpace * ioSpace,mork_aid inAid)411 void morkFarBookAtom::InitFarBookAtom(morkEnv* ev, const morkBuf& inBuf,
412 mork_cscode inForm,
413 morkAtomSpace* ioSpace, mork_aid inAid) {
414 mAtom_Kind = 0;
415 mAtom_Change = morkChange_kNil;
416 if (ioSpace) {
417 if (inAid) {
418 mAtom_CellUses = 0;
419 mAtom_Kind = morkAtom_kKindFarBook;
420 mAtom_Size = 0;
421 mBookAtom_Space = ioSpace;
422 mBookAtom_Id = inAid;
423 mFarBookAtom_Form = inForm;
424 mFarBookAtom_Size = inBuf.mBuf_Fill;
425 mFarBookAtom_Body = (mork_u1*)inBuf.mBuf_Body;
426 } else
427 this->ZeroAidError(ev);
428 } else
429 ev->NilPointerError();
430 }
431
432 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
433