diff options
Diffstat (limited to 'comm/mailnews/db/mork/morkAtom.cpp')
-rw-r--r-- | comm/mailnews/db/mork/morkAtom.cpp | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/comm/mailnews/db/mork/morkAtom.cpp b/comm/mailnews/db/mork/morkAtom.cpp new file mode 100644 index 0000000000..ad3b1d53bf --- /dev/null +++ b/comm/mailnews/db/mork/morkAtom.cpp @@ -0,0 +1,432 @@ +/* -*- 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 _MORKBLOB_ +# include "morkBlob.h" +#endif + +#ifndef _MORKATOM_ +# include "morkAtom.h" +#endif + +#ifndef _MORKENV_ +# include "morkEnv.h" +#endif + +#ifndef _MORKATOMSPACE_ +# include "morkAtomSpace.h" +#endif + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +/* static */ +mork_bool morkAtom::GetYarn(const morkAtom* atom, mdbYarn* outYarn) { + const void* source = 0; + mdb_fill fill = 0; + mdb_cscode form = 0; + outYarn->mYarn_More = 0; + + if (atom) { + if (atom->IsWeeBook()) { + morkWeeBookAtom* weeBook = (morkWeeBookAtom*)atom; + source = weeBook->mWeeBookAtom_Body; + fill = weeBook->mAtom_Size; + } else if (atom->IsBigBook()) { + morkBigBookAtom* bigBook = (morkBigBookAtom*)atom; + source = bigBook->mBigBookAtom_Body; + fill = bigBook->mBigBookAtom_Size; + form = bigBook->mBigBookAtom_Form; + } else if (atom->IsWeeAnon()) { + morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*)atom; + source = weeAnon->mWeeAnonAtom_Body; + fill = weeAnon->mAtom_Size; + } else if (atom->IsBigAnon()) { + morkBigAnonAtom* bigAnon = (morkBigAnonAtom*)atom; + source = bigAnon->mBigAnonAtom_Body; + fill = bigAnon->mBigAnonAtom_Size; + form = bigAnon->mBigAnonAtom_Form; + } + } + + if (source && fill) // have an atom with nonempty content? + { + // if we have too many bytes, and yarn seems growable: + if (fill > outYarn->mYarn_Size && outYarn->mYarn_Grow) // try grow? + (*outYarn->mYarn_Grow)(outYarn, (mdb_size)fill); // request bigger + + mdb_size size = outYarn->mYarn_Size; // max dest size + if (fill > size) // too much atom content? + { + outYarn->mYarn_More = fill - size; // extra atom bytes omitted + fill = size; // copy no more bytes than size of yarn buffer + } + void* dest = outYarn->mYarn_Buf; // where bytes are going + if (!dest) // nil destination address buffer? + fill = 0; // we can't write any content at all + + if (fill) // anything to copy? + MORK_MEMCPY(dest, source, fill); // copy fill bytes to yarn + + outYarn->mYarn_Fill = fill; // tell yarn size of copied content + } else // no content to put into the yarn + { + outYarn->mYarn_Fill = 0; // tell yarn that atom has no bytes + } + outYarn->mYarn_Form = form; // always update the form slot + + return (source != 0); +} + +/* static */ +mork_bool morkAtom::AliasYarn(const morkAtom* atom, mdbYarn* outYarn) { + outYarn->mYarn_More = 0; + outYarn->mYarn_Form = 0; + + if (atom) { + if (atom->IsWeeBook()) { + morkWeeBookAtom* weeBook = (morkWeeBookAtom*)atom; + outYarn->mYarn_Buf = weeBook->mWeeBookAtom_Body; + outYarn->mYarn_Fill = weeBook->mAtom_Size; + outYarn->mYarn_Size = weeBook->mAtom_Size; + } else if (atom->IsBigBook()) { + morkBigBookAtom* bigBook = (morkBigBookAtom*)atom; + outYarn->mYarn_Buf = bigBook->mBigBookAtom_Body; + outYarn->mYarn_Fill = bigBook->mBigBookAtom_Size; + outYarn->mYarn_Size = bigBook->mBigBookAtom_Size; + outYarn->mYarn_Form = bigBook->mBigBookAtom_Form; + } else if (atom->IsWeeAnon()) { + morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*)atom; + outYarn->mYarn_Buf = weeAnon->mWeeAnonAtom_Body; + outYarn->mYarn_Fill = weeAnon->mAtom_Size; + outYarn->mYarn_Size = weeAnon->mAtom_Size; + } else if (atom->IsBigAnon()) { + morkBigAnonAtom* bigAnon = (morkBigAnonAtom*)atom; + outYarn->mYarn_Buf = bigAnon->mBigAnonAtom_Body; + outYarn->mYarn_Fill = bigAnon->mBigAnonAtom_Size; + outYarn->mYarn_Size = bigAnon->mBigAnonAtom_Size; + outYarn->mYarn_Form = bigAnon->mBigAnonAtom_Form; + } else + atom = 0; // show desire to put empty content in yarn + } + + if (!atom) // empty content for yarn? + { + outYarn->mYarn_Buf = 0; + outYarn->mYarn_Fill = 0; + outYarn->mYarn_Size = 0; + // outYarn->mYarn_Grow = 0; // please don't modify the Grow slot + } + return (atom != 0); +} + +mork_aid morkAtom::GetBookAtomAid() const // zero or book atom's ID +{ + return (this->IsBook()) ? ((morkBookAtom*)this)->mBookAtom_Id : 0; +} + +mork_scope morkAtom::GetBookAtomSpaceScope( + morkEnv* ev) const // zero or book's space's scope +{ + mork_scope outScope = 0; + if (this->IsBook()) { + const morkBookAtom* bookAtom = (const morkBookAtom*)this; + morkAtomSpace* space = bookAtom->mBookAtom_Space; + if (space->IsAtomSpace()) + outScope = space->SpaceScope(); + else + space->NonAtomSpaceTypeError(ev); + } + + return outScope; +} + +void morkAtom::MakeCellUseForever(morkEnv* ev) { + MORK_USED_1(ev); + mAtom_CellUses = morkAtom_kForeverCellUses; +} + +mork_u1 morkAtom::AddCellUse(morkEnv* ev) { + MORK_USED_1(ev); + if (mAtom_CellUses < morkAtom_kMaxCellUses) // not already maxed out? + ++mAtom_CellUses; + + return mAtom_CellUses; +} + +mork_u1 morkAtom::CutCellUse(morkEnv* ev) { + if (mAtom_CellUses) // any outstanding uses to cut? + { + if (mAtom_CellUses < morkAtom_kMaxCellUses) // not frozen at max? + --mAtom_CellUses; + } else + this->CellUsesUnderflowWarning(ev); + + return mAtom_CellUses; +} + +/*static*/ void morkAtom::CellUsesUnderflowWarning(morkEnv* ev) { + ev->NewWarning("mAtom_CellUses underflow"); +} + +/*static*/ void morkAtom::BadAtomKindError(morkEnv* ev) { + ev->NewError("bad mAtom_Kind"); +} + +/*static*/ void morkAtom::ZeroAidError(morkEnv* ev) { + ev->NewError("zero atom ID"); +} + +/*static*/ void morkAtom::AtomSizeOverflowError(morkEnv* ev) { + ev->NewError("atom mAtom_Size overflow"); +} + +void morkOidAtom::InitRowOidAtom(morkEnv* ev, const mdbOid& inOid) { + MORK_USED_1(ev); + mAtom_CellUses = 0; + mAtom_Kind = morkAtom_kKindRowOid; + mAtom_Change = morkChange_kNil; + mAtom_Size = 0; + mOidAtom_Oid = inOid; // bitwise copy +} + +void morkOidAtom::InitTableOidAtom(morkEnv* ev, const mdbOid& inOid) { + MORK_USED_1(ev); + mAtom_CellUses = 0; + mAtom_Kind = morkAtom_kKindTableOid; + mAtom_Change = morkChange_kNil; + mAtom_Size = 0; + mOidAtom_Oid = inOid; // bitwise copy +} + +void morkWeeAnonAtom::InitWeeAnonAtom(morkEnv* ev, const morkBuf& inBuf) { + mAtom_Kind = 0; + mAtom_Change = morkChange_kNil; + if (inBuf.mBuf_Fill <= morkAtom_kMaxByteSize) { + mAtom_CellUses = 0; + mAtom_Kind = morkAtom_kKindWeeAnon; + mork_size size = inBuf.mBuf_Fill; + mAtom_Size = (mork_u1)size; + if (size && inBuf.mBuf_Body) + MORK_MEMCPY(mWeeAnonAtom_Body, inBuf.mBuf_Body, size); + + mWeeAnonAtom_Body[size] = 0; + } else + this->AtomSizeOverflowError(ev); +} + +void morkBigAnonAtom::InitBigAnonAtom(morkEnv* ev, const morkBuf& inBuf, + mork_cscode inForm) { + MORK_USED_1(ev); + mAtom_CellUses = 0; + mAtom_Kind = morkAtom_kKindBigAnon; + mAtom_Change = morkChange_kNil; + mAtom_Size = 0; + mBigAnonAtom_Form = inForm; + mork_size size = inBuf.mBuf_Fill; + mBigAnonAtom_Size = size; + if (size && inBuf.mBuf_Body) + MORK_MEMCPY(mBigAnonAtom_Body, inBuf.mBuf_Body, size); + + mBigAnonAtom_Body[size] = 0; +} + +/*static*/ void morkBookAtom::NonBookAtomTypeError(morkEnv* ev) { + ev->NewError("non morkBookAtom"); +} + +mork_u4 morkBookAtom::HashFormAndBody(morkEnv* ev) const { + // This hash is obviously a variation of the dragon book string hash. + // (I won't bother to explain or rationalize this usage for you.) + + mork_u4 outHash = 0; // hash value returned + unsigned char c; // next character + const mork_u1* body; // body of bytes to hash + mork_size size = 0; // the number of bytes to hash + + if (this->IsWeeBook()) { + size = mAtom_Size; + body = ((const morkWeeBookAtom*)this)->mWeeBookAtom_Body; + } else if (this->IsBigBook()) { + size = ((const morkBigBookAtom*)this)->mBigBookAtom_Size; + body = ((const morkBigBookAtom*)this)->mBigBookAtom_Body; + } else if (this->IsFarBook()) { + size = ((const morkFarBookAtom*)this)->mFarBookAtom_Size; + body = ((const morkFarBookAtom*)this)->mFarBookAtom_Body; + } else { + this->NonBookAtomTypeError(ev); + return 0; + } + + const mork_u1* end = body + size; + while (body < end) { + c = *body++; + outHash <<= 4; + outHash += c; + mork_u4 top = outHash & 0xF0000000L; // top four bits + if (top) // any of high four bits equal to one? + { + outHash ^= (top >> 24); // fold down high bits + outHash ^= top; // zero top four bits + } + } + + return outHash; +} + +mork_bool morkBookAtom::EqualFormAndBody(morkEnv* ev, + const morkBookAtom* inAtom) const { + mork_bool outEqual = morkBool_kFalse; + + const mork_u1* body = 0; // body of inAtom bytes to compare + mork_size size; // the number of inAtom bytes to compare + mork_cscode form; // nominal charset for ioAtom + + if (inAtom->IsWeeBook()) { + size = inAtom->mAtom_Size; + body = ((const morkWeeBookAtom*)inAtom)->mWeeBookAtom_Body; + form = 0; + } else if (inAtom->IsBigBook()) { + size = ((const morkBigBookAtom*)inAtom)->mBigBookAtom_Size; + body = ((const morkBigBookAtom*)inAtom)->mBigBookAtom_Body; + form = ((const morkBigBookAtom*)inAtom)->mBigBookAtom_Form; + } else if (inAtom->IsFarBook()) { + size = ((const morkFarBookAtom*)inAtom)->mFarBookAtom_Size; + body = ((const morkFarBookAtom*)inAtom)->mFarBookAtom_Body; + form = ((const morkFarBookAtom*)inAtom)->mFarBookAtom_Form; + } else { + inAtom->NonBookAtomTypeError(ev); + return morkBool_kFalse; + } + + const mork_u1* thisBody = 0; // body of bytes in this to compare + mork_size thisSize; // the number of bytes in this to compare + mork_cscode thisForm; // nominal charset for this atom + + if (this->IsWeeBook()) { + thisSize = mAtom_Size; + thisBody = ((const morkWeeBookAtom*)this)->mWeeBookAtom_Body; + thisForm = 0; + } else if (this->IsBigBook()) { + thisSize = ((const morkBigBookAtom*)this)->mBigBookAtom_Size; + thisBody = ((const morkBigBookAtom*)this)->mBigBookAtom_Body; + thisForm = ((const morkBigBookAtom*)this)->mBigBookAtom_Form; + } else if (this->IsFarBook()) { + thisSize = ((const morkFarBookAtom*)this)->mFarBookAtom_Size; + thisBody = ((const morkFarBookAtom*)this)->mFarBookAtom_Body; + thisForm = ((const morkFarBookAtom*)this)->mFarBookAtom_Form; + } else { + this->NonBookAtomTypeError(ev); + return morkBool_kFalse; + } + + // if atoms are empty, form is irrelevant + if (body && thisBody && size == thisSize && (!size || form == thisForm)) + outEqual = (MORK_MEMCMP(body, thisBody, size) == 0); + + return outEqual; +} + +void morkBookAtom::CutBookAtomFromSpace(morkEnv* ev) { + morkAtomSpace* space = mBookAtom_Space; + if (space) { + mBookAtom_Space = 0; + space->mAtomSpace_AtomBodies.CutAtom(ev, this); + space->mAtomSpace_AtomAids.CutAtom(ev, this); + } else + ev->NilPointerError(); +} + +morkWeeBookAtom::morkWeeBookAtom(mork_aid inAid) { + mAtom_Kind = morkAtom_kKindWeeBook; + mAtom_CellUses = 0; + mAtom_Change = morkChange_kNil; + mAtom_Size = 0; + + mBookAtom_Space = 0; + mBookAtom_Id = inAid; + + mWeeBookAtom_Body[0] = 0; +} + +void morkWeeBookAtom::InitWeeBookAtom(morkEnv* ev, const morkBuf& inBuf, + morkAtomSpace* ioSpace, mork_aid inAid) { + mAtom_Kind = 0; + mAtom_Change = morkChange_kNil; + if (ioSpace) { + if (inAid) { + if (inBuf.mBuf_Fill <= morkAtom_kMaxByteSize) { + mAtom_CellUses = 0; + mAtom_Kind = morkAtom_kKindWeeBook; + mBookAtom_Space = ioSpace; + mBookAtom_Id = inAid; + mork_size size = inBuf.mBuf_Fill; + mAtom_Size = (mork_u1)size; + if (size && inBuf.mBuf_Body) + MORK_MEMCPY(mWeeBookAtom_Body, inBuf.mBuf_Body, size); + + mWeeBookAtom_Body[size] = 0; + } else + this->AtomSizeOverflowError(ev); + } else + this->ZeroAidError(ev); + } else + ev->NilPointerError(); +} + +void morkBigBookAtom::InitBigBookAtom(morkEnv* ev, const morkBuf& inBuf, + mork_cscode inForm, + morkAtomSpace* ioSpace, mork_aid inAid) { + mAtom_Kind = 0; + mAtom_Change = morkChange_kNil; + if (ioSpace) { + if (inAid) { + mAtom_CellUses = 0; + mAtom_Kind = morkAtom_kKindBigBook; + mAtom_Size = 0; + mBookAtom_Space = ioSpace; + mBookAtom_Id = inAid; + mBigBookAtom_Form = inForm; + mork_size size = inBuf.mBuf_Fill; + mBigBookAtom_Size = size; + if (size && inBuf.mBuf_Body) + MORK_MEMCPY(mBigBookAtom_Body, inBuf.mBuf_Body, size); + + mBigBookAtom_Body[size] = 0; + } else + this->ZeroAidError(ev); + } else + ev->NilPointerError(); +} + +void morkFarBookAtom::InitFarBookAtom(morkEnv* ev, const morkBuf& inBuf, + mork_cscode inForm, + morkAtomSpace* ioSpace, mork_aid inAid) { + mAtom_Kind = 0; + mAtom_Change = morkChange_kNil; + if (ioSpace) { + if (inAid) { + mAtom_CellUses = 0; + mAtom_Kind = morkAtom_kKindFarBook; + mAtom_Size = 0; + mBookAtom_Space = ioSpace; + mBookAtom_Id = inAid; + mFarBookAtom_Form = inForm; + mFarBookAtom_Size = inBuf.mBuf_Fill; + mFarBookAtom_Body = (mork_u1*)inBuf.mBuf_Body; + } else + this->ZeroAidError(ev); + } else + ev->NilPointerError(); +} + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 |