summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/db/mork/morkBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/db/mork/morkBuilder.cpp')
-rw-r--r--comm/mailnews/db/mork/morkBuilder.cpp892
1 files changed, 892 insertions, 0 deletions
diff --git a/comm/mailnews/db/mork/morkBuilder.cpp b/comm/mailnews/db/mork/morkBuilder.cpp
new file mode 100644
index 0000000000..4e96209929
--- /dev/null
+++ b/comm/mailnews/db/mork/morkBuilder.cpp
@@ -0,0 +1,892 @@
+/* -*- 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 _MORKMAP_
+# include "morkMap.h"
+#endif
+
+#ifndef _MORKENV_
+# include "morkEnv.h"
+#endif
+
+#ifndef _MORKPARSER_
+# include "morkParser.h"
+#endif
+
+#ifndef _MORKBUILDER_
+# include "morkBuilder.h"
+#endif
+
+#ifndef _MORKCELL_
+# include "morkCell.h"
+#endif
+
+#ifndef _MORKSTORE_
+# include "morkStore.h"
+#endif
+
+#ifndef _MORKTABLE_
+# include "morkTable.h"
+#endif
+
+#ifndef _MORKROW_
+# include "morkRow.h"
+#endif
+
+#ifndef _MORKCELL_
+# include "morkCell.h"
+#endif
+
+#ifndef _MORKATOM_
+# include "morkAtom.h"
+#endif
+
+#ifndef _MORKATOMSPACE_
+# include "morkAtomSpace.h"
+#endif
+
+#ifndef _MORKROWSPACE_
+# include "morkRowSpace.h"
+#endif
+
+// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+
+// ````` ````` ````` ````` `````
+// { ===== begin morkNode interface =====
+
+/*public virtual*/ void morkBuilder::CloseMorkNode(
+ morkEnv* ev) // CloseBuilder() only if open
+{
+ if (this->IsOpenNode()) {
+ this->MarkClosing();
+ this->CloseBuilder(ev);
+ this->MarkShut();
+ }
+}
+
+/*public virtual*/
+morkBuilder::~morkBuilder() // assert CloseBuilder() executed earlier
+{
+ MORK_ASSERT(mBuilder_Store == 0);
+ MORK_ASSERT(mBuilder_Row == 0);
+ MORK_ASSERT(mBuilder_Table == 0);
+ MORK_ASSERT(mBuilder_Cell == 0);
+ MORK_ASSERT(mBuilder_RowSpace == 0);
+ MORK_ASSERT(mBuilder_AtomSpace == 0);
+}
+
+/*public non-poly*/
+morkBuilder::morkBuilder(morkEnv* ev, const morkUsage& inUsage,
+ nsIMdbHeap* ioHeap, morkStream* ioStream,
+ mdb_count inBytesPerParseSegment,
+ nsIMdbHeap* ioSlotHeap, morkStore* ioStore)
+
+ : morkParser(ev, inUsage, ioHeap, ioStream, inBytesPerParseSegment,
+ ioSlotHeap)
+
+ ,
+ mBuilder_Store(0)
+
+ ,
+ mBuilder_Table(0),
+ mBuilder_Row(0),
+ mBuilder_Cell(0)
+
+ ,
+ mBuilder_RowSpace(0),
+ mBuilder_AtomSpace(0)
+
+ ,
+ mBuilder_OidAtomSpace(0),
+ mBuilder_ScopeAtomSpace(0)
+
+ ,
+ mBuilder_PortForm(0),
+ mBuilder_PortRowScope((mork_scope)'r'),
+ mBuilder_PortAtomScope((mork_scope)'v')
+
+ ,
+ mBuilder_TableForm(0),
+ mBuilder_TableRowScope((mork_scope)'r'),
+ mBuilder_TableAtomScope((mork_scope)'v'),
+ mBuilder_TableKind(0)
+
+ ,
+ mBuilder_TablePriority(morkPriority_kLo),
+ mBuilder_TableIsUnique(morkBool_kFalse),
+ mBuilder_TableIsVerbose(morkBool_kFalse),
+ mBuilder_TablePadByte(0)
+
+ ,
+ mBuilder_RowForm(0),
+ mBuilder_RowRowScope((mork_scope)'r'),
+ mBuilder_RowAtomScope((mork_scope)'v')
+
+ ,
+ mBuilder_CellForm(0),
+ mBuilder_CellAtomScope((mork_scope)'v')
+
+ ,
+ mBuilder_DictForm(0),
+ mBuilder_DictAtomScope((mork_scope)'v')
+
+ ,
+ mBuilder_MetaTokenSlot(0)
+
+ ,
+ mBuilder_DoCutRow(morkBool_kFalse),
+ mBuilder_DoCutCell(morkBool_kFalse),
+ mBuilder_CellsVecFill(0) {
+ if (ev->Good()) {
+ if (ioStore) {
+ morkStore::SlotWeakStore(ioStore, ev, &mBuilder_Store);
+ if (ev->Good()) mNode_Derived = morkDerived_kBuilder;
+ } else
+ ev->NilPointerError();
+ }
+}
+
+/*public non-poly*/ void morkBuilder::CloseBuilder(
+ morkEnv* ev) // called by CloseMorkNode();
+{
+ if (this->IsNode()) {
+ mBuilder_Row = 0;
+ mBuilder_Cell = 0;
+ mBuilder_MetaTokenSlot = 0;
+
+ morkTable::SlotStrongTable((morkTable*)0, ev, &mBuilder_Table);
+ morkStore::SlotWeakStore((morkStore*)0, ev, &mBuilder_Store);
+
+ morkRowSpace::SlotStrongRowSpace((morkRowSpace*)0, ev, &mBuilder_RowSpace);
+
+ morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
+ &mBuilder_AtomSpace);
+
+ morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
+ &mBuilder_OidAtomSpace);
+
+ morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
+ &mBuilder_ScopeAtomSpace);
+ this->CloseParser(ev);
+ this->MarkShut();
+ } else
+ this->NonNodeError(ev);
+}
+
+// } ===== end morkNode methods =====
+// ````` ````` ````` ````` `````
+
+/*static*/ void morkBuilder::NonBuilderTypeError(morkEnv* ev) {
+ ev->NewError("non morkBuilder");
+}
+
+/*static*/ void morkBuilder::NilBuilderCellError(morkEnv* ev) {
+ ev->NewError("nil mBuilder_Cell");
+}
+
+/*static*/ void morkBuilder::NilBuilderRowError(morkEnv* ev) {
+ ev->NewError("nil mBuilder_Row");
+}
+
+/*static*/ void morkBuilder::NilBuilderTableError(morkEnv* ev) {
+ ev->NewError("nil mBuilder_Table");
+}
+
+/*static*/ void morkBuilder::NonColumnSpaceScopeError(morkEnv* ev) {
+ ev->NewError("column space != 'c'");
+}
+
+void morkBuilder::LogGlitch(morkEnv* ev, const morkGlitch& inGlitch,
+ const char* inKind) {
+ MORK_USED_2(inGlitch, inKind);
+ ev->NewWarning("parsing glitch");
+}
+
+/*virtual*/ void morkBuilder::MidToYarn(
+ morkEnv* ev,
+ const morkMid& inMid, // typically an alias to concat with strings
+ mdbYarn* outYarn)
+// The parser might ask that some aliases be turned into yarns, so they
+// can be concatenated into longer blobs under some circumstances. This
+// is an alternative to using a long and complex callback for many parts
+// for a single cell value.
+{
+ mBuilder_Store->MidToYarn(ev, inMid, outYarn);
+}
+
+/*virtual*/ void morkBuilder::OnNewPort(morkEnv* ev, const morkPlace& inPlace)
+// mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
+// mp:PortItem ::= mp:Content | mp:Group | OnPortGlitch
+// mp:Content ::= mp:PortRow | mp:Dict | mp:Table | mp:Row
+{
+ MORK_USED_2(ev, inPlace);
+ // mParser_InPort = morkBool_kTrue;
+ mBuilder_PortForm = 0;
+ mBuilder_PortRowScope = (mork_scope)'r';
+ mBuilder_PortAtomScope = (mork_scope)'v';
+}
+
+/*virtual*/ void morkBuilder::OnPortGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "port");
+}
+
+/*virtual*/ void morkBuilder::OnPortEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Start ::= OnNewPort mp:PortItem* OnPortEnd
+{
+ MORK_USED_2(ev, inSpan);
+ // ev->StubMethodOnlyError();
+ // nothing to do?
+ // mParser_InPort = morkBool_kFalse;
+}
+
+/*virtual*/ void morkBuilder::OnNewGroup(morkEnv* ev, const morkPlace& inPlace,
+ mork_gid inGid) {
+ MORK_USED_1(inPlace);
+ mParser_InGroup = morkBool_kTrue;
+ mork_pos startPos = inPlace.mPlace_Pos;
+
+ morkStore* store = mBuilder_Store;
+ if (store) {
+ if (inGid >= store->mStore_CommitGroupIdentity)
+ store->mStore_CommitGroupIdentity = inGid + 1;
+
+ if (!store->mStore_FirstCommitGroupPos)
+ store->mStore_FirstCommitGroupPos = startPos;
+ else if (!store->mStore_SecondCommitGroupPos)
+ store->mStore_SecondCommitGroupPos = startPos;
+ }
+}
+
+/*virtual*/ void morkBuilder::OnGroupGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "group");
+}
+
+/*virtual*/ void morkBuilder::OnGroupCommitEnd(morkEnv* ev,
+ const morkSpan& inSpan) {
+ MORK_USED_2(ev, inSpan);
+ // mParser_InGroup = morkBool_kFalse;
+ // ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void morkBuilder::OnGroupAbortEnd(morkEnv* ev,
+ const morkSpan& inSpan) {
+ MORK_USED_1(inSpan);
+ // mParser_InGroup = morkBool_kFalse;
+ ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void morkBuilder::OnNewPortRow(morkEnv* ev,
+ const morkPlace& inPlace,
+ const morkMid& inMid,
+ mork_change inChange) {
+ MORK_USED_3(inMid, inPlace, inChange);
+ // mParser_InPortRow = morkBool_kTrue;
+ ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void morkBuilder::OnPortRowGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "port row");
+}
+
+/*virtual*/ void morkBuilder::OnPortRowEnd(morkEnv* ev,
+ const morkSpan& inSpan) {
+ MORK_USED_1(inSpan);
+ // mParser_InPortRow = morkBool_kFalse;
+ ev->StubMethodOnlyError();
+}
+
+/*virtual*/ void morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
+ const morkMid& inMid,
+ mork_bool inCutAllRows)
+// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
+// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
+// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
+// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
+// mp:MetaItem ::= mp:Cell | OnMetaGlitch
+{
+ MORK_USED_1(inPlace);
+ // mParser_InTable = morkBool_kTrue;
+ mBuilder_TableForm = mBuilder_PortForm;
+ mBuilder_TableRowScope = mBuilder_PortRowScope;
+ mBuilder_TableAtomScope = mBuilder_PortAtomScope;
+ mBuilder_TableKind = morkStore_kNoneToken;
+
+ mBuilder_TablePriority = morkPriority_kLo;
+ mBuilder_TableIsUnique = morkBool_kFalse;
+ mBuilder_TableIsVerbose = morkBool_kFalse;
+
+ morkTable* table = mBuilder_Store->MidToTable(ev, inMid);
+ morkTable::SlotStrongTable(table, ev, &mBuilder_Table);
+ if (table) {
+ if (table->mTable_RowSpace)
+ mBuilder_TableRowScope = table->mTable_RowSpace->SpaceScope();
+
+ if (inCutAllRows) table->CutAllRows(ev);
+ }
+}
+
+/*virtual*/ void morkBuilder::OnTableGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "table");
+}
+
+/*virtual*/ void morkBuilder::OnTableEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
+{
+ MORK_USED_1(inSpan);
+ // mParser_InTable = morkBool_kFalse;
+ if (mBuilder_Table) {
+ mBuilder_Table->mTable_Priority = mBuilder_TablePriority;
+
+ if (mBuilder_TableIsUnique) mBuilder_Table->SetTableUnique();
+
+ if (mBuilder_TableIsVerbose) mBuilder_Table->SetTableVerbose();
+
+ morkTable::SlotStrongTable((morkTable*)0, ev, &mBuilder_Table);
+ } else
+ this->NilBuilderTableError(ev);
+
+ mBuilder_Row = 0;
+ mBuilder_Cell = 0;
+
+ mBuilder_TablePriority = morkPriority_kLo;
+ mBuilder_TableIsUnique = morkBool_kFalse;
+ mBuilder_TableIsVerbose = morkBool_kFalse;
+
+ if (mBuilder_TableKind == morkStore_kNoneToken)
+ ev->NewError("missing table kind");
+
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope = mBuilder_TableAtomScope =
+ mBuilder_PortAtomScope;
+
+ mBuilder_DoCutCell = morkBool_kFalse;
+ mBuilder_DoCutRow = morkBool_kFalse;
+}
+
+/*virtual*/ void morkBuilder::OnNewMeta(morkEnv* ev, const morkPlace& inPlace)
+// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
+// mp:MetaItem ::= mp:Cell | OnMetaGlitch
+// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_2(ev, inPlace);
+ // mParser_InMeta = morkBool_kTrue;
+}
+
+/*virtual*/ void morkBuilder::OnMetaGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "meta");
+}
+
+/*virtual*/ void morkBuilder::OnMetaEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Meta ::= OnNewMeta mp:MetaItem* OnMetaEnd
+{
+ MORK_USED_2(ev, inSpan);
+ // mParser_InMeta = morkBool_kFalse;
+}
+
+/*virtual*/ void morkBuilder::OnMinusRow(morkEnv* ev) {
+ MORK_USED_1(ev);
+ mBuilder_DoCutRow = morkBool_kTrue;
+}
+
+/*virtual*/ void morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
+ const morkMid& inMid,
+ mork_bool inCutAllCols)
+// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
+// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
+// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
+// mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
+// mp:RowItem ::= mp:Cell | mp:Meta | OnRowGlitch
+// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inPlace);
+ // mParser_InRow = morkBool_kTrue;
+
+ mBuilder_CellForm = mBuilder_RowForm = mBuilder_TableForm;
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope = mBuilder_TableAtomScope;
+ mBuilder_RowRowScope = mBuilder_TableRowScope;
+ morkStore* store = mBuilder_Store;
+
+ if (!inMid.mMid_Buf && !inMid.mMid_Oid.mOid_Scope) {
+ morkMid mid(inMid);
+ mid.mMid_Oid.mOid_Scope = mBuilder_RowRowScope;
+ mBuilder_Row = store->MidToRow(ev, mid);
+ } else {
+ mBuilder_Row = store->MidToRow(ev, inMid);
+ }
+ morkRow* row = mBuilder_Row;
+ if (row && inCutAllCols) {
+ row->CutAllColumns(ev);
+ }
+
+ morkTable* table = mBuilder_Table;
+ if (table) {
+ if (row) {
+ if (mParser_InMeta) {
+ morkRow* metaRow = table->mTable_MetaRow;
+ if (!metaRow) {
+ table->mTable_MetaRow = row;
+ table->mTable_MetaRowOid = row->mRow_Oid;
+ row->AddRowGcUse(ev);
+ } else if (metaRow != row) // not identical?
+ ev->NewError("duplicate table meta row");
+ } else {
+ if (mBuilder_DoCutRow)
+ table->CutRow(ev, row);
+ else
+ table->AddRow(ev, row);
+ }
+ }
+ }
+ // else // it is now okay to have rows outside a table:
+ // this->NilBuilderTableError(ev);
+
+ mBuilder_DoCutRow = morkBool_kFalse;
+}
+
+/*virtual*/ void morkBuilder::OnRowPos(morkEnv* ev, mork_pos inRowPos) {
+ if (mBuilder_Row && mBuilder_Table && !mParser_InMeta) {
+ mork_pos hintFromPos = 0; // best hint when we don't know position
+ mBuilder_Table->MoveRow(ev, mBuilder_Row, hintFromPos, inRowPos);
+ }
+}
+
+/*virtual*/ void morkBuilder::OnRowGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "row");
+}
+
+void morkBuilder::FlushBuilderCells(morkEnv* ev) {
+ if (mBuilder_Row) {
+ morkPool* pool = mBuilder_Store->StorePool();
+ morkCell* cells = mBuilder_CellsVec;
+ mork_fill fill = mBuilder_CellsVecFill;
+ mBuilder_Row->TakeCells(ev, cells, fill, mBuilder_Store);
+
+ morkCell* end = cells + fill;
+ --cells; // prepare for preincrement
+ while (++cells < end) {
+ if (cells->mCell_Atom) cells->SetAtom(ev, (morkAtom*)0, pool);
+ }
+ mBuilder_CellsVecFill = 0;
+ } else
+ this->NilBuilderRowError(ev);
+}
+
+/*virtual*/ void morkBuilder::OnRowEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Row ::= OnMinusRow? OnNewRow mp:RowItem* OnRowEnd
+{
+ MORK_USED_1(inSpan);
+ // mParser_InRow = morkBool_kFalse;
+ if (mBuilder_Row) {
+ this->FlushBuilderCells(ev);
+ } else
+ this->NilBuilderRowError(ev);
+
+ mBuilder_Row = 0;
+ mBuilder_Cell = 0;
+
+ mBuilder_DoCutCell = morkBool_kFalse;
+ mBuilder_DoCutRow = morkBool_kFalse;
+}
+
+/*virtual*/ void morkBuilder::OnNewDict(morkEnv* ev, const morkPlace& inPlace)
+// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
+// mp:DictItem ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
+{
+ MORK_USED_2(ev, inPlace);
+ // mParser_InDict = morkBool_kTrue;
+
+ mBuilder_CellForm = mBuilder_DictForm = mBuilder_PortForm;
+ mBuilder_CellAtomScope = mBuilder_DictAtomScope = mBuilder_PortAtomScope;
+}
+
+/*virtual*/ void morkBuilder::OnDictGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "dict");
+}
+
+/*virtual*/ void morkBuilder::OnDictEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
+{
+ MORK_USED_2(ev, inSpan);
+ // mParser_InDict = morkBool_kFalse;
+
+ mBuilder_DictForm = 0;
+ mBuilder_DictAtomScope = 0;
+}
+
+/*virtual*/ void morkBuilder::OnAlias(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid) {
+ MORK_USED_1(inSpan);
+ if (mParser_InDict) {
+ morkMid mid = inMid; // local copy for modification
+ mid.mMid_Oid.mOid_Scope = mBuilder_DictAtomScope;
+ mBuilder_Store->AddAlias(ev, mid, mBuilder_DictForm);
+ } else
+ ev->NewError("alias not in dict");
+}
+
+/*virtual*/ void morkBuilder::OnAliasGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "alias");
+}
+
+morkCell* morkBuilder::AddBuilderCell(morkEnv* ev, const morkMid& inMid,
+ mork_change inChange) {
+ morkCell* outCell = 0;
+ mork_column column = inMid.mMid_Oid.mOid_Id;
+
+ if (ev->Good()) {
+ if (mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize)
+ this->FlushBuilderCells(ev);
+ if (ev->Good()) {
+ if (mBuilder_CellsVecFill < morkBuilder_kCellsVecSize) {
+ mork_fill indx = mBuilder_CellsVecFill++;
+ outCell = mBuilder_CellsVec + indx;
+ outCell->SetColumnAndChange(column, inChange);
+ outCell->mCell_Atom = 0;
+ } else
+ ev->NewError("out of builder cells");
+ }
+ }
+ return outCell;
+}
+
+/*virtual*/ void morkBuilder::OnMinusCell(morkEnv* ev) {
+ MORK_USED_1(ev);
+ mBuilder_DoCutCell = morkBool_kTrue;
+}
+
+/*virtual*/ void morkBuilder::OnNewCell(morkEnv* ev, const morkPlace& inPlace,
+ const morkMid* inMid,
+ const morkBuf* inBuf)
+// Exactly one of inMid and inBuf is nil, and the other is non-nil.
+// When hex ID syntax is used for a column, then inMid is not nil, and
+// when a naked string names a column, then inBuf is not nil.
+
+// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inPlace);
+ // mParser_InCell = morkBool_kTrue;
+
+ mork_change cellChange =
+ (mBuilder_DoCutCell) ? morkChange_kCut : morkChange_kAdd;
+
+ mBuilder_DoCutCell = morkBool_kFalse;
+
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope;
+
+ mBuilder_Cell = 0; // nil until determined for a row
+ morkStore* store = mBuilder_Store;
+ mork_scope scope = morkStore_kColumnSpaceScope;
+ morkMid tempMid; // space for local and modifiable cell mid
+ morkMid* cellMid = &tempMid; // default to local if inMid==0
+
+ if (inMid) // mid parameter is actually provided?
+ {
+ *cellMid = *inMid; // bitwise copy for modifiable local mid
+
+ if (!cellMid->mMid_Oid.mOid_Scope) {
+ if (cellMid->mMid_Buf) {
+ scope = store->BufToToken(ev, cellMid->mMid_Buf);
+ cellMid->mMid_Buf = 0; // don't do scope lookup again
+ ev->NewWarning("column mids need column scope");
+ }
+ cellMid->mMid_Oid.mOid_Scope = scope;
+ }
+ } else if (inBuf) // buf points to naked column string name?
+ {
+ cellMid->ClearMid();
+ cellMid->mMid_Oid.mOid_Id = store->BufToToken(ev, inBuf);
+ cellMid->mMid_Oid.mOid_Scope = scope; // kColumnSpaceScope
+ } else
+ ev->NilPointerError(); // either inMid or inBuf must be non-nil
+
+ mork_column column = cellMid->mMid_Oid.mOid_Id;
+
+ if (mBuilder_Row && ev->Good()) // this cell must be inside a row
+ {
+ // mBuilder_Cell = this->AddBuilderCell(ev, *cellMid, cellChange);
+
+ if (mBuilder_CellsVecFill >= morkBuilder_kCellsVecSize)
+ this->FlushBuilderCells(ev);
+ if (ev->Good()) {
+ if (mBuilder_CellsVecFill < morkBuilder_kCellsVecSize) {
+ mork_fill ix = mBuilder_CellsVecFill++;
+ morkCell* cell = mBuilder_CellsVec + ix;
+ cell->SetColumnAndChange(column, cellChange);
+
+ cell->mCell_Atom = 0;
+ mBuilder_Cell = cell;
+ } else
+ ev->NewError("out of builder cells");
+ }
+ }
+
+ else if (mParser_InMeta && ev->Good()) // cell is in metainfo structure?
+ {
+ if (scope == morkStore_kColumnSpaceScope) {
+ if (mParser_InTable) // metainfo for table?
+ {
+ if (column == morkStore_kKindColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_TableKind;
+ else if (column == morkStore_kStatusColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_TableStatus;
+ else if (column == morkStore_kRowScopeColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_TableRowScope;
+ else if (column == morkStore_kAtomScopeColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_TableAtomScope;
+ else if (column == morkStore_kFormColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_TableForm;
+ } else if (mParser_InDict) // metainfo for dict?
+ {
+ if (column == morkStore_kAtomScopeColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_DictAtomScope;
+ else if (column == morkStore_kFormColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_DictForm;
+ } else if (mParser_InRow) // metainfo for row?
+ {
+ if (column == morkStore_kAtomScopeColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_RowAtomScope;
+ else if (column == morkStore_kRowScopeColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_RowRowScope;
+ else if (column == morkStore_kFormColumn)
+ mBuilder_MetaTokenSlot = &mBuilder_RowForm;
+ }
+ } else
+ ev->NewWarning("expected column scope");
+ }
+}
+
+/*virtual*/ void morkBuilder::OnCellGlitch(morkEnv* ev,
+ const morkGlitch& inGlitch) {
+ this->LogGlitch(ev, inGlitch, "cell");
+}
+
+/*virtual*/ void morkBuilder::OnCellForm(morkEnv* ev,
+ mork_cscode inCharsetFormat) {
+ morkCell* cell = mBuilder_Cell;
+ if (cell) {
+ mBuilder_CellForm = inCharsetFormat;
+ } else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void morkBuilder::OnCellEnd(morkEnv* ev, const morkSpan& inSpan)
+// mp:Cell ::= OnMinusCell? OnNewCell mp:CellItem? OnCellEnd
+{
+ MORK_USED_2(ev, inSpan);
+ // mParser_InCell = morkBool_kFalse;
+
+ mBuilder_MetaTokenSlot = 0;
+ mBuilder_CellAtomScope = mBuilder_RowAtomScope;
+}
+
+/*virtual*/ void morkBuilder::OnValue(morkEnv* ev, const morkSpan& inSpan,
+ const morkBuf& inBuf)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+ if (cell) {
+ mdbYarn yarn;
+ yarn.mYarn_Buf = inBuf.mBuf_Body;
+ yarn.mYarn_Fill = yarn.mYarn_Size = inBuf.mBuf_Fill;
+ yarn.mYarn_More = 0;
+ yarn.mYarn_Form = mBuilder_CellForm;
+ yarn.mYarn_Grow = 0;
+ morkAtom* atom = store->YarnToAtom(ev, &yarn, true /* create */);
+ cell->SetAtom(ev, atom, store->StorePool());
+ } else if (mParser_InMeta) {
+ mork_token* metaSlot = mBuilder_MetaTokenSlot;
+ if (metaSlot) {
+ if (metaSlot == &mBuilder_TableStatus) // table status?
+ {
+ if (mParser_InTable && mBuilder_Table) {
+ const char* body = (const char*)inBuf.mBuf_Body;
+ mork_fill bufFill = inBuf.mBuf_Fill;
+ if (body && bufFill) {
+ const char* bodyEnd = body + bufFill;
+ while (body < bodyEnd) {
+ int c = *body++;
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ mBuilder_TablePriority = (mork_priority)(c - '0');
+ break;
+
+ case 'u':
+ case 'U':
+ mBuilder_TableIsUnique = morkBool_kTrue;
+ break;
+
+ case 'v':
+ case 'V':
+ mBuilder_TableIsVerbose = morkBool_kTrue;
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ mork_token token = store->BufToToken(ev, &inBuf);
+ if (token) {
+ *metaSlot = token;
+ if (metaSlot == &mBuilder_TableKind) // table kind?
+ {
+ if (mParser_InTable && mBuilder_Table)
+ mBuilder_Table->mTable_Kind = token;
+ }
+ }
+ }
+ }
+ } else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void morkBuilder::OnValueMid(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+
+ morkMid valMid; // local mid for modifications
+ mdbOid* valOid = &valMid.mMid_Oid; // ref to oid inside mid
+ *valOid = inMid.mMid_Oid; // bitwise copy inMid's oid
+
+ if (inMid.mMid_Buf) {
+ if (!valOid->mOid_Scope) store->MidToOid(ev, inMid, valOid);
+ } else if (!valOid->mOid_Scope)
+ valOid->mOid_Scope = mBuilder_CellAtomScope;
+
+ if (cell) {
+ morkBookAtom* atom = store->MidToAtom(ev, valMid);
+ if (atom)
+ cell->SetAtom(ev, atom, store->StorePool());
+ else
+ ev->NewError("undefined cell value alias");
+ } else if (mParser_InMeta) {
+ mork_token* metaSlot = mBuilder_MetaTokenSlot;
+ if (metaSlot) {
+ mork_scope valScope = valOid->mOid_Scope;
+ if (!valScope || valScope == morkStore_kColumnSpaceScope) {
+ if (ev->Good() && valMid.HasSomeId()) {
+ *metaSlot = valOid->mOid_Id;
+ if (metaSlot == &mBuilder_TableKind) // table kind?
+ {
+ if (mParser_InTable && mBuilder_Table) {
+ mBuilder_Table->mTable_Kind = valOid->mOid_Id;
+ } else
+ ev->NewWarning("mBuilder_TableKind not in table");
+ } else if (metaSlot == &mBuilder_TableStatus) // table status?
+ {
+ if (mParser_InTable && mBuilder_Table) {
+ // $$ what here??
+ } else
+ ev->NewWarning("mBuilder_TableStatus not in table");
+ }
+ }
+ } else
+ this->NonColumnSpaceScopeError(ev);
+ }
+ } else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void morkBuilder::OnRowMid(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+ if (cell) {
+ mdbOid rowOid = inMid.mMid_Oid;
+ if (inMid.mMid_Buf) {
+ if (!rowOid.mOid_Scope) store->MidToOid(ev, inMid, &rowOid);
+ } else if (!rowOid.mOid_Scope)
+ rowOid.mOid_Scope = mBuilder_RowRowScope;
+
+ if (ev->Good()) {
+ morkPool* pool = store->StorePool();
+ morkAtom* atom = pool->NewRowOidAtom(ev, rowOid, &store->mStore_Zone);
+ if (atom) {
+ cell->SetAtom(ev, atom, pool);
+ morkRow* row = store->OidToRow(ev, &rowOid);
+ if (row) // found or created such a row?
+ row->AddRowGcUse(ev);
+ }
+ }
+ } else
+ this->NilBuilderCellError(ev);
+}
+
+/*virtual*/ void morkBuilder::OnTableMid(morkEnv* ev, const morkSpan& inSpan,
+ const morkMid& inMid)
+// mp:CellItem ::= mp:Slot | OnCellForm | OnCellGlitch
+// mp:Slot ::= OnValue | OnValueMid | OnRowMid | OnTableMid
+{
+ MORK_USED_1(inSpan);
+ morkStore* store = mBuilder_Store;
+ morkCell* cell = mBuilder_Cell;
+ if (cell) {
+ mdbOid tableOid = inMid.mMid_Oid;
+ if (inMid.mMid_Buf) {
+ if (!tableOid.mOid_Scope) store->MidToOid(ev, inMid, &tableOid);
+ } else if (!tableOid.mOid_Scope)
+ tableOid.mOid_Scope = mBuilder_RowRowScope;
+
+ if (ev->Good()) {
+ morkPool* pool = store->StorePool();
+ morkAtom* atom = pool->NewTableOidAtom(ev, tableOid, &store->mStore_Zone);
+ if (atom) {
+ cell->SetAtom(ev, atom, pool);
+ morkTable* table = store->OidToTable(ev, &tableOid,
+ /*optionalMetaRowOid*/ (mdbOid*)0);
+ if (table) // found or created such a table?
+ table->AddTableGcUse(ev);
+ }
+ }
+ } else
+ this->NilBuilderCellError(ev);
+}
+
+// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789