latest mork drop, fix ref counting bug, add meta table info

This commit is contained in:
bienvenu%netscape.com 1999-03-30 05:43:09 +00:00
parent af224c9bc6
commit 0484e4a350
60 changed files with 2074 additions and 629 deletions

View File

@ -690,6 +690,88 @@ public:
extern "C" nsIMdbFactory* MakeMdbFactory();
/*| nsIMdbFile: abstract file interface resembling the original morkFile
**| abstract interface (which was in turn modeled on the file interface
**| from public domain IronDoc). The design of this file interface is
**| complicated by the fact that some DB's will not find this interface
**| adequate for all runtime requirements (even though this file API is
**| enough to implement text-based DB's like Mork). For this reason,
**| more methods have been added to let a DB library force the file to
**| become closed so the DB can reopen the file in some other manner.
**| Folks are encouraged to suggest ways to tune this interface to suit
**| DB's that cannot manage to pull their maneuvers even given this API.
**|
**|| Tell: get the current i/o position in file
**|
**|| Seek: change the current i/o position in file
**|
**|| Eof: return file's total length in bytes
**|
**|| Read: input inSize bytes into outBuf, returning actual transfer size
**|
**|| Get: read starting at specific file offset (e.g. Seek(); Read();)
**|
**|| Write: output inSize bytes from inBuf, returning actual transfer size
**|
**|| Put: write starting at specific file offset (e.g. Seek(); Write();)
**|
**|| Flush: if written bytes are buffered, push them to final destination
**|
**|| Path: get file path in some string representation. This is intended
**| either to support the display of file name in a user presentation, or
**| to support the closing and reopening of the file when the DB needs more
**| exotic file access than is presented by the nsIMdbFile interface.
**|
**|| Steal: tell this file to close any associated i/o stream in the file
**| system, because the file ioThief intends to reopen the file in order
**| to provide the MDB implementation with more exotic file access than is
**| offered by the nsIMdbFile alone. Presumably the thief knows enough
**| from Path() in order to know which file to reopen. If Steal() is
**| successful, this file should probably delegate all future calls to
**| the nsIMdbFile interface down to the thief files, so that even after
**| the file has been stolen, it can still be read, written, or forcibly
**| closed (by a call to CloseMdbObject()).
**|
**|| Thief: acquire and return thief passed to an earlier call to Steal().
|*/
class nsIMdbFile : public nsIMdbObject { // minimal file interface
public:
// { ===== begin nsIMdbFile methods =====
// { ----- begin pos methods -----
virtual mdb_err Tell(nsIMdbEnv* ev, mdb_pos* outPos) const = 0;
virtual mdb_err Seek(nsIMdbEnv* ev, mdb_pos inPos) = 0;
virtual mdb_err Eof(nsIMdbEnv* ev, mdb_pos* outPos) const = 0;
// } ----- end pos methods -----
// { ----- begin read methods -----
virtual mdb_err Read(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
mdb_size* outActualSize) = 0;
virtual mdb_err Get(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
mdb_pos inPos, mdb_size* outActualSize) = 0;
// } ----- end read methods -----
// { ----- begin write methods -----
virtual mdb_err Write(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
mdb_size* outActualSize) = 0;
virtual mdb_err Put(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
mdb_pos inPos, mdb_size* outActualSize) = 0;
virtual mdb_err Flush(nsIMdbEnv* ev) = 0;
// } ----- end attribute methods -----
// { ----- begin path methods -----
virtual mdb_err Path(nsIMdbEnv* ev, mdbYarn* outFilePath) = 0;
// } ----- end path methods -----
// { ----- begin replacement methods -----
virtual mdb_err Steal(nsIMdbEnv* ev, nsIMdbFile* ioThief) = 0;
virtual mdb_err Thief(nsIMdbEnv* ev, nsIMdbFile** acqThief) = 0;
// } ----- end replacement methods -----
// } ===== end nsIMdbFile methods =====
};
/*| nsIMdbPort: a readonly interface to a specific database file. The mutable
**| nsIMdbStore interface is a subclass that includes writing behavior, but
**| most of the needed db methods appear in the readonly nsIMdbPort interface.
@ -995,6 +1077,15 @@ public:
mdb_scope inRowScope, // row scope for row ids
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) = 0; // acquire scoped collection of rows
virtual mdb_err NewTableWithOid( // make one new table of specific type
nsIMdbEnv* ev, // context
const mdbOid* inOid, // caller assigned oid
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) = 0; // acquire scoped collection of rows
// } ----- end table methods -----
@ -1333,7 +1424,7 @@ public:
**| complain not at all. Cutting a row from a table only does something when
**| the row was actually a member, and otherwise does nothing silently.
**|
**|| row ref count: one can query the number of tables (and or cells)
**|| row ref count: one can query the number of tables (and/or cells)
**| containing a row as a member or a child.
**|
**|| row content: one can access or modify the cell content in a table's row
@ -1355,11 +1446,38 @@ public:
// { ===== begin nsIMdbTable methods =====
// { ----- begin attribute methods -----
// { ----- begin meta attribute methods -----
virtual mdb_err GetTableKind(nsIMdbEnv* ev, mdb_kind* outTableKind) = 0;
virtual mdb_err GetRowScope(nsIMdbEnv* ev, mdb_scope* outRowScope) = 0;
// } ----- end attribute methods -----
virtual mdb_err GetMetaRow(
nsIMdbEnv* ev, // context
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mdbOid* outOid, // output meta row oid, can be nil to suppress output
nsIMdbRow** acqRow) = 0; // acquire table's unique singleton meta row
// The purpose of a meta row is to support the persistent recording of
// meta info about a table as cells put into the distinguished meta row.
// Each table has exactly one meta row, which is not considered a member
// of the collection of rows inside the table. The only way to tell
// whether a row is a meta row is by the fact that it is returned by this
// GetMetaRow() method from some table. Otherwise nothing distinguishes
// a meta row from any other row. A meta row can be used anyplace that
// any other row can be used, and can even be put into other tables (or
// the same table) as a table member, if this is useful for some reason.
// The first attempt to access a table's meta row using GetMetaRow() will
// cause the meta row to be created if it did not already exist. When the
// meta row is created, it will have the row oid that was previously
// requested for this table's meta row; or if no oid was ever explicitly
// specified for this meta row, then a unique oid will be generated in
// the row scope named "metaScope" (so obviously MDB clients should not
// manually allocate any row IDs from that special meta scope namespace).
// The meta row oid can be specified either when the table is created, or
// else the first time that GetMetaRow() is called, by passing a non-nil
// pointer to an oid for parameter inOptionalMetaRowOid. The meta row's
// actual oid is returned in outOid (if this is a non-nil pointer), and
// it will be different from inOptionalMetaRowOid when the meta row was
// already given a different oid earlier.
// } ----- end meta attribute methods -----
// { ----- begin cursor methods -----
virtual mdb_err GetTableRowCursor( // make a cursor, starting iteration at inRowPos
@ -1374,7 +1492,10 @@ public:
mdb_pos inRowPos, // zero-based ordinal position of row in table
mdbOid* outOid) = 0; // row oid at the specified position
// Note that HasRow() performs the inverse oid->pos mapping
virtual mdb_err RowToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
// } ----- end row position methods -----
// { ----- begin oid set methods -----
@ -1383,6 +1504,11 @@ public:
const mdbOid* inOid) = 0; // row to ensure membership in table
virtual mdb_err HasOid( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_bool* outHasOid) = 0; // whether inOid is a member row
virtual mdb_err OidToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
@ -1395,7 +1521,7 @@ public:
// { ----- begin row set methods -----
virtual mdb_err NewRow( // create a new row instance in table
nsIMdbEnv* ev, // context
mdbOid* ioOid, // please use zero (unbound) rowId for db-assigned IDs
mdbOid* ioOid, // please use minus one (unbound) rowId for db-assigned IDs
nsIMdbRow** acqRow) = 0; // create new row
virtual mdb_err AddRow( // make sure the row with inOid is a table member
@ -1405,7 +1531,7 @@ public:
virtual mdb_err HasRow( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
mdb_bool* outHasRow) = 0; // whether row is a table member
virtual mdb_err CutRow( // make sure the row with inOid is not a member
nsIMdbEnv* ev, // context

View File

@ -131,6 +131,12 @@ public: // setup
public: // other space methods
// void ReserveColumnAidCount(mork_count inCount)
// {
// mAtomSpace_HighUnderId = morkAtomSpace_kMinUnderId + inCount;
// mAtomSpace_HighOverId = morkAtomSpace_kMinOverId + inCount;
// }
mork_num CutAllAtoms(morkEnv* ev, morkPool* ioPool);
// CutAllAtoms() puts all the atoms back in the pool.

View File

@ -123,32 +123,25 @@ morkBuilder::morkBuilder(morkEnv* ev,
, mBuilder_OidAtomSpace( 0 )
, mBuilder_ScopeAtomSpace( 0 )
, mBuilder_iso_8859_1( 0 )
, mBuilder_r( (mork_scope) 'r' )
, mBuilder_a( (mork_scope) 'a' )
, mBuilder_t( (mork_scope) 't' )
, mBuilder_MorkNoneToken( 0 )
, mBuilder_PortForm( 0 )
, mBuilder_PortRowScope( (mork_scope) 'r' )
, mBuilder_PortAtomScope( (mork_scope) 'a' )
, mBuilder_PortAtomScope( (mork_scope) 'v' )
, mBuilder_TableForm( 0 )
, mBuilder_TableRowScope( (mork_scope) 'r' )
, mBuilder_TableAtomScope( (mork_scope) 'a' )
, mBuilder_TableAtomScope( (mork_scope) 'v' )
, mBuilder_TableKind( 0 )
, mBuilder_RowForm( 0 )
, mBuilder_RowRowScope( (mork_scope) 'r' )
, mBuilder_RowAtomScope( (mork_scope) 'a' )
, mBuilder_RowAtomScope( (mork_scope) 'v' )
, mBuilder_CellForm( 0 )
, mBuilder_CellAtomScope( (mork_scope) 'a' )
, mBuilder_CellAtomScope( (mork_scope) 'v' )
, mBuilder_DictForm( 0 )
, mBuilder_DictAtomScope( (mork_scope) 'a' )
, mBuilder_DictAtomScope( (mork_scope) 'v' )
, mBuilder_MetaTokenSlot( 0 )
@ -160,7 +153,6 @@ morkBuilder::morkBuilder(morkEnv* ev,
{
if ( ioStore )
{
mBuilder_MorkNoneToken = ioStore->mStore_MorkNoneToken;
morkStore::SlotWeakStore(ioStore, ev, &mBuilder_Store);
if ( ev->Good() )
mNode_Derived = morkDerived_kBuilder;
@ -267,7 +259,7 @@ morkBuilder::OnNewPort(morkEnv* ev, const morkPlace& inPlace)
// mParser_InPort = morkBool_kTrue;
mBuilder_PortForm = 0;
mBuilder_PortRowScope = (mork_scope) 'r';
mBuilder_PortAtomScope = (mork_scope) 'a';
mBuilder_PortAtomScope = (mork_scope) 'v';
}
/*virtual*/ void
@ -337,7 +329,8 @@ morkBuilder::OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan)
morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_change inChange)
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:Meta | OnTableGlitch
// 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
{
@ -345,7 +338,7 @@ morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
mBuilder_TableForm = mBuilder_PortForm;
mBuilder_TableRowScope = mBuilder_PortRowScope;
mBuilder_TableAtomScope = mBuilder_PortAtomScope;
mBuilder_TableKind = mBuilder_MorkNoneToken;
mBuilder_TableKind = morkStore_kNoneToken;
morkTable* table = mBuilder_Store->MidToTable(ev, inMid);
morkTable::SlotStrongTable(table, ev, &mBuilder_Table);
@ -372,7 +365,7 @@ morkBuilder::OnTableEnd(morkEnv* ev, const morkSpan& inSpan)
mBuilder_Row = 0;
mBuilder_Cell = 0;
if ( mBuilder_TableKind == mBuilder_MorkNoneToken )
if ( mBuilder_TableKind == morkStore_kNoneToken )
ev->NewError("missing table kind");
mBuilder_CellAtomScope = mBuilder_RowAtomScope =
@ -407,6 +400,9 @@ morkBuilder::OnMetaEnd(morkEnv* ev, const morkSpan& inSpan)
/*virtual*/ void
morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_change inChange)
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
// mp:Row ::= OnNewRow mp:RowItem* OnRowEnd
// mp:RowItem ::= mp:Cell | mp:Meta | OnRowGlitch
// mp:Cell ::= OnNewCell mp:CellItem? OnCellEnd
@ -432,8 +428,24 @@ morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
mBuilder_Row = store->MidToRow(ev, inMid);
}
if ( mBuilder_Row )
mBuilder_Table->AddRow(ev, mBuilder_Row);
morkRow* row = mBuilder_Row;
if ( row )
{
morkTable* table = mBuilder_Table;
if ( mParser_InMeta )
{
if ( !table->mTable_MetaRow )
{
table->mTable_MetaRow = row;
table->mTable_MetaRowOid = row->mRow_Oid;
row->AddTableUse(ev);
}
else
ev->NewError("duplicate table meta row");
}
else
table->AddRow(ev, row);
}
}
else
this->NilBuilderTableError(ev);
@ -612,29 +624,29 @@ morkBuilder::OnNewCell(morkEnv* ev, const morkPlace& inPlace,
{
if ( mParser_InTable ) // metainfo for table?
{
if ( column == store->mStore_TableKindToken )
if ( column == morkStore_kKindColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableKind;
else if ( column == store->mStore_RowScopeToken )
else if ( column == morkStore_kRowScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableRowScope;
else if ( column == store->mStore_AtomScopeToken )
else if ( column == morkStore_kAtomScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableAtomScope;
else if ( column == store->mStore_CharsetToken )
else if ( column == morkStore_kFormColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableForm;
}
else if ( mParser_InDict ) // metainfo for dict?
{
if ( column == store->mStore_AtomScopeToken )
if ( column == morkStore_kAtomScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_DictAtomScope;
else if ( column == store->mStore_CharsetToken )
else if ( column == morkStore_kFormColumn )
mBuilder_MetaTokenSlot = &mBuilder_DictForm;
}
else if ( mParser_InRow ) // metainfo for row?
{
if ( column == store->mStore_AtomScopeToken )
if ( column == morkStore_kAtomScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_RowAtomScope;
else if ( column == store->mStore_RowScopeToken )
else if ( column == morkStore_kRowScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_RowRowScope;
else if ( column == store->mStore_CharsetToken )
else if ( column == morkStore_kFormColumn )
mBuilder_MetaTokenSlot = &mBuilder_RowForm;
}
}
@ -856,7 +868,8 @@ morkBuilder::OnTableMid(morkEnv* ev, const morkSpan& inSpan,
if ( atom )
{
cell->SetAtom(ev, atom, pool);
morkTable* table = store->OidToTable(ev, &tableOid);
morkTable* table = store->OidToTable(ev, &tableOid,
/*optionalMetaRowOid*/ (mdbOid*) 0);
if ( table ) // found or created such a table?
table->AddCellUse(ev);
}

View File

@ -127,15 +127,7 @@ protected: // protected morkBuilder members
// scoped object ids for current objects under construction:
mdbOid mBuilder_TableOid; // full oid for current table
mdbOid mBuilder_RowOid; // full oid for current row
// standard tokens that we want to know about for this port:
mork_cscode mBuilder_iso_8859_1; // token for "iso-8859-1"
mork_cscode mBuilder_r; // token for "r"
mork_cscode mBuilder_a; // token for "a"
mork_cscode mBuilder_t; // token for "t"
mork_token mBuilder_MorkNoneToken; // token for "mork:none"
// tokens that become set as the result of meta cells in port rows:
mork_cscode mBuilder_PortForm; // default port charset format
mork_scope mBuilder_PortRowScope; // port row scope

View File

@ -99,14 +99,17 @@ morkCellObject::morkCellObject(morkEnv* ev, const morkUsage& inUsage,
morkStore* store = ioRow->GetRowSpaceStore(ev);
if ( store )
{
morkRowObject* rowObj = ioRow->GetRowObject(ev, store);
morkRowObject* rowObj = ioRow->AcquireRowObject(ev, store);
if ( rowObj )
{
mCellObject_Row = ioRow;
mCellObject_Cell = ioCell;
mCellObject_RowSeed = ioRow->mRow_Seed;
morkRowObject::SlotStrongRowObject(rowObj, ev,
&mCellObject_RowObject);
// morkRowObject::SlotStrongRowObject(rowObj, ev,
// &mCellObject_RowObject);
mCellObject_RowObject = rowObj; // assume control of strong ref
}
if ( ev->Good() )
mNode_Derived = morkDerived_kCellObject;

View File

@ -87,7 +87,7 @@ const mork_u1 morkCh_Type[] = /* derives from public domain Mithril ch table */
0, /* 0x29 ) cannot be kV because needs escape */
morkCh_kV, /* 0x2A * */
morkCh_kV|morkCh_kM, /* 0x2B + */
0, /* 0x2C , */
morkCh_kV, /* 0x2C , */
morkCh_kV|morkCh_kM, /* 0x2D - */
morkCh_kV, /* 0x2E . */
morkCh_kV, /* 0x2F / */

View File

@ -31,8 +31,8 @@
// { %%%%% begin platform defs peculiar to Mork %%%%%
#ifdef XP_MAC
#define MORK_MAC 1
#define MORK_OBSOLETE 1
#define MORK_MAC 1
#endif
#ifdef XP_OS2

View File

@ -113,7 +113,7 @@ morkHandle::CloseHandle(morkEnv* ev) // called by CloseMorkNode();
this->MarkShut();
if ( objDidRefSelf )
this->CutWeakRef(ev);
this->CutWeakRef(ev); // do last, because it might self destroy
}
else
this->NonNodeError(ev);

View File

@ -917,8 +917,18 @@ void morkParser::ReadMeta(morkEnv* ev, int inEndMeta)
this->UnexpectedByteInMetaWarning(ev);
break;
case '[': // maybe table meta row?
if ( mParser_InTable )
this->ReadRow(ev, '[');
else
this->UnexpectedByteInMetaWarning(ev);
break;
default:
this->UnexpectedByteInMetaWarning(ev);
if ( mParser_InTable && morkCh_IsHex(c) )
this->ReadRow(ev, c);
else
this->UnexpectedByteInMetaWarning(ev);
break;
}
}

View File

@ -379,7 +379,8 @@ public: // out virtual morkParser methods, data flow parser to subclass
// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
// mp:DictItem ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:Meta | OnTableGlitch
// 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
// mp:Row ::= OnNewRow mp:RowItem* OnRowEnd

View File

@ -217,7 +217,8 @@ morkPool::AddRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize)
ioRow->mRow_Length = inNewSize;
++ioRow->mRow_Seed;
this->ZapCells(ev, oldCells, fill);
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
return ( ev->Good() && ioRow->mRow_Length >= inNewSize );
@ -230,28 +231,42 @@ morkPool::CutRowCells(morkEnv* ev, morkRow* ioRow,
mork_fill fill = ioRow->mRow_Length;
if ( ev->Good() && fill > inNewSize ) // need fewer cells?
{
morkCell* newCells = this->NewCells(ev, inNewSize);
if ( newCells )
if ( inNewSize ) // want any row cells at all?
{
morkCell* newCells = this->NewCells(ev, inNewSize);
if ( newCells )
{
morkCell* oldCells = ioRow->mRow_Cells;
morkCell* oldEnd = oldCells + fill; // one past all old cells
morkCell* newEnd = oldCells + inNewSize; // copy only kept old cells
while ( oldCells < newEnd )
{
*newCells++ = *oldCells++; // bitwise copy each old cell struct
}
while ( oldCells < oldEnd )
{
if ( oldCells->mCell_Atom ) // need to unref old cell atom?
oldCells->SetAtom(ev, (morkAtom*) 0, this); // unref cell atom
++oldCells;
}
oldCells = ioRow->mRow_Cells;
ioRow->mRow_Cells = newCells;
ioRow->mRow_Length = inNewSize;
++ioRow->mRow_Seed;
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
else // get rid of all row cells
{
morkCell* oldCells = ioRow->mRow_Cells;
morkCell* oldEnd = oldCells + fill; // one past all old cells
morkCell* newEnd = oldCells + inNewSize; // copy only kept old cells
while ( oldCells < newEnd )
{
*newCells++ = *oldCells++; // bitwise copy each old cell struct
}
while ( oldCells < oldEnd )
{
if ( oldCells->mCell_Atom ) // need to unref old cell atom?
oldCells->SetAtom(ev, (morkAtom*) 0, this); // unref cell atom
++oldCells;
}
oldCells = ioRow->mRow_Cells;
ioRow->mRow_Cells = newCells;
ioRow->mRow_Length = inNewSize;
ioRow->mRow_Cells = 0;
ioRow->mRow_Length = 0;
++ioRow->mRow_Seed;
this->ZapCells(ev, oldCells, fill);
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
return ( ev->Good() && ioRow->mRow_Length <= inNewSize );

View File

@ -163,15 +163,18 @@ morkRow::InitRow(morkEnv* ev, const mdbOid* inOid, morkRowSpace* ioSpace,
}
morkRowObject*
morkRow::GetRowObject(morkEnv* ev, morkStore* ioStore)
morkRow::AcquireRowObject(morkEnv* ev, morkStore* ioStore)
{
morkRowObject* ro = mRow_Object;
if ( !ro ) // need new row object?
if ( ro ) // need new row object?
ro->AddStrongRef(ev);
else
{
nsIMdbHeap* heap = ioStore->mPort_Heap;
ro = new (*heap, ev)
morkRowObject(ev, morkUsage::kHeap, heap, this, ioStore);
mRow_Object = ro;
morkRowObject::SlotWeakRowObject(ro, ev, &mRow_Object);
}
return ro;
}
@ -179,10 +182,13 @@ morkRow::GetRowObject(morkEnv* ev, morkStore* ioStore)
nsIMdbRow*
morkRow::AcquireRowHandle(morkEnv* ev, morkStore* ioStore)
{
morkRowObject* object = this->GetRowObject(ev, ioStore);
morkRowObject* object = this->AcquireRowObject(ev, ioStore);
if ( object )
return object->AcquireRowHandle(ev);
{
nsIMdbRow* rowHandle = object->AcquireRowHandle(ev);
object->CutStrongRef(ev);
return rowHandle;
}
return (nsIMdbRow*) 0;
}
@ -387,12 +393,74 @@ morkRow::EmptyAllCells(morkEnv* ev)
}
}
void
morkRow::CutAllColumns(morkEnv* ev)
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
morkPool* pool = store->StorePool();
pool->CutRowCells(ev, this, /*newSize*/ 0);
}
}
void
morkRow::SetRow(morkEnv* ev, const morkRow* inSourceRow)
{
// note inSourceRow might be in another DB, with a different store...
morkStore* store = this->GetRowSpaceStore(ev);
morkStore* srcStore = inSourceRow->GetRowSpaceStore(ev);
if ( store && srcStore )
{
mork_bool sameStore = ( store == srcStore ); // identical stores?
morkPool* pool = store->StorePool();
if ( pool->CutRowCells(ev, this, /*newSize*/ 0) )
{
mork_fill fill = inSourceRow->mRow_Length;
if ( pool->AddRowCells(ev, this, fill) )
{
morkCell* dst = mRow_Cells;
morkCell* dstEnd = dst + mRow_Length;
const morkCell* src = inSourceRow->mRow_Cells;
const morkCell* srcEnd = src + fill;
--dst; --src; // prepare both for preincrement:
while ( ++dst < dstEnd && ++src < srcEnd && ev->Good() )
{
morkAtom* atom = src->mCell_Atom;
mork_column col = src->GetColumn();
if ( sameStore ) // source and dest in same store?
{
dst->SetColumnAndChange(col, morkChange_kAdd);
dst->mCell_Atom = atom;
if ( atom ) // another ref to non-nil atom?
atom->AddCellUse(ev);
}
else // need to dup items from src store in a dest store
{
mork_column dstCol = store->CopyToken(ev, col, srcStore);
if ( dstCol )
{
dst->SetColumnAndChange(dstCol, morkChange_kAdd);
dst->mCell_Atom = store->CopyAtom(ev, atom);
}
}
}
}
}
}
}
void
morkRow::AddRow(morkEnv* ev, const morkRow* inSourceRow)
{
ev->StubMethodOnlyError();
// $$$$$ need to iterate over inSourceRow cells adding them to this row.
// When the atoms are book atoms, we can just incr the use count.
if ( mRow_Length ) // any existing cells we might need to keep?
{
ev->StubMethodOnlyError();
}
else
this->SetRow(ev, inSourceRow); // just exactly duplicate inSourceRow
}
void
@ -444,6 +512,41 @@ morkRow::GetRowSpaceStore(morkEnv* ev) const
return (morkStore*) 0;
}
void morkRow::CutColumn(morkEnv* ev, mdb_column inColumn)
{
mork_pos pos = -1;
morkCell* cell = this->GetCell(ev, inColumn, &pos);
if ( cell )
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
morkPool* pool = store->StorePool();
cell->SetAtom(ev, (morkAtom*) 0, pool);
mork_fill fill = mRow_Length; // should not be zero
MORK_ASSERT(fill);
if ( fill ) // index < fill for last cell exists?
{
mork_fill last = fill - 1; // index of last cell in row
if ( pos < last ) // need to move cells following cut cell?
{
morkCell* lastCell = mRow_Cells + last;
mork_count after = last - pos; // cell count after cut cell
morkCell* next = cell + 1; // next cell after cut cell
MORK_MEMMOVE(cell, next, after * sizeof(morkCell));
lastCell->SetColumnAndChange(0, 0);
lastCell->mCell_Atom = 0;
}
if ( ev->Good() )
pool->CutRowCells(ev, this, fill - 1);
}
}
}
}
void morkRow::AddColumn(morkEnv* ev, mdb_column inColumn,
const mdbYarn* inYarn, morkStore* ioStore)
{
@ -475,7 +578,7 @@ morkRow::NewRowCellCursor(morkEnv* ev, mdb_pos inPos)
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
morkRowObject* rowObj = this->GetRowObject(ev, store);
morkRowObject* rowObj = this->AcquireRowObject(ev, store);
if ( rowObj )
{
nsIMdbHeap* heap = store->mPort_Heap;
@ -492,6 +595,7 @@ morkRow::NewRowCellCursor(morkEnv* ev, mdb_pos inPos)
else
cursor->CutStrongRef(ev);
}
rowObj->CutStrongRef(ev); // always cut ref (cursor has its own)
}
}
}

View File

@ -58,7 +58,7 @@ public: // other row methods
mork_size inLength, morkPool* ioPool);
// if inLength is nonzero, cells will be allocated from ioPool
morkRowObject* GetRowObject(morkEnv* ev, morkStore* ioStore);
morkRowObject* AcquireRowObject(morkEnv* ev, morkStore* ioStore);
nsIMdbRow* AcquireRowHandle(morkEnv* ev, morkStore* ioStore);
nsIMdbCell* AcquireCellHandle(morkEnv* ev, morkCell* ioCell,
mdb_column inColumn, mork_pos inPos);
@ -109,10 +109,14 @@ public: // external row methods
void AddColumn(morkEnv* ev, mdb_column inColumn,
const mdbYarn* inYarn, morkStore* ioStore);
void CutColumn(morkEnv* ev, mdb_column inColumn);
morkRowCellCursor* NewRowCellCursor(morkEnv* ev, mdb_pos inPos);
void EmptyAllCells(morkEnv* ev);
void AddRow(morkEnv* ev, const morkRow* inSourceRow);
void SetRow(morkEnv* ev, const morkRow* inSourceRow);
void CutAllColumns(morkEnv* ev);
void OnZeroTableUse(morkEnv* ev);
// OnZeroTableUse() is called when CutTableUse() returns zero.

View File

@ -103,15 +103,16 @@ morkRowObject::CloseRowObject(morkEnv* ev) // called by CloseMorkNode();
if ( row )
{
MORK_ASSERT(row->mRow_Object == this);
if ( row->mRow_Object == this )
{
morkRowObject::SlotWeakRowObject((morkRowObject*) 0, ev,
&row->mRow_Object);
row->mRow_Object = 0; // just nil this slot -- cut ref down below
morkStore::SlotWeakStore((morkStore*) 0, ev,
&mRowObject_Store);
this->CutWeakRef(ev); // do last, because it might self destroy
}
else
MORK_ASSERT(morkBool_kFalse);
}
}
else

View File

@ -232,7 +232,8 @@ morkRowSpace::FindTableByKind(morkEnv* ev, mork_kind inTableKind)
morkTable*
morkRowSpace::NewTableWithTid(morkEnv* ev, mork_tid inTid,
mork_kind inTableKind)
mork_kind inTableKind,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
@ -242,7 +243,7 @@ morkRowSpace::NewTableWithTid(morkEnv* ev, mork_tid inTid,
nsIMdbHeap* heap = mSpace_Store->mPort_Heap;
morkTable* table = new(*heap, ev)
morkTable(ev, morkUsage::kHeap, heap, mSpace_Store, heap, this,
inTid, inTableKind, mustBeUnique);
inOptionalMetaRowOid, inTid, inTableKind, mustBeUnique);
if ( table )
{
if ( mRowSpace_Tables.AddTable(ev, table) )
@ -263,7 +264,8 @@ morkRowSpace::NewTableWithTid(morkEnv* ev, mork_tid inTid,
morkTable*
morkRowSpace::NewTable(morkEnv* ev, mork_kind inTableKind,
mdb_bool inMustBeUnique)
mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
@ -280,7 +282,7 @@ morkRowSpace::NewTable(morkEnv* ev, mork_kind inTableKind,
nsIMdbHeap* heap = mSpace_Store->mPort_Heap;
morkTable* table = new(*heap, ev)
morkTable(ev, morkUsage::kHeap, heap, mSpace_Store, heap, this,
id, inTableKind, inMustBeUnique);
inOptionalMetaRowOid, id, inTableKind, inMustBeUnique);
if ( table )
{
if ( mRowSpace_Tables.AddTable(ev, table) )

View File

@ -113,10 +113,10 @@ public: // other space methods
// CutAllRows() puts all rows and cells back into the pool.
morkTable* NewTable(morkEnv* ev, mork_kind inTableKind,
mdb_bool inMustBeUnique);
mdb_bool inMustBeUnique, const mdbOid* inOptionalMetaRowOid);
morkTable* NewTableWithTid(morkEnv* ev, mork_tid inTid,
mork_kind inTableKind);
mork_kind inTableKind, const mdbOid* inOptionalMetaRowOid);
morkTable* FindTableByKind(morkEnv* ev, mork_kind inTableKind);
morkTable* FindTableByTid(morkEnv* ev, mork_tid inTid)

View File

@ -217,14 +217,6 @@ morkStore::morkStore(morkEnv* ev, const morkUsage& inUsage,
, mStore_GroundAtomSpace( 0 )
, mStore_GroundColumnSpace( 0 )
, mStore_MorkNoneToken( 0 )
, mStore_CharsetToken( 0 )
, mStore_AtomScopeToken( 0 )
, mStore_RowScopeToken( 0 )
, mStore_TableScopeToken( 0 )
, mStore_ColumnScopeToken( 0 )
, mStore_TableKindToken( 0 )
, mStore_RowSpaces(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioPortHeap)
, mStore_AtomSpaces(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioPortHeap)
, mStore_Pool(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioPortHeap)
@ -233,26 +225,6 @@ morkStore::morkStore(morkEnv* ev, const morkUsage& inUsage,
{
mNode_Derived = morkDerived_kStore;
if ( ev->Good() )
mStore_MorkNoneToken = this->StringToToken(ev, "mork:none");
if ( ev->Good() )
mStore_CharsetToken = this->StringToToken(ev, "charset");
if ( ev->Good() )
mStore_AtomScopeToken = this->StringToToken(ev, "atomScope");
if ( ev->Good() )
mStore_RowScopeToken = this->StringToToken(ev, "rowScope");
if ( ev->Good() )
mStore_TableScopeToken = this->StringToToken(ev, "tableScope");
if ( ev->Good() )
mStore_ColumnScopeToken = this->StringToToken(ev, "columnScope");
if ( ev->Good() )
mStore_TableKindToken = this->StringToToken(ev, "tableKind");
}
}
@ -603,6 +575,20 @@ morkStore::CreateStoreFile(morkEnv* ev,
}
return ev->Good();
}
morkAtom*
morkStore::CopyAtom(morkEnv* ev, const morkAtom* inAtom)
// copy inAtom (from some other store) over to this store
{
morkAtom* outAtom = 0;
if ( inAtom )
{
mdbYarn yarn;
if ( inAtom->AliasYarn(&yarn) )
outAtom = this->YarnToAtom(ev, &yarn);
}
return outAtom;
}
morkAtom*
morkStore::YarnToAtom(morkEnv* ev, const mdbYarn* inYarn)
@ -691,7 +677,7 @@ morkStore::MidToTable(morkEnv* ev, const morkMid& inMid)
{
mdbOid tempOid;
this->MidToOid(ev, inMid, &tempOid);
return this->OidToTable(ev, &tempOid);
return this->OidToTable(ev, &tempOid, /*metarow*/ (mdbOid*) 0);
}
mork_bool
@ -769,10 +755,10 @@ morkStore::TokenToString(morkEnv* ev, mdb_token inToken, mdbYarn* outTokenName)
this->SmallTokenToOneByteYarn(ev, inToken, outTokenName);
}
void
morkStore::SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
const mdbOid* inOid)
{
// void
// morkStore::SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
// const mdbOid* inOid)
// {
// mork_token mStore_MorkNoneToken; // token for "mork:none" // fill=9
// mork_column mStore_CharsetToken; // token for "charset" // fill=7
// mork_column mStore_AtomScopeToken; // token for "atomScope" // fill=9
@ -781,55 +767,55 @@ morkStore::SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
// mork_column mStore_ColumnScopeToken; // token for "columnScope" // fill=11
// mork_kind mStore_TableKindToken; // token for "tableKind" // fill=9
// ---------------------ruler-for-token-length-above---123456789012
if ( inOid->mOid_Scope == morkStore_kColumnSpaceScope && inAtom->IsWeeBook() )
{
const mork_u1* body = ((const morkWeeBookAtom*) inAtom)->mWeeBookAtom_Body;
mork_size size = inAtom->mAtom_Size;
if ( size >= 7 && size <= 11 )
{
if ( size == 9 )
{
if ( *body == 'm' )
{
if ( MORK_MEMCMP(body, "mork:none", 9) == 0 )
mStore_MorkNoneToken = inAtom->mBookAtom_Id;
}
else if ( *body == 'a' )
{
if ( MORK_MEMCMP(body, "atomScope", 9) == 0 )
mStore_AtomScopeToken = inAtom->mBookAtom_Id;
}
else if ( *body == 't' )
{
if ( MORK_MEMCMP(body, "tableKind", 9) == 0 )
mStore_TableKindToken = inAtom->mBookAtom_Id;
}
}
else if ( size == 7 && *body == 'c' )
{
if ( MORK_MEMCMP(body, "charset", 7) == 0 )
mStore_CharsetToken = inAtom->mBookAtom_Id;
}
else if ( size == 8 && *body == 'r' )
{
if ( MORK_MEMCMP(body, "rowScope", 8) == 0 )
mStore_RowScopeToken = inAtom->mBookAtom_Id;
}
else if ( size == 10 && *body == 't' )
{
if ( MORK_MEMCMP(body, "tableScope", 10) == 0 )
mStore_TableScopeToken = inAtom->mBookAtom_Id;
}
else if ( size == 11 && *body == 'c' )
{
if ( MORK_MEMCMP(body, "columnScope", 11) == 0 )
mStore_ColumnScopeToken = inAtom->mBookAtom_Id;
}
}
}
}
//
// if ( inOid->mOid_Scope == morkStore_kColumnSpaceScope && inAtom->IsWeeBook() )
// {
// const mork_u1* body = ((const morkWeeBookAtom*) inAtom)->mWeeBookAtom_Body;
// mork_size size = inAtom->mAtom_Size;
//
// if ( size >= 7 && size <= 11 )
// {
// if ( size == 9 )
// {
// if ( *body == 'm' )
// {
// if ( MORK_MEMCMP(body, "mork:none", 9) == 0 )
// mStore_MorkNoneToken = inAtom->mBookAtom_Id;
// }
// else if ( *body == 'a' )
// {
// if ( MORK_MEMCMP(body, "atomScope", 9) == 0 )
// mStore_AtomScopeToken = inAtom->mBookAtom_Id;
// }
// else if ( *body == 't' )
// {
// if ( MORK_MEMCMP(body, "tableKind", 9) == 0 )
// mStore_TableKindToken = inAtom->mBookAtom_Id;
// }
// }
// else if ( size == 7 && *body == 'c' )
// {
// if ( MORK_MEMCMP(body, "charset", 7) == 0 )
// mStore_CharsetToken = inAtom->mBookAtom_Id;
// }
// else if ( size == 8 && *body == 'r' )
// {
// if ( MORK_MEMCMP(body, "rowScope", 8) == 0 )
// mStore_RowScopeToken = inAtom->mBookAtom_Id;
// }
// else if ( size == 10 && *body == 't' )
// {
// if ( MORK_MEMCMP(body, "tableScope", 10) == 0 )
// mStore_TableScopeToken = inAtom->mBookAtom_Id;
// }
// else if ( size == 11 && *body == 'c' )
// {
// if ( MORK_MEMCMP(body, "columnScope", 11) == 0 )
// mStore_ColumnScopeToken = inAtom->mBookAtom_Id;
// }
// }
// }
// }
morkAtom*
morkStore::AddAlias(morkEnv* ev, const morkMid& inMid, mork_cscode inForm)
@ -858,15 +844,15 @@ morkStore::AddAlias(morkEnv* ev, const morkMid& inMid, mork_cscode inForm)
outAtom = atomSpace->MakeBookAtomCopyWithAid(ev,
*keyAtom, (mork_aid) oid->mOid_Id);
if ( outAtom && outAtom->IsWeeBook() )
{
if ( oid->mOid_Scope == morkStore_kColumnSpaceScope )
{
mork_size size = outAtom->mAtom_Size;
if ( size >= 7 && size <= 11 )
this->SyncTokenIdChange(ev, outAtom, oid);
}
}
// if ( outAtom && outAtom->IsWeeBook() )
// {
// if ( oid->mOid_Scope == morkStore_kColumnSpaceScope )
// {
// mork_size size = outAtom->mAtom_Size;
// if ( size >= 7 && size <= 11 )
// this->SyncTokenIdChange(ev, outAtom, oid);
// }
// }
}
}
}
@ -874,6 +860,36 @@ morkStore::AddAlias(morkEnv* ev, const morkMid& inMid, mork_cscode inForm)
return outAtom;
}
#define morkStore_kMaxCopyTokenSize 512 /* if larger, cannot be copied */
mork_token
morkStore::CopyToken(morkEnv* ev, mdb_token inToken, morkStore* inStore)
// copy inToken from inStore over to this store
{
mork_token outToken = 0;
if ( inStore == this ) // same store?
outToken = inToken; // just return token unchanged
else
{
char yarnBuf[ morkStore_kMaxCopyTokenSize ];
mdbYarn yarn;
yarn.mYarn_Buf = yarnBuf;
yarn.mYarn_Fill = 0;
yarn.mYarn_Size = morkStore_kMaxCopyTokenSize;
yarn.mYarn_More = 0;
yarn.mYarn_Form = 0;
yarn.mYarn_Grow = 0;
inStore->TokenToString(ev, inToken, &yarn);
if ( ev->Good() )
{
morkBuf buf(yarn.mYarn_Buf, yarn.mYarn_Fill);
outToken = this->BufToToken(ev, &buf);
}
}
return outToken;
}
mork_token
morkStore::BufToToken(morkEnv* ev, const morkBuf* inBuf)
{
@ -1064,14 +1080,16 @@ morkStore::GetTable(morkEnv* ev, const mdbOid* inOid)
morkTable*
morkStore::NewTable(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind, mdb_bool inMustBeUnique)
mdb_kind inTableKind, mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
if ( ev->Good() )
{
morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inRowScope);
if ( rowSpace )
outTable = rowSpace->NewTable(ev, inTableKind, inMustBeUnique);
outTable = rowSpace->NewTable(ev, inTableKind, inMustBeUnique,
inOptionalMetaRowOid);
}
return outTable;
}
@ -1136,7 +1154,8 @@ morkStore::OidToRow(morkEnv* ev, const mdbOid* inOid)
}
morkTable*
morkStore::OidToTable(morkEnv* ev, const mdbOid* inOid)
morkStore::OidToTable(morkEnv* ev, const mdbOid* inOid,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
// OidToTable() finds old table with oid, or makes new one if not found.
{
morkTable* outTable = 0;
@ -1148,8 +1167,9 @@ morkStore::OidToTable(morkEnv* ev, const mdbOid* inOid)
outTable = rowSpace->mRowSpace_Tables.GetTable(ev, inOid->mOid_Id);
if ( !outTable && ev->Good() )
{
mork_kind tableKind = mStore_MorkNoneToken;
outTable = rowSpace->NewTableWithTid(ev, inOid->mOid_Id, tableKind);
mork_kind tableKind = morkStore_kNoneToken;
outTable = rowSpace->NewTableWithTid(ev, inOid->mOid_Id, tableKind,
inOptionalMetaRowOid);
}
}
}

View File

@ -119,6 +119,15 @@ public: // typesafe refcounting inlines calling inherited morkNode methods
#define morkStore_kGroundAtomSpace 'a' /* for mStore_GroundAtomSpace*/
#define morkStore_kStreamBufSize (8 * 1024) /* okay buffer size */
#define morkStore_kReservedColumnCount 0x20 /* for well-known columns */
#define morkStore_kNoneToken ((mork_token) 'n')
#define morkStore_kFormColumn ((mork_column) 'f')
#define morkStore_kAtomScopeColumn ((mork_column) 'a')
#define morkStore_kRowScopeColumn ((mork_column) 'r')
#define morkStore_kMetaScope ((mork_scope) 'm')
#define morkStore_kKindColumn ((mork_column) 'k')
/*| morkStore:
|*/
class morkStore : public morkPort {
@ -151,14 +160,6 @@ public: // state is public because the entire Mork system is private
morkStream* mStore_OutStream; // stream using file used by the writer
mork_token mStore_MorkNoneToken; // token for "mork:none"
mork_column mStore_CharsetToken; // token for "charset"
mork_column mStore_AtomScopeToken; // token for "atomScope"
mork_column mStore_RowScopeToken; // token for "rowScope"
mork_column mStore_TableScopeToken; // token for "tableScope"
mork_column mStore_ColumnScopeToken; // token for "columnScope"
mork_kind mStore_TableKindToken; // token for "tableKind"
morkRowSpaceMap mStore_RowSpaces; // maps mork_scope -> morkSpace
morkAtomSpaceMap mStore_AtomSpaces; // maps mork_scope -> morkSpace
@ -169,8 +170,8 @@ public: // state is public because the entire Mork system is private
public: // coping with any changes to store token slots above:
void SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
const mdbOid* inOid);
// void SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
// const mdbOid* inOid);
public: // building an atom inside mStore_BookAtom from a char* string
@ -252,6 +253,12 @@ public: // other store methods
const char* inFilePath,
const mdbOpenPolicy* inOpenPolicy);
morkAtom* CopyAtom(morkEnv* ev, const morkAtom* inAtom);
// copy inAtom (from some other store) over to this store
mork_token CopyToken(morkEnv* ev, mdb_token inToken, morkStore* inStore);
// copy inToken from inStore over to this store
mork_token BufToToken(morkEnv* ev, const morkBuf* inBuf);
mork_token StringToToken(morkEnv* ev, const char* inTokenName);
mork_token QueryToken(morkEnv* ev, const char* inTokenName);
@ -270,7 +277,8 @@ public: // other store methods
morkRow* OidToRow(morkEnv* ev, const mdbOid* inOid);
// OidToRow() finds old row with oid, or makes new one if not found.
morkTable* OidToTable(morkEnv* ev, const mdbOid* inOid);
morkTable* OidToTable(morkEnv* ev, const mdbOid* inOid,
const mdbOid* inOptionalMetaRowOid);
// OidToTable() finds old table with oid, or makes new one if not found.
static void SmallTokenToOneByteYarn(morkEnv* ev, mdb_token inToken,
@ -287,7 +295,8 @@ public: // other store methods
morkTable* GetTable(morkEnv* ev, const mdbOid* inOid);
morkTable* NewTable(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind, mdb_bool inMustBeUnique);
mdb_kind inTableKind, mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid);
morkPortTableCursor* GetPortTableCursor(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind) ;

View File

@ -92,10 +92,12 @@ morkTable::~morkTable() /*i*/ // assert CloseTable() executed earlier
morkTable::morkTable(morkEnv* ev, /*i*/
const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkStore* ioStore, nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mork_tid inTid, mork_kind inKind, mork_bool inMustBeUnique)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mTable_Store( 0 )
, mTable_RowSpace( 0 )
, mTable_MetaRow( 0 )
, mTable_Id( inTid )
, mTable_RowMap(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap,
morkTable_kStartRowMapSlotCount)
@ -112,6 +114,13 @@ morkTable::morkTable(morkEnv* ev, /*i*/
{
morkStore::SlotWeakStore(ioStore, ev, &mTable_Store);
morkRowSpace::SlotWeakRowSpace(ioRowSpace, ev, &mTable_RowSpace);
if ( inOptionalMetaRowOid )
mTable_MetaRowOid = *inOptionalMetaRowOid;
else
{
mTable_MetaRowOid.mOid_Scope = 0;
mTable_MetaRowOid.mOid_Id = morkRow_kMinusOneRid;
}
if ( ev->Good() )
mNode_Derived = morkDerived_kTable;
}
@ -194,6 +203,33 @@ morkTable::NilRowSpaceError(morkEnv* ev)
ev->NewError("nil mTable_RowSpace");
}
morkRow*
morkTable::GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid)
{
morkRow* outRow = mTable_MetaRow;
if ( !outRow )
{
morkStore* store = mTable_Store;
mdbOid* oid = &mTable_MetaRowOid;
if ( inOptionalMetaRowOid && !oid->mOid_Scope )
*oid = *inOptionalMetaRowOid;
if ( oid->mOid_Scope ) // oid already recorded in table?
outRow = store->OidToRow(ev, oid);
else
{
outRow = store->NewRow(ev, morkStore_kMetaScope);
if ( outRow ) // need to record new oid in table?
*oid = outRow->mRow_Oid;
}
mTable_MetaRow = outRow;
if ( outRow ) // need to note another use of this row?
outRow->AddTableUse(ev);
}
return outRow;
}
void
morkTable::GetTableOid(morkEnv* ev, mdbOid* outOid)
{
@ -241,14 +277,10 @@ morkTable::ArrayHasOid(morkEnv* ev, const mdbOid* inOid)
return -1;
}
mork_pos
mork_bool
morkTable::MapHasOid(morkEnv* ev, const mdbOid* inOid)
{
morkRow* row = mTable_RowMap.GetOid(ev, inOid);
if ( row )
return 1;
return -1;
return ( mTable_RowMap.GetOid(ev, inOid) != 0 );
}
mork_bool

View File

@ -78,6 +78,9 @@ public: // state is public because the entire Mork system is private
// mTable_RowSpace->mSpace_Scope is row scope
morkRowSpace* mTable_RowSpace; // weak ref to containing space
morkRow* mTable_MetaRow; // table's actual meta row
mdbOid mTable_MetaRowOid; // oid for meta row
morkRowMap mTable_RowMap; // hash table of all members
morkArray mTable_RowArray; // array of morkRow pointers
@ -98,6 +101,7 @@ public: // morkTable construction & destruction
morkTable(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioNodeHeap, morkStore* ioStore,
nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mork_tid inTableId,
mork_kind inKind, mork_bool inMustBeUnique);
void CloseTable(morkEnv* ev); // called by CloseMorkNode();
@ -120,6 +124,8 @@ public: // warnings
static void CellUsesUnderflowWarning(morkEnv* ev);
public: // other table methods
morkRow* GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid);
mork_u2 AddCellUse(morkEnv* ev);
mork_u2 CutCellUse(morkEnv* ev);
@ -134,7 +140,7 @@ public: // other table methods
void GetTableOid(morkEnv* ev, mdbOid* outOid);
mork_pos ArrayHasOid(morkEnv* ev, const mdbOid* inOid);
mork_pos MapHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool MapHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool AddRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()

View File

@ -129,18 +129,16 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage,
, mWriter_MaxIndent( morkWriter_kMaxIndent )
, mWriter_MaxLine( morkWriter_kMaxLine )
, mWriter_TableCharset( 0 )
, mWriter_TableForm( 0 )
, mWriter_TableAtomScope( 0 )
, mWriter_TableRowScope( 0 )
, mWriter_TableTableScope( 0 )
, mWriter_TableColumnScope( 0 )
, mWriter_TableKind( 0 )
, mWriter_RowCharset( 0 )
, mWriter_RowForm( 0 )
, mWriter_RowAtomScope( 0 )
, mWriter_RowScope( 0 )
, mWriter_DictCharset( 0 )
, mWriter_DictForm( 0 )
, mWriter_DictAtomScope( 0 )
, mWriter_NeedDirtyAll( morkBool_kFalse )
@ -372,7 +370,7 @@ morkWriter::WriteYarn(morkEnv* ev, const mdbYarn* inYarn)
stream->Putc(ev, c);
++outSize; // c
}
else if ( c == ')' && c == '$' && c == '\\' )
else if ( c == ')' || c == '$' || c == '\\' )
{
stream->Putc(ev, '\\');
stream->Putc(ev, c);
@ -403,8 +401,8 @@ morkWriter::WriteAtom(morkEnv* ev, const morkAtom* inAtom)
if ( inAtom->AliasYarn(&yarn) )
{
if ( mWriter_DidStartDict && yarn.mYarn_Form != mWriter_DictCharset )
this->ChangeDictCharset(ev, yarn.mYarn_Form);
if ( mWriter_DidStartDict && yarn.mYarn_Form != mWriter_DictForm )
this->ChangeDictForm(ev, yarn.mYarn_Form);
outSize = this->WriteYarn(ev, &yarn);
// mWriter_LineSize += stream->Write(ev, inYarn->mYarn_Buf, outSize);
@ -424,10 +422,10 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace)
{
if ( mWriter_LineSize )
stream->PutLineBreak(ev);
stream->PutString(ev, "< <(atomScope=");
stream->PutString(ev, "< <(a=");
stream->Putc(ev, (int) scope);
++mWriter_LineSize;
stream->PutString(ev, ")> // (charset=iso-8859-1)");
stream->PutString(ev, ")> // (f=iso-8859-1)");
mWriter_LineSize = stream->PutIndent(ev, morkWriter_kDictAliasDepth);
}
else
@ -457,8 +455,8 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace)
atom->AliasYarn(&yarn);
mork_size size = ev->TokenAsHex(idBuf, atom->mBookAtom_Id);
if ( yarn.mYarn_Form != mWriter_DictCharset )
this->ChangeDictCharset(ev, yarn.mYarn_Form);
if ( yarn.mYarn_Form != mWriter_DictForm )
this->ChangeDictForm(ev, yarn.mYarn_Form);
mork_size pending = yarn.mYarn_Fill + size +
morkWriter_kYarnEscapeSlop + 4;
@ -648,7 +646,7 @@ morkWriter::OnDirtyAllDone(morkEnv* ev)
stream->Seek(ev, 0); // beginning of stream
if ( ev->Good() )
{
stream->PutStringThenNewline(ev, "// <!-- <mdb:mork:z v=\"1.1\"/> -->");
stream->PutStringThenNewline(ev, morkWriter_kFileHeader);
mWriter_LineSize = 0;
}
@ -968,17 +966,15 @@ morkWriter::PutTableDict(morkEnv* ev, morkTable* ioTable)
{
morkRowSpace* space = ioTable->mTable_RowSpace;
mWriter_TableRowScope = space->mSpace_Scope;
mWriter_TableCharset = 0; // (charset=iso-8859-1)
mWriter_TableAtomScope = 'a'; // (atomScope=a)
mWriter_TableTableScope = 't'; // (tableScope=t)
mWriter_TableColumnScope = 'c'; // (columnScope=c)
mWriter_TableForm = 0; // (f=iso-8859-1)
mWriter_TableAtomScope = 'v'; // (a=v)
mWriter_TableKind = ioTable->mTable_Kind;
mWriter_RowCharset = mWriter_TableCharset;
mWriter_RowForm = mWriter_TableForm;
mWriter_RowAtomScope = mWriter_TableAtomScope;
mWriter_RowScope = mWriter_TableRowScope;
mWriter_DictCharset = mWriter_TableCharset;
mWriter_DictForm = mWriter_TableForm;
mWriter_DictAtomScope = mWriter_TableAtomScope;
if ( ev->Good() )
@ -986,6 +982,14 @@ morkWriter::PutTableDict(morkEnv* ev, morkTable* ioTable)
if ( ev->Good() )
{
morkRow* r = ioTable->mTable_MetaRow;
if ( r )
{
if ( r->IsRow() )
this->PutRowDict(ev, r);
else
r->NonRowTypeError(ev);
}
morkArray* array = &ioTable->mTable_RowArray; // vector of rows
mork_fill fill = array->mArray_Fill; // count of rows
morkRow** rows = (morkRow**) array->mArray_Slots;
@ -994,7 +998,7 @@ morkWriter::PutTableDict(morkEnv* ev, morkTable* ioTable)
morkRow** end = rows + fill;
while ( rows < end && ev->Good() )
{
morkRow* r = *rows++; // next row to consider
r = *rows++; // next row to consider
if ( r && r->IsRow() )
this->PutRowDict(ev, r);
else
@ -1013,15 +1017,25 @@ morkWriter::WriteTokenToTokenMetaCell(morkEnv* ev,
mork_token inCol, mork_token inValue)
{
morkStream* stream = mWriter_Stream;
char buf[ 128 ]; // buffer for staging the two hex IDs
char* p = buf;
*p++ = '('; // we always start with open paren
*p++ = '^'; // indicates col is hex ID
mork_size colSize = ev->TokenAsHex(p, inCol);
p += colSize;
*p++ = '='; // we always start with open paren
mWriter_LineSize += stream->Write(ev, buf, colSize + 3);
if ( inCol < 0x80 )
{
stream->Putc(ev, '(');
stream->Putc(ev, (char) inCol);
stream->Putc(ev, '=');
}
else
{
char buf[ 128 ]; // buffer for staging the two hex IDs
char* p = buf;
*p++ = '('; // we always start with open paren
*p++ = '^'; // indicates col is hex ID
mork_size colSize = ev->TokenAsHex(p, inCol);
p += colSize;
*p++ = '=';
mWriter_LineSize += stream->Write(ev, buf, colSize + 3);
}
this->IndentAsNeeded(ev, morkWriter_kTableMetaCellValueDepth);
mdbYarn* yarn = &mWriter_ColYarn;
@ -1058,21 +1072,34 @@ morkWriter::WriteStringToTokenDictCell(morkEnv* ev,
}
void
morkWriter::ChangeDictCharset(morkEnv* ev, mork_cscode inNewForm)
morkWriter::ChangeDictForm(morkEnv* ev, mork_cscode inNewForm)
{
if ( inNewForm != mWriter_DictCharset )
if ( inNewForm != mWriter_DictForm )
{
morkStream* stream = mWriter_Stream;
if ( mWriter_LineSize )
stream->PutLineBreak(ev);
mWriter_LineSize = 0;
stream->Putc(ev, '<');
this->WriteStringToTokenDictCell(ev, "(charset=", mWriter_DictCharset);
stream->Putc(ev, '>');
++mWriter_LineSize;
char buf[ 128 ]; // buffer for staging the two hex IDs
char* p = buf;
*p++ = '<'; // we always start with open paren
*p++ = '('; // we always start with open paren
*p++ = (char) morkStore_kFormColumn;
*p++ = '^'; // indicates col is hex ID
mork_size formSize = ev->TokenAsHex(p, inNewForm);
p += formSize;
*p++ = ')';
*p++ = '>';
*p = 0;
mork_size pending = formSize + 6;
this->IndentOverMaxLine(ev, pending, morkWriter_kDictAliasDepth);
mWriter_LineSize += stream->Write(ev, buf, pending);
mWriter_DictCharset = inNewForm;
mWriter_DictForm = inNewForm;
}
}
@ -1091,16 +1118,16 @@ morkWriter::StartDict(morkEnv* ev)
stream->PutLineBreak(ev);
mWriter_LineSize = 0;
stream->PutLineBreak(ev);
if ( mWriter_DictCharset || mWriter_DictAtomScope != 'a' )
if ( mWriter_DictForm || mWriter_DictAtomScope != 'v' )
{
stream->Putc(ev, '<');
stream->Putc(ev, ' ');
stream->Putc(ev, '<');
mWriter_LineSize = 3;
if ( mWriter_DictCharset )
this->WriteStringToTokenDictCell(ev, "(charset=", mWriter_DictCharset);
if ( mWriter_DictAtomScope != 'a' )
this->WriteStringToTokenDictCell(ev, "(atomScope=", mWriter_DictAtomScope);
if ( mWriter_DictForm )
this->WriteStringToTokenDictCell(ev, "(f=", mWriter_DictForm);
if ( mWriter_DictAtomScope != 'v' )
this->WriteStringToTokenDictCell(ev, "(a=", mWriter_DictAtomScope);
stream->Putc(ev, '>');
++mWriter_LineSize;
@ -1149,19 +1176,28 @@ morkWriter::StartTable(morkEnv* ev, morkTable* ioTable)
*p = '{';
mWriter_LineSize += stream->Write(ev, buf, size + 3);
morkStore* store = mWriter_Store;
mork_scope rs = mWriter_TableRowScope;
if ( rs )
{
this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth);
this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs);
}
// mork_scope rs = mWriter_TableRowScope;
// if ( rs )
// {
// this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth);
// this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs);
// }
mork_kind tk = mWriter_TableKind;
if ( tk )
{
this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth);
this->WriteTokenToTokenMetaCell(ev, store->mStore_TableKindToken, tk);
this->WriteTokenToTokenMetaCell(ev, morkStore_kKindColumn, tk);
}
morkRow* r = ioTable->mTable_MetaRow;
if ( r )
{
if ( r->IsRow() )
this->PutRow(ev, r);
else
r->NonRowTypeError(ev);
}
stream->Putc(ev, '}'); // end meta
mWriter_LineSize = stream->PutIndent(ev, morkWriter_kRowCellDepth);
}
@ -1218,6 +1254,22 @@ morkWriter::PutRowDict(morkEnv* ev, morkRow* ioRow)
return ev->Good();
}
mork_bool
morkWriter::IsYarnAllValue(const mdbYarn* inYarn)
{
mork_fill fill = inYarn->mYarn_Fill;
const mork_u1* buf = (const mork_u1*) inYarn->mYarn_Buf;
const mork_u1* end = buf + fill;
--buf; // prepare for preincrement
while ( ++buf < end )
{
mork_ch c = *buf;
if ( !morkCh_IsValue(c) )
return morkBool_kFalse;
}
return morkBool_kTrue;
}
mork_bool
morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow)
{
@ -1243,17 +1295,39 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow)
char* p = idBuf;
colSize = ev->TokenAsHex(p, col);
p += colSize;
mdbYarn yarn; // to ref content inside atom
atom->AliasYarn(&yarn);
if ( atom->IsBook() ) // is it possible to write atom ID?
{
this->IndentAsNeeded(ev, morkWriter_kRowCellDepth);
*p++ = '^';
morkBookAtom* ba = (morkBookAtom*) atom;
mork_size valSize = ev->TokenAsHex(p, ba->mBookAtom_Id);
p += valSize;
*p = ')';
mWriter_LineSize += stream->Write(ev, buf, colSize + valSize + 4);
mork_size valSize = ev->TokenAsHex(p, ba->mBookAtom_Id);
mork_fill yarnFill = yarn.mYarn_Fill;
mork_bool putImmYarn = ( yarnFill <= valSize );
if ( putImmYarn )
putImmYarn = this->IsYarnAllValue(&yarn);
if ( putImmYarn ) // value no bigger than id?
{
p[ -1 ] = '='; // go back and clobber '^' with '=' instead
if ( yarnFill )
{
MORK_MEMCPY(p, yarn.mYarn_Buf, yarnFill);
p += yarnFill;
}
*p++ = ')';
mWriter_LineSize += stream->Write(ev, buf, p - buf);
}
else
{
p += valSize;
*p = ')';
mWriter_LineSize += stream->Write(ev, buf, colSize + valSize + 4);
}
if ( atom->mAtom_Change == morkChange_kAdd )
{
@ -1263,11 +1337,8 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow)
}
else // must write an anonymous atom
{
mdbYarn yarn; // to ref content inside atom
atom->AliasYarn(&yarn);
if ( yarn.mYarn_Form != mWriter_DictCharset )
this->ChangeDictCharset(ev, yarn.mYarn_Form);
if ( yarn.mYarn_Form != mWriter_DictForm )
this->ChangeDictForm(ev, yarn.mYarn_Form);
mork_size pending = yarn.mYarn_Fill + colSize +
morkWriter_kYarnEscapeSlop + 2;
@ -1299,11 +1370,10 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow)
mdbOid* roid = &ioRow->mRow_Oid;
mork_size ridSize = 0;
this->IndentAsNeeded(ev, morkWriter_kRowDepth);
//if ( morkBool_kTrue )
if ( ioRow->IsRowDirty() )
{
stream->PutIndent(ev, morkWriter_kRowDepth);
ioRow->SetRowClean();
mork_rid rid = roid->mOid_Id;
*p++ = '[';
@ -1322,6 +1392,8 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow)
}
else
{
this->IndentAsNeeded(ev, morkWriter_kRowDepth);
if ( roid->mOid_Scope == mWriter_TableRowScope )
ridSize = ev->TokenAsHex(p, roid->mOid_Id);
else

View File

@ -103,6 +103,9 @@
#define morkWriter_kRowCellDepth 4 /* */
#define morkWriter_kRowCellValueDepth 6 /* */
// v=1.1 retired on 23-Mar-98
#define morkWriter_kFileHeader "// <!-- <mdb:mork:z v=\"1.2\"/> -->"
class morkWriter : public morkNode { // row iterator
// public: // slots inherited from morkObject (meant to inform only)
@ -131,18 +134,16 @@ public: // state is public because the entire Mork system is private
mork_size mWriter_MaxIndent; // line size forcing a line break
mork_size mWriter_MaxLine; // line size forcing a value continuation
mork_cscode mWriter_TableCharset; // current charset metainfo
mork_cscode mWriter_TableForm; // current charset metainfo
mork_scope mWriter_TableAtomScope; // current atom scope
mork_scope mWriter_TableRowScope; // current row scope
mork_scope mWriter_TableTableScope; // current table scope
mork_scope mWriter_TableColumnScope; // current column scope
mork_kind mWriter_TableKind; // current table kind
mork_cscode mWriter_RowCharset; // current charset metainfo
mork_cscode mWriter_RowForm; // current charset metainfo
mork_scope mWriter_RowAtomScope; // current atom scope
mork_scope mWriter_RowScope; // current row scope
mork_cscode mWriter_DictCharset; // current charset metainfo
mork_cscode mWriter_DictForm; // current charset metainfo
mork_scope mWriter_DictAtomScope; // current atom scope
mork_bool mWriter_NeedDirtyAll; // need to call DirtyAll()
@ -199,7 +200,7 @@ public: // typing & errors
static void UnsupportedPhaseError(morkEnv* ev);
public: // inlines
void ChangeDictCharset(morkEnv* ev, mork_cscode inNewForm);
void ChangeDictForm(morkEnv* ev, mork_cscode inNewForm);
mork_bool DidStartDict() const { return mWriter_DidStartDict; }
mork_bool DidEndDict() const { return mWriter_DidEndDict; }
@ -269,6 +270,8 @@ public: // writing node content second pass
public: // other writer methods
mork_bool IsYarnAllValue(const mdbYarn* inYarn);
mork_size WriteYarn(morkEnv* ev, const mdbYarn* inYarn);
// return number of atom bytes written on the current line (which
// implies that escaped line breaks will make the size value smaller

View File

@ -60,6 +60,10 @@
#include "morkFile.h"
#endif
#ifndef _MORKWRITER_
#include "morkWriter.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
@ -371,6 +375,7 @@ orkinFactory::CanOpenFilePort(
{
if ( inFilePath && inFirst512Bytes && outCanOpen )
{
canOpenAsPort = this->CanOpenMorkTextFile(ev, inFirst512Bytes);
}
else
ev->NilPointerError();
@ -448,6 +453,21 @@ orkinFactory::ThumbToOpenPort( // redeeming a completed thumb from OpenFilePort(
}
// } ----- end port methods -----
mork_bool
orkinFactory::CanOpenMorkTextFile(morkEnv* ev,
const mdbYarn* inFirst512Bytes)
{
mork_bool outBool = morkBool_kFalse;
mork_size headSize = MORK_STRLEN(morkWriter_kFileHeader);
const mdbYarn* y = inFirst512Bytes;
if ( y && y->mYarn_Buf && y->mYarn_Fill >= headSize )
{
mork_u1* buf = (mork_u1*) y->mYarn_Buf;
outBool = ( MORK_MEMCMP(morkWriter_kFileHeader, buf, headSize) == 0 );
}
return outBool;
}
// { ----- begin store methods -----
/*virtual*/ mdb_err
orkinFactory::CanOpenFileStore(
@ -468,8 +488,8 @@ orkinFactory::CanOpenFileStore(
if ( inFilePath && inFirst512Bytes && outCanOpenAsStore )
{
// right now always say true; later we should look for magic patterns
canOpenAsStore = morkBool_kTrue; // don't bother checking
canOpenAsPort = morkBool_kTrue;
canOpenAsStore = this->CanOpenMorkTextFile(ev, inFirst512Bytes);
canOpenAsPort = canOpenAsStore;
}
else
ev->NilPointerError();

View File

@ -92,6 +92,8 @@ public: // utilities:
mdb_err* outErr) const;
morkEnv* GetInternalFactoryEnv(mdb_err* outErr);
mork_bool CanOpenMorkTextFile(morkEnv* ev, const mdbYarn* inFirst512Bytes);
public: // type identification
mork_bool IsOrkinFactory() const

View File

@ -48,6 +48,10 @@
#include "morkRowObject.h"
#endif
#ifndef _MORKCELLOBJECT_
#include "morkCellObject.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
@ -68,6 +72,10 @@
#include "orkinRowCellCursor.h"
#endif
#ifndef _ORKINCELL_
#include "orkinCell.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/* public virtual*/
@ -463,7 +471,7 @@ orkinRow::CutColumn( // make sure a column is absent from the row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
row->CutColumn(ev, inColumn);
outErr = ev->AsErr();
}
return outErr;
@ -479,7 +487,7 @@ orkinRow::CutAllColumns( // remove all columns from the row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
row->CutAllColumns(ev);
outErr = ev->AsErr();
}
return outErr;
@ -539,7 +547,39 @@ orkinRow::AddCell( // copy a cell from another row to this row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
morkCell* cell = 0;
orkinCell* ocell = (orkinCell*) inCell; // must verify this cast:
if ( ocell->CanUseCell(mev, morkBool_kFalse, &outErr, &cell) )
{
morkCellObject* cellObj = (morkCellObject*) ocell->mHandle_Object;
morkRow* cellRow = cellObj->mCellObject_Row;
if ( cellRow )
{
if ( row != cellRow )
{
morkStore* store = row->GetRowSpaceStore(ev);
morkStore* cellStore = cellRow->GetRowSpaceStore(ev);
if ( store && cellStore )
{
mork_column col = cell->GetColumn();
morkAtom* atom = cell->mCell_Atom;
mdbYarn yarn;
atom->AliasYarn(&yarn); // works even when atom is nil
if ( store != cellStore )
col = store->CopyToken(ev, col, cellStore);
if ( ev->Good() )
row->AddColumn(ev, col, &yarn, store);
}
else
ev->NilPointerError();
}
}
else
ev->NilPointerError();
}
outErr = ev->AsErr();
}
return outErr;
@ -627,7 +667,11 @@ orkinRow::SetRow( // make exact duplicate of another row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
morkRow* source = 0;
if ( this->CanUseRow(mev, morkBool_kFalse, &outErr, &source) )
{
row->SetRow(ev, source);
}
outErr = ev->AsErr();
}
return outErr;

View File

@ -677,6 +677,7 @@ orkinStore::NewTable( // make one new table of specific type
mdb_scope inRowScope, // row scope for row ids
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) // acquire scoped collection of rows
{
mdb_err outErr = 0;
@ -686,7 +687,7 @@ orkinStore::NewTable( // make one new table of specific type
{
morkTable* table =
((morkStore*) mHandle_Object)->NewTable(ev, inRowScope,
inTableKind, inMustBeUnique);
inTableKind, inMustBeUnique, inOptionalMetaRowOid);
if ( table && ev->Good() )
outTable = table->AcquireTableHandle(ev);
outErr = ev->AsErr();
@ -695,6 +696,36 @@ orkinStore::NewTable( // make one new table of specific type
*acqTable = outTable;
return outErr;
}
/*virtual*/ mdb_err
orkinStore::NewTableWithOid( // make one new table of specific type
nsIMdbEnv* mev, // context
const mdbOid* inOid, // caller assigned oid
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) // acquire scoped collection of rows
{
mdb_err outErr = 0;
nsIMdbTable* outTable = 0;
morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkTable* table = ((morkStore*) mHandle_Object)->OidToTable(ev, inOid,
inOptionalMetaRowOid);
if ( table && ev->Good() )
{
table->mTable_Kind = inTableKind;
if ( inMustBeUnique )
table->mTable_MustBeUnique = inMustBeUnique;
outTable = table->AcquireTableHandle(ev);
}
outErr = ev->AsErr();
}
if ( acqTable )
*acqTable = outTable;
return outErr;
}
// } ----- end table methods -----
// { ----- begin row scope methods -----

View File

@ -274,6 +274,15 @@ public: // type identification
mdb_scope inRowScope, // row scope for row ids
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable); // acquire scoped collection of rows
virtual mdb_err NewTableWithOid( // make one new table of specific type
nsIMdbEnv* ev, // context
const mdbOid* inOid, // caller assigned oid
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable); // acquire scoped collection of rows
// } ----- end table methods -----

View File

@ -383,6 +383,61 @@ orkinTable::GetRowScope(nsIMdbEnv* mev, mdb_scope* outRowScope)
return outErr;
}
/*virtual*/ mdb_err
orkinTable::GetMetaRow( nsIMdbEnv* mev,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mdbOid* outOid, // output meta row oid, can be nil to suppress output
nsIMdbRow** acqRow) // acquire table's unique singleton meta row
// The purpose of a meta row is to support the persistent recording of
// meta info about a table as cells put into the distinguished meta row.
// Each table has exactly one meta row, which is not considered a member
// of the collection of rows inside the table. The only way to tell
// whether a row is a meta row is by the fact that it is returned by this
// GetMetaRow() method from some table. Otherwise nothing distinguishes
// a meta row from any other row. A meta row can be used anyplace that
// any other row can be used, and can even be put into other tables (or
// the same table) as a table member, if this is useful for some reason.
// The first attempt to access a table's meta row using GetMetaRow() will
// cause the meta row to be created if it did not already exist. When the
// meta row is created, it will have the row oid that was previously
// requested for this table's meta row; or if no oid was ever explicitly
// specified for this meta row, then a unique oid will be generated in
// the row scope named "metaScope" (so obviously MDB clients should not
// manually allocate any row IDs from that special meta scope namespace).
// The meta row oid can be specified either when the table is created, or
// else the first time that GetMetaRow() is called, by passing a non-nil
// pointer to an oid for parameter inOptionalMetaRowOid. The meta row's
// actual oid is returned in outOid (if this is a non-nil pointer), and
// it will be different from inOptionalMetaRowOid when the meta row was
// already given a different oid earlier.
{
mdb_err outErr = 0;
nsIMdbRow* outRow = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkTable* table = (morkTable*) mHandle_Object;
morkRow* row = table->GetMetaRow(ev, inOptionalMetaRowOid);
if ( row && ev->Good() )
{
if ( outOid )
*outOid = row->mRow_Oid;
outRow = row->AcquireRowHandle(ev, table->mTable_Store);
}
outErr = ev->AsErr();
}
if ( acqRow )
*acqRow = outRow;
if ( ev->Bad() && outOid )
{
outOid->mOid_Scope = 0;
outOid->mOid_Id = morkRow_kMinusOneRid;
}
return outErr;
}
// } ----- end attribute methods -----
// { ----- begin cursor methods -----
@ -456,6 +511,23 @@ orkinTable::AddOid( // make sure the row with inOid is a table member
/*virtual*/ mdb_err
orkinTable::HasOid( // test for the table position of a row member
nsIMdbEnv* mev, // context
const mdbOid* inOid, // row to find in table
mdb_bool* outHasOid) // whether inOid is a member row
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
if ( outHasOid )
*outHasOid = ((morkTable*) mHandle_Object)->MapHasOid(ev, inOid);
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
orkinTable::OidToPos( // test for the table position of a row member
nsIMdbEnv* mev, // context
const mdbOid* inOid, // row to find in table
mdb_pos* outPos) // zero-based ordinal position of row in table
@ -481,7 +553,17 @@ orkinTable::CutOid( // make sure the row with inOid is not a member
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
morkTable* table = (morkTable*) mHandle_Object;
morkStore* store = table->mTable_Store;
if ( inOid && store )
{
morkRow* row = store->GetRow(ev, inOid);
if ( row )
table->CutRow(ev, row);
}
else
ev->NilPointerError();
outErr = ev->AsErr();
}
return outErr;
@ -496,12 +578,30 @@ orkinTable::NewRow( // create a new row instance in table
nsIMdbRow** acqRow) // create new row
{
mdb_err outErr = 0;
nsIMdbRow* outRow = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
morkTable* table = (morkTable*) mHandle_Object;
morkStore* store = table->mTable_Store;
if ( ioOid && store )
{
morkRow* row = 0;
if ( ioOid->mOid_Id == morkRow_kMinusOneRid )
row = store->NewRow(ev, ioOid->mOid_Scope);
else
row = store->NewRowWithOid(ev, ioOid);
if ( row && table->AddRow(ev, row) )
outRow = row->AcquireRowHandle(ev, store);
}
else
ev->NilPointerError();
outErr = ev->AsErr();
}
if ( acqRow )
*acqRow = outRow;
return outErr;
}
@ -527,6 +627,30 @@ orkinTable::AddRow( // make sure the row with inOid is a table member
/*virtual*/ mdb_err
orkinTable::HasRow( // test for the table position of a row member
nsIMdbEnv* mev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_bool* outBool) // zero-based ordinal position of row in table
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkRow* row = 0;
orkinRow* orow = (orkinRow*) ioRow;
if ( orow->CanUseRow(mev, /*inMutable*/ morkBool_kFalse, &outErr, &row) )
{
morkTable* table = (morkTable*) mHandle_Object;
if ( outBool )
*outBool = table->MapHasOid(ev, &row->mRow_Oid);
}
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
orkinTable::RowToPos( // test for the table position of a row member
nsIMdbEnv* mev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos) // zero-based ordinal position of row in table
@ -535,7 +659,15 @@ orkinTable::HasRow( // test for the table position of a row member
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
morkRow* row = 0;
orkinRow* orow = (orkinRow*) ioRow;
if ( orow->CanUseRow(mev, /*inMutable*/ morkBool_kFalse, &outErr, &row) )
{
morkTable* table = (morkTable*) mHandle_Object;
mork_pos pos = table->ArrayHasOid(ev, &row->mRow_Oid);
if ( outPos )
*outPos = pos;
}
outErr = ev->AsErr();
}
return outErr;
@ -611,7 +743,7 @@ orkinTable::SearchColumnsHint( // advise re future expected search cols
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -626,7 +758,7 @@ orkinTable::SortColumnsHint( // advise re future expected sort columns
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -644,7 +776,7 @@ orkinTable::StartBatchChangeHint( // advise before many adds and cuts
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -668,7 +800,7 @@ orkinTable::EndBatchChangeHint( // advise before many adds and cuts
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -689,7 +821,9 @@ orkinTable::CanSortColumn( // query which col is currently used for sorting
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
if ( outCanSort )
*outCanSort = morkBool_kFalse;
outErr = ev->AsErr();
}
return outErr;
@ -703,12 +837,15 @@ orkinTable::NewSortColumn( // change col used for sorting in the table
nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort
{
mdb_err outErr = 0;
nsIMdbThumb* outThumb = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqThumb )
*acqThumb = outThumb;
return outErr;
}
// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
@ -723,12 +860,15 @@ orkinTable::NewSortColumnWithCompare( // change sort col w/ explicit compare
nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort
{
mdb_err outErr = 0;
nsIMdbThumb* outThumb = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqThumb )
*acqThumb = outThumb;
return outErr;
}
// Note the table will hold a reference to inCompare if this object is used
@ -743,12 +883,15 @@ orkinTable::GetSortColumn( // query which col is currently sorted
mdb_column* outColumn) // col the table uses for sorting (or zero)
{
mdb_err outErr = 0;
mdb_column col = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( outColumn )
*outColumn = col;
return outErr;
}
@ -760,12 +903,15 @@ orkinTable::CloneSortColumn( // view same table with a different sort
nsIMdbThumb** acqThumb) // acquire thumb for incremental table clone
{
mdb_err outErr = 0;
nsIMdbThumb* outThumb = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqThumb )
*acqThumb = outThumb;
return outErr;
}
// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
@ -778,12 +924,15 @@ orkinTable::ThumbToCloneSortTable( // redeem complete CloneSortColumn() thumb
nsIMdbTable** acqTable) // new table instance (or old if sort unchanged)
{
mdb_err outErr = 0;
nsIMdbTable* outTable = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqTable )
*acqTable = outTable;
return outErr;
}
// } ----- end sorting methods -----
@ -841,7 +990,8 @@ orkinTable::AddIndex( // create a sorting index for column if possible
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -859,7 +1009,8 @@ orkinTable::CutIndex( // stop supporting a specific column index
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -875,7 +1026,9 @@ orkinTable::HasIndex( // query for current presence of a column index
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
if ( outHasIndex )
*outHasIndex = morkBool_kFalse;
outErr = ev->AsErr();
}
return outErr;
@ -890,7 +1043,7 @@ orkinTable::EnableIndexOnSort( // create an index for col on first sort
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -906,7 +1059,9 @@ orkinTable::QueryIndexOnSort( // check whether index on sort is enabled
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
if ( outIndexOnSort )
*outIndexOnSort = morkBool_kFalse;
outErr = ev->AsErr();
}
return outErr;
@ -921,7 +1076,7 @@ orkinTable::DisableIndexOnSort( // prevent future index creation on sort
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;

View File

@ -35,7 +35,7 @@
#include "morkHandle.h"
#endif
#ifndef _MORKTable_
#ifndef _MORKTABLE_
#include "morkTable.h"
#endif
@ -164,11 +164,38 @@ public: // type identification
// { ===== begin nsIMdbTable methods =====
// { ----- begin attribute methods -----
// { ----- begin meta attribute methods -----
virtual mdb_err GetTableKind(nsIMdbEnv* ev, mdb_kind* outTableKind);
virtual mdb_err GetRowScope(nsIMdbEnv* ev, mdb_scope* outRowScope);
// } ----- end attribute methods -----
virtual mdb_err GetMetaRow(
nsIMdbEnv* ev, // context
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mdbOid* outOid, // output meta row oid, can be nil to suppress output
nsIMdbRow** acqRow); // acquire table's unique singleton meta row
// The purpose of a meta row is to support the persistent recording of
// meta info about a table as cells put into the distinguished meta row.
// Each table has exactly one meta row, which is not considered a member
// of the collection of rows inside the table. The only way to tell
// whether a row is a meta row is by the fact that it is returned by this
// GetMetaRow() method from some table. Otherwise nothing distinguishes
// a meta row from any other row. A meta row can be used anyplace that
// any other row can be used, and can even be put into other tables (or
// the same table) as a table member, if this is useful for some reason.
// The first attempt to access a table's meta row using GetMetaRow() will
// cause the meta row to be created if it did not already exist. When the
// meta row is created, it will have the row oid that was previously
// requested for this table's meta row; or if no oid was ever explicitly
// specified for this meta row, then a unique oid will be generated in
// the row scope named "metaScope" (so obviously MDB clients should not
// manually allocate any row IDs from that special meta scope namespace).
// The meta row oid can be specified either when the table is created, or
// else the first time that GetMetaRow() is called, by passing a non-nil
// pointer to an oid for parameter inOptionalMetaRowOid. The meta row's
// actual oid is returned in outOid (if this is a non-nil pointer), and
// it will be different from inOptionalMetaRowOid when the meta row was
// already given a different oid earlier.
// } ----- end meta attribute methods -----
// { ----- begin cursor methods -----
virtual mdb_err GetTableRowCursor( // make a cursor, starting iteration at inRowPos
@ -183,7 +210,11 @@ public: // type identification
mdb_pos inRowPos, // zero-based ordinal position of row in table
mdbOid* outOid); // row oid at the specified position
// Note that HasRow() performs the inverse oid->pos mapping
virtual mdb_err RowToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos); // zero-based ordinal position of row in table
// } ----- end row position methods -----
// { ----- begin oid set methods -----
@ -192,6 +223,11 @@ public: // type identification
const mdbOid* inOid); // row to ensure membership in table
virtual mdb_err HasOid( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_bool* outHasOid); // whether inOid is a member row
virtual mdb_err OidToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_pos* outPos); // zero-based ordinal position of row in table
@ -214,7 +250,7 @@ public: // type identification
virtual mdb_err HasRow( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos); // zero-based ordinal position of row in table
mdb_bool* outHasRow); // whether row is a table member
virtual mdb_err CutRow( // make sure the row with inOid is not a member
nsIMdbEnv* ev, // context

View File

@ -690,6 +690,88 @@ public:
extern "C" nsIMdbFactory* MakeMdbFactory();
/*| nsIMdbFile: abstract file interface resembling the original morkFile
**| abstract interface (which was in turn modeled on the file interface
**| from public domain IronDoc). The design of this file interface is
**| complicated by the fact that some DB's will not find this interface
**| adequate for all runtime requirements (even though this file API is
**| enough to implement text-based DB's like Mork). For this reason,
**| more methods have been added to let a DB library force the file to
**| become closed so the DB can reopen the file in some other manner.
**| Folks are encouraged to suggest ways to tune this interface to suit
**| DB's that cannot manage to pull their maneuvers even given this API.
**|
**|| Tell: get the current i/o position in file
**|
**|| Seek: change the current i/o position in file
**|
**|| Eof: return file's total length in bytes
**|
**|| Read: input inSize bytes into outBuf, returning actual transfer size
**|
**|| Get: read starting at specific file offset (e.g. Seek(); Read();)
**|
**|| Write: output inSize bytes from inBuf, returning actual transfer size
**|
**|| Put: write starting at specific file offset (e.g. Seek(); Write();)
**|
**|| Flush: if written bytes are buffered, push them to final destination
**|
**|| Path: get file path in some string representation. This is intended
**| either to support the display of file name in a user presentation, or
**| to support the closing and reopening of the file when the DB needs more
**| exotic file access than is presented by the nsIMdbFile interface.
**|
**|| Steal: tell this file to close any associated i/o stream in the file
**| system, because the file ioThief intends to reopen the file in order
**| to provide the MDB implementation with more exotic file access than is
**| offered by the nsIMdbFile alone. Presumably the thief knows enough
**| from Path() in order to know which file to reopen. If Steal() is
**| successful, this file should probably delegate all future calls to
**| the nsIMdbFile interface down to the thief files, so that even after
**| the file has been stolen, it can still be read, written, or forcibly
**| closed (by a call to CloseMdbObject()).
**|
**|| Thief: acquire and return thief passed to an earlier call to Steal().
|*/
class nsIMdbFile : public nsIMdbObject { // minimal file interface
public:
// { ===== begin nsIMdbFile methods =====
// { ----- begin pos methods -----
virtual mdb_err Tell(nsIMdbEnv* ev, mdb_pos* outPos) const = 0;
virtual mdb_err Seek(nsIMdbEnv* ev, mdb_pos inPos) = 0;
virtual mdb_err Eof(nsIMdbEnv* ev, mdb_pos* outPos) const = 0;
// } ----- end pos methods -----
// { ----- begin read methods -----
virtual mdb_err Read(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
mdb_size* outActualSize) = 0;
virtual mdb_err Get(nsIMdbEnv* ev, void* outBuf, mdb_size inSize,
mdb_pos inPos, mdb_size* outActualSize) = 0;
// } ----- end read methods -----
// { ----- begin write methods -----
virtual mdb_err Write(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
mdb_size* outActualSize) = 0;
virtual mdb_err Put(nsIMdbEnv* ev, const void* inBuf, mdb_size inSize,
mdb_pos inPos, mdb_size* outActualSize) = 0;
virtual mdb_err Flush(nsIMdbEnv* ev) = 0;
// } ----- end attribute methods -----
// { ----- begin path methods -----
virtual mdb_err Path(nsIMdbEnv* ev, mdbYarn* outFilePath) = 0;
// } ----- end path methods -----
// { ----- begin replacement methods -----
virtual mdb_err Steal(nsIMdbEnv* ev, nsIMdbFile* ioThief) = 0;
virtual mdb_err Thief(nsIMdbEnv* ev, nsIMdbFile** acqThief) = 0;
// } ----- end replacement methods -----
// } ===== end nsIMdbFile methods =====
};
/*| nsIMdbPort: a readonly interface to a specific database file. The mutable
**| nsIMdbStore interface is a subclass that includes writing behavior, but
**| most of the needed db methods appear in the readonly nsIMdbPort interface.
@ -995,6 +1077,15 @@ public:
mdb_scope inRowScope, // row scope for row ids
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) = 0; // acquire scoped collection of rows
virtual mdb_err NewTableWithOid( // make one new table of specific type
nsIMdbEnv* ev, // context
const mdbOid* inOid, // caller assigned oid
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) = 0; // acquire scoped collection of rows
// } ----- end table methods -----
@ -1333,7 +1424,7 @@ public:
**| complain not at all. Cutting a row from a table only does something when
**| the row was actually a member, and otherwise does nothing silently.
**|
**|| row ref count: one can query the number of tables (and or cells)
**|| row ref count: one can query the number of tables (and/or cells)
**| containing a row as a member or a child.
**|
**|| row content: one can access or modify the cell content in a table's row
@ -1355,11 +1446,38 @@ public:
// { ===== begin nsIMdbTable methods =====
// { ----- begin attribute methods -----
// { ----- begin meta attribute methods -----
virtual mdb_err GetTableKind(nsIMdbEnv* ev, mdb_kind* outTableKind) = 0;
virtual mdb_err GetRowScope(nsIMdbEnv* ev, mdb_scope* outRowScope) = 0;
// } ----- end attribute methods -----
virtual mdb_err GetMetaRow(
nsIMdbEnv* ev, // context
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mdbOid* outOid, // output meta row oid, can be nil to suppress output
nsIMdbRow** acqRow) = 0; // acquire table's unique singleton meta row
// The purpose of a meta row is to support the persistent recording of
// meta info about a table as cells put into the distinguished meta row.
// Each table has exactly one meta row, which is not considered a member
// of the collection of rows inside the table. The only way to tell
// whether a row is a meta row is by the fact that it is returned by this
// GetMetaRow() method from some table. Otherwise nothing distinguishes
// a meta row from any other row. A meta row can be used anyplace that
// any other row can be used, and can even be put into other tables (or
// the same table) as a table member, if this is useful for some reason.
// The first attempt to access a table's meta row using GetMetaRow() will
// cause the meta row to be created if it did not already exist. When the
// meta row is created, it will have the row oid that was previously
// requested for this table's meta row; or if no oid was ever explicitly
// specified for this meta row, then a unique oid will be generated in
// the row scope named "metaScope" (so obviously MDB clients should not
// manually allocate any row IDs from that special meta scope namespace).
// The meta row oid can be specified either when the table is created, or
// else the first time that GetMetaRow() is called, by passing a non-nil
// pointer to an oid for parameter inOptionalMetaRowOid. The meta row's
// actual oid is returned in outOid (if this is a non-nil pointer), and
// it will be different from inOptionalMetaRowOid when the meta row was
// already given a different oid earlier.
// } ----- end meta attribute methods -----
// { ----- begin cursor methods -----
virtual mdb_err GetTableRowCursor( // make a cursor, starting iteration at inRowPos
@ -1374,7 +1492,10 @@ public:
mdb_pos inRowPos, // zero-based ordinal position of row in table
mdbOid* outOid) = 0; // row oid at the specified position
// Note that HasRow() performs the inverse oid->pos mapping
virtual mdb_err RowToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
// } ----- end row position methods -----
// { ----- begin oid set methods -----
@ -1383,6 +1504,11 @@ public:
const mdbOid* inOid) = 0; // row to ensure membership in table
virtual mdb_err HasOid( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_bool* outHasOid) = 0; // whether inOid is a member row
virtual mdb_err OidToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
@ -1395,7 +1521,7 @@ public:
// { ----- begin row set methods -----
virtual mdb_err NewRow( // create a new row instance in table
nsIMdbEnv* ev, // context
mdbOid* ioOid, // please use zero (unbound) rowId for db-assigned IDs
mdbOid* ioOid, // please use minus one (unbound) rowId for db-assigned IDs
nsIMdbRow** acqRow) = 0; // create new row
virtual mdb_err AddRow( // make sure the row with inOid is a table member
@ -1405,7 +1531,7 @@ public:
virtual mdb_err HasRow( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos) = 0; // zero-based ordinal position of row in table
mdb_bool* outHasRow) = 0; // whether row is a table member
virtual mdb_err CutRow( // make sure the row with inOid is not a member
nsIMdbEnv* ev, // context

View File

@ -131,6 +131,12 @@ public: // setup
public: // other space methods
// void ReserveColumnAidCount(mork_count inCount)
// {
// mAtomSpace_HighUnderId = morkAtomSpace_kMinUnderId + inCount;
// mAtomSpace_HighOverId = morkAtomSpace_kMinOverId + inCount;
// }
mork_num CutAllAtoms(morkEnv* ev, morkPool* ioPool);
// CutAllAtoms() puts all the atoms back in the pool.

View File

@ -123,32 +123,25 @@ morkBuilder::morkBuilder(morkEnv* ev,
, mBuilder_OidAtomSpace( 0 )
, mBuilder_ScopeAtomSpace( 0 )
, mBuilder_iso_8859_1( 0 )
, mBuilder_r( (mork_scope) 'r' )
, mBuilder_a( (mork_scope) 'a' )
, mBuilder_t( (mork_scope) 't' )
, mBuilder_MorkNoneToken( 0 )
, mBuilder_PortForm( 0 )
, mBuilder_PortRowScope( (mork_scope) 'r' )
, mBuilder_PortAtomScope( (mork_scope) 'a' )
, mBuilder_PortAtomScope( (mork_scope) 'v' )
, mBuilder_TableForm( 0 )
, mBuilder_TableRowScope( (mork_scope) 'r' )
, mBuilder_TableAtomScope( (mork_scope) 'a' )
, mBuilder_TableAtomScope( (mork_scope) 'v' )
, mBuilder_TableKind( 0 )
, mBuilder_RowForm( 0 )
, mBuilder_RowRowScope( (mork_scope) 'r' )
, mBuilder_RowAtomScope( (mork_scope) 'a' )
, mBuilder_RowAtomScope( (mork_scope) 'v' )
, mBuilder_CellForm( 0 )
, mBuilder_CellAtomScope( (mork_scope) 'a' )
, mBuilder_CellAtomScope( (mork_scope) 'v' )
, mBuilder_DictForm( 0 )
, mBuilder_DictAtomScope( (mork_scope) 'a' )
, mBuilder_DictAtomScope( (mork_scope) 'v' )
, mBuilder_MetaTokenSlot( 0 )
@ -160,7 +153,6 @@ morkBuilder::morkBuilder(morkEnv* ev,
{
if ( ioStore )
{
mBuilder_MorkNoneToken = ioStore->mStore_MorkNoneToken;
morkStore::SlotWeakStore(ioStore, ev, &mBuilder_Store);
if ( ev->Good() )
mNode_Derived = morkDerived_kBuilder;
@ -267,7 +259,7 @@ morkBuilder::OnNewPort(morkEnv* ev, const morkPlace& inPlace)
// mParser_InPort = morkBool_kTrue;
mBuilder_PortForm = 0;
mBuilder_PortRowScope = (mork_scope) 'r';
mBuilder_PortAtomScope = (mork_scope) 'a';
mBuilder_PortAtomScope = (mork_scope) 'v';
}
/*virtual*/ void
@ -337,7 +329,8 @@ morkBuilder::OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan)
morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_change inChange)
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:Meta | OnTableGlitch
// 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
{
@ -345,7 +338,7 @@ morkBuilder::OnNewTable(morkEnv* ev, const morkPlace& inPlace,
mBuilder_TableForm = mBuilder_PortForm;
mBuilder_TableRowScope = mBuilder_PortRowScope;
mBuilder_TableAtomScope = mBuilder_PortAtomScope;
mBuilder_TableKind = mBuilder_MorkNoneToken;
mBuilder_TableKind = morkStore_kNoneToken;
morkTable* table = mBuilder_Store->MidToTable(ev, inMid);
morkTable::SlotStrongTable(table, ev, &mBuilder_Table);
@ -372,7 +365,7 @@ morkBuilder::OnTableEnd(morkEnv* ev, const morkSpan& inSpan)
mBuilder_Row = 0;
mBuilder_Cell = 0;
if ( mBuilder_TableKind == mBuilder_MorkNoneToken )
if ( mBuilder_TableKind == morkStore_kNoneToken )
ev->NewError("missing table kind");
mBuilder_CellAtomScope = mBuilder_RowAtomScope =
@ -407,6 +400,9 @@ morkBuilder::OnMetaEnd(morkEnv* ev, const morkSpan& inSpan)
/*virtual*/ void
morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
const morkMid& inMid, mork_change inChange)
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:MetaTable | OnTableGlitch
// mp:MetaTable ::= OnNewMeta mp:MetaItem* mp:Row OnMetaEnd
// mp:Row ::= OnNewRow mp:RowItem* OnRowEnd
// mp:RowItem ::= mp:Cell | mp:Meta | OnRowGlitch
// mp:Cell ::= OnNewCell mp:CellItem? OnCellEnd
@ -432,8 +428,24 @@ morkBuilder::OnNewRow(morkEnv* ev, const morkPlace& inPlace,
mBuilder_Row = store->MidToRow(ev, inMid);
}
if ( mBuilder_Row )
mBuilder_Table->AddRow(ev, mBuilder_Row);
morkRow* row = mBuilder_Row;
if ( row )
{
morkTable* table = mBuilder_Table;
if ( mParser_InMeta )
{
if ( !table->mTable_MetaRow )
{
table->mTable_MetaRow = row;
table->mTable_MetaRowOid = row->mRow_Oid;
row->AddTableUse(ev);
}
else
ev->NewError("duplicate table meta row");
}
else
table->AddRow(ev, row);
}
}
else
this->NilBuilderTableError(ev);
@ -612,29 +624,29 @@ morkBuilder::OnNewCell(morkEnv* ev, const morkPlace& inPlace,
{
if ( mParser_InTable ) // metainfo for table?
{
if ( column == store->mStore_TableKindToken )
if ( column == morkStore_kKindColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableKind;
else if ( column == store->mStore_RowScopeToken )
else if ( column == morkStore_kRowScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableRowScope;
else if ( column == store->mStore_AtomScopeToken )
else if ( column == morkStore_kAtomScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableAtomScope;
else if ( column == store->mStore_CharsetToken )
else if ( column == morkStore_kFormColumn )
mBuilder_MetaTokenSlot = &mBuilder_TableForm;
}
else if ( mParser_InDict ) // metainfo for dict?
{
if ( column == store->mStore_AtomScopeToken )
if ( column == morkStore_kAtomScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_DictAtomScope;
else if ( column == store->mStore_CharsetToken )
else if ( column == morkStore_kFormColumn )
mBuilder_MetaTokenSlot = &mBuilder_DictForm;
}
else if ( mParser_InRow ) // metainfo for row?
{
if ( column == store->mStore_AtomScopeToken )
if ( column == morkStore_kAtomScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_RowAtomScope;
else if ( column == store->mStore_RowScopeToken )
else if ( column == morkStore_kRowScopeColumn )
mBuilder_MetaTokenSlot = &mBuilder_RowRowScope;
else if ( column == store->mStore_CharsetToken )
else if ( column == morkStore_kFormColumn )
mBuilder_MetaTokenSlot = &mBuilder_RowForm;
}
}
@ -856,7 +868,8 @@ morkBuilder::OnTableMid(morkEnv* ev, const morkSpan& inSpan,
if ( atom )
{
cell->SetAtom(ev, atom, pool);
morkTable* table = store->OidToTable(ev, &tableOid);
morkTable* table = store->OidToTable(ev, &tableOid,
/*optionalMetaRowOid*/ (mdbOid*) 0);
if ( table ) // found or created such a table?
table->AddCellUse(ev);
}

View File

@ -127,15 +127,7 @@ protected: // protected morkBuilder members
// scoped object ids for current objects under construction:
mdbOid mBuilder_TableOid; // full oid for current table
mdbOid mBuilder_RowOid; // full oid for current row
// standard tokens that we want to know about for this port:
mork_cscode mBuilder_iso_8859_1; // token for "iso-8859-1"
mork_cscode mBuilder_r; // token for "r"
mork_cscode mBuilder_a; // token for "a"
mork_cscode mBuilder_t; // token for "t"
mork_token mBuilder_MorkNoneToken; // token for "mork:none"
// tokens that become set as the result of meta cells in port rows:
mork_cscode mBuilder_PortForm; // default port charset format
mork_scope mBuilder_PortRowScope; // port row scope

View File

@ -99,14 +99,17 @@ morkCellObject::morkCellObject(morkEnv* ev, const morkUsage& inUsage,
morkStore* store = ioRow->GetRowSpaceStore(ev);
if ( store )
{
morkRowObject* rowObj = ioRow->GetRowObject(ev, store);
morkRowObject* rowObj = ioRow->AcquireRowObject(ev, store);
if ( rowObj )
{
mCellObject_Row = ioRow;
mCellObject_Cell = ioCell;
mCellObject_RowSeed = ioRow->mRow_Seed;
morkRowObject::SlotStrongRowObject(rowObj, ev,
&mCellObject_RowObject);
// morkRowObject::SlotStrongRowObject(rowObj, ev,
// &mCellObject_RowObject);
mCellObject_RowObject = rowObj; // assume control of strong ref
}
if ( ev->Good() )
mNode_Derived = morkDerived_kCellObject;

View File

@ -87,7 +87,7 @@ const mork_u1 morkCh_Type[] = /* derives from public domain Mithril ch table */
0, /* 0x29 ) cannot be kV because needs escape */
morkCh_kV, /* 0x2A * */
morkCh_kV|morkCh_kM, /* 0x2B + */
0, /* 0x2C , */
morkCh_kV, /* 0x2C , */
morkCh_kV|morkCh_kM, /* 0x2D - */
morkCh_kV, /* 0x2E . */
morkCh_kV, /* 0x2F / */

View File

@ -31,8 +31,8 @@
// { %%%%% begin platform defs peculiar to Mork %%%%%
#ifdef XP_MAC
#define MORK_MAC 1
#define MORK_OBSOLETE 1
#define MORK_MAC 1
#endif
#ifdef XP_OS2

View File

@ -113,7 +113,7 @@ morkHandle::CloseHandle(morkEnv* ev) // called by CloseMorkNode();
this->MarkShut();
if ( objDidRefSelf )
this->CutWeakRef(ev);
this->CutWeakRef(ev); // do last, because it might self destroy
}
else
this->NonNodeError(ev);

View File

@ -917,8 +917,18 @@ void morkParser::ReadMeta(morkEnv* ev, int inEndMeta)
this->UnexpectedByteInMetaWarning(ev);
break;
case '[': // maybe table meta row?
if ( mParser_InTable )
this->ReadRow(ev, '[');
else
this->UnexpectedByteInMetaWarning(ev);
break;
default:
this->UnexpectedByteInMetaWarning(ev);
if ( mParser_InTable && morkCh_IsHex(c) )
this->ReadRow(ev, c);
else
this->UnexpectedByteInMetaWarning(ev);
break;
}
}

View File

@ -379,7 +379,8 @@ public: // out virtual morkParser methods, data flow parser to subclass
// mp:Dict ::= OnNewDict mp:DictItem* OnDictEnd
// mp:DictItem ::= OnAlias | OnAliasGlitch | mp:Meta | OnDictGlitch
// mp:Table ::= OnNewTable mp:TableItem* OnTableEnd
// mp:TableItem ::= mp:Row | mp:Meta | OnTableGlitch
// 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
// mp:Row ::= OnNewRow mp:RowItem* OnRowEnd

View File

@ -217,7 +217,8 @@ morkPool::AddRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize)
ioRow->mRow_Length = inNewSize;
++ioRow->mRow_Seed;
this->ZapCells(ev, oldCells, fill);
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
return ( ev->Good() && ioRow->mRow_Length >= inNewSize );
@ -230,28 +231,42 @@ morkPool::CutRowCells(morkEnv* ev, morkRow* ioRow,
mork_fill fill = ioRow->mRow_Length;
if ( ev->Good() && fill > inNewSize ) // need fewer cells?
{
morkCell* newCells = this->NewCells(ev, inNewSize);
if ( newCells )
if ( inNewSize ) // want any row cells at all?
{
morkCell* newCells = this->NewCells(ev, inNewSize);
if ( newCells )
{
morkCell* oldCells = ioRow->mRow_Cells;
morkCell* oldEnd = oldCells + fill; // one past all old cells
morkCell* newEnd = oldCells + inNewSize; // copy only kept old cells
while ( oldCells < newEnd )
{
*newCells++ = *oldCells++; // bitwise copy each old cell struct
}
while ( oldCells < oldEnd )
{
if ( oldCells->mCell_Atom ) // need to unref old cell atom?
oldCells->SetAtom(ev, (morkAtom*) 0, this); // unref cell atom
++oldCells;
}
oldCells = ioRow->mRow_Cells;
ioRow->mRow_Cells = newCells;
ioRow->mRow_Length = inNewSize;
++ioRow->mRow_Seed;
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
else // get rid of all row cells
{
morkCell* oldCells = ioRow->mRow_Cells;
morkCell* oldEnd = oldCells + fill; // one past all old cells
morkCell* newEnd = oldCells + inNewSize; // copy only kept old cells
while ( oldCells < newEnd )
{
*newCells++ = *oldCells++; // bitwise copy each old cell struct
}
while ( oldCells < oldEnd )
{
if ( oldCells->mCell_Atom ) // need to unref old cell atom?
oldCells->SetAtom(ev, (morkAtom*) 0, this); // unref cell atom
++oldCells;
}
oldCells = ioRow->mRow_Cells;
ioRow->mRow_Cells = newCells;
ioRow->mRow_Length = inNewSize;
ioRow->mRow_Cells = 0;
ioRow->mRow_Length = 0;
++ioRow->mRow_Seed;
this->ZapCells(ev, oldCells, fill);
if ( oldCells )
this->ZapCells(ev, oldCells, fill);
}
}
return ( ev->Good() && ioRow->mRow_Length <= inNewSize );

View File

@ -163,15 +163,18 @@ morkRow::InitRow(morkEnv* ev, const mdbOid* inOid, morkRowSpace* ioSpace,
}
morkRowObject*
morkRow::GetRowObject(morkEnv* ev, morkStore* ioStore)
morkRow::AcquireRowObject(morkEnv* ev, morkStore* ioStore)
{
morkRowObject* ro = mRow_Object;
if ( !ro ) // need new row object?
if ( ro ) // need new row object?
ro->AddStrongRef(ev);
else
{
nsIMdbHeap* heap = ioStore->mPort_Heap;
ro = new (*heap, ev)
morkRowObject(ev, morkUsage::kHeap, heap, this, ioStore);
mRow_Object = ro;
morkRowObject::SlotWeakRowObject(ro, ev, &mRow_Object);
}
return ro;
}
@ -179,10 +182,13 @@ morkRow::GetRowObject(morkEnv* ev, morkStore* ioStore)
nsIMdbRow*
morkRow::AcquireRowHandle(morkEnv* ev, morkStore* ioStore)
{
morkRowObject* object = this->GetRowObject(ev, ioStore);
morkRowObject* object = this->AcquireRowObject(ev, ioStore);
if ( object )
return object->AcquireRowHandle(ev);
{
nsIMdbRow* rowHandle = object->AcquireRowHandle(ev);
object->CutStrongRef(ev);
return rowHandle;
}
return (nsIMdbRow*) 0;
}
@ -387,12 +393,74 @@ morkRow::EmptyAllCells(morkEnv* ev)
}
}
void
morkRow::CutAllColumns(morkEnv* ev)
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
morkPool* pool = store->StorePool();
pool->CutRowCells(ev, this, /*newSize*/ 0);
}
}
void
morkRow::SetRow(morkEnv* ev, const morkRow* inSourceRow)
{
// note inSourceRow might be in another DB, with a different store...
morkStore* store = this->GetRowSpaceStore(ev);
morkStore* srcStore = inSourceRow->GetRowSpaceStore(ev);
if ( store && srcStore )
{
mork_bool sameStore = ( store == srcStore ); // identical stores?
morkPool* pool = store->StorePool();
if ( pool->CutRowCells(ev, this, /*newSize*/ 0) )
{
mork_fill fill = inSourceRow->mRow_Length;
if ( pool->AddRowCells(ev, this, fill) )
{
morkCell* dst = mRow_Cells;
morkCell* dstEnd = dst + mRow_Length;
const morkCell* src = inSourceRow->mRow_Cells;
const morkCell* srcEnd = src + fill;
--dst; --src; // prepare both for preincrement:
while ( ++dst < dstEnd && ++src < srcEnd && ev->Good() )
{
morkAtom* atom = src->mCell_Atom;
mork_column col = src->GetColumn();
if ( sameStore ) // source and dest in same store?
{
dst->SetColumnAndChange(col, morkChange_kAdd);
dst->mCell_Atom = atom;
if ( atom ) // another ref to non-nil atom?
atom->AddCellUse(ev);
}
else // need to dup items from src store in a dest store
{
mork_column dstCol = store->CopyToken(ev, col, srcStore);
if ( dstCol )
{
dst->SetColumnAndChange(dstCol, morkChange_kAdd);
dst->mCell_Atom = store->CopyAtom(ev, atom);
}
}
}
}
}
}
}
void
morkRow::AddRow(morkEnv* ev, const morkRow* inSourceRow)
{
ev->StubMethodOnlyError();
// $$$$$ need to iterate over inSourceRow cells adding them to this row.
// When the atoms are book atoms, we can just incr the use count.
if ( mRow_Length ) // any existing cells we might need to keep?
{
ev->StubMethodOnlyError();
}
else
this->SetRow(ev, inSourceRow); // just exactly duplicate inSourceRow
}
void
@ -444,6 +512,41 @@ morkRow::GetRowSpaceStore(morkEnv* ev) const
return (morkStore*) 0;
}
void morkRow::CutColumn(morkEnv* ev, mdb_column inColumn)
{
mork_pos pos = -1;
morkCell* cell = this->GetCell(ev, inColumn, &pos);
if ( cell )
{
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
morkPool* pool = store->StorePool();
cell->SetAtom(ev, (morkAtom*) 0, pool);
mork_fill fill = mRow_Length; // should not be zero
MORK_ASSERT(fill);
if ( fill ) // index < fill for last cell exists?
{
mork_fill last = fill - 1; // index of last cell in row
if ( pos < last ) // need to move cells following cut cell?
{
morkCell* lastCell = mRow_Cells + last;
mork_count after = last - pos; // cell count after cut cell
morkCell* next = cell + 1; // next cell after cut cell
MORK_MEMMOVE(cell, next, after * sizeof(morkCell));
lastCell->SetColumnAndChange(0, 0);
lastCell->mCell_Atom = 0;
}
if ( ev->Good() )
pool->CutRowCells(ev, this, fill - 1);
}
}
}
}
void morkRow::AddColumn(morkEnv* ev, mdb_column inColumn,
const mdbYarn* inYarn, morkStore* ioStore)
{
@ -475,7 +578,7 @@ morkRow::NewRowCellCursor(morkEnv* ev, mdb_pos inPos)
morkStore* store = this->GetRowSpaceStore(ev);
if ( store )
{
morkRowObject* rowObj = this->GetRowObject(ev, store);
morkRowObject* rowObj = this->AcquireRowObject(ev, store);
if ( rowObj )
{
nsIMdbHeap* heap = store->mPort_Heap;
@ -492,6 +595,7 @@ morkRow::NewRowCellCursor(morkEnv* ev, mdb_pos inPos)
else
cursor->CutStrongRef(ev);
}
rowObj->CutStrongRef(ev); // always cut ref (cursor has its own)
}
}
}

View File

@ -58,7 +58,7 @@ public: // other row methods
mork_size inLength, morkPool* ioPool);
// if inLength is nonzero, cells will be allocated from ioPool
morkRowObject* GetRowObject(morkEnv* ev, morkStore* ioStore);
morkRowObject* AcquireRowObject(morkEnv* ev, morkStore* ioStore);
nsIMdbRow* AcquireRowHandle(morkEnv* ev, morkStore* ioStore);
nsIMdbCell* AcquireCellHandle(morkEnv* ev, morkCell* ioCell,
mdb_column inColumn, mork_pos inPos);
@ -109,10 +109,14 @@ public: // external row methods
void AddColumn(morkEnv* ev, mdb_column inColumn,
const mdbYarn* inYarn, morkStore* ioStore);
void CutColumn(morkEnv* ev, mdb_column inColumn);
morkRowCellCursor* NewRowCellCursor(morkEnv* ev, mdb_pos inPos);
void EmptyAllCells(morkEnv* ev);
void AddRow(morkEnv* ev, const morkRow* inSourceRow);
void SetRow(morkEnv* ev, const morkRow* inSourceRow);
void CutAllColumns(morkEnv* ev);
void OnZeroTableUse(morkEnv* ev);
// OnZeroTableUse() is called when CutTableUse() returns zero.

View File

@ -103,15 +103,16 @@ morkRowObject::CloseRowObject(morkEnv* ev) // called by CloseMorkNode();
if ( row )
{
MORK_ASSERT(row->mRow_Object == this);
if ( row->mRow_Object == this )
{
morkRowObject::SlotWeakRowObject((morkRowObject*) 0, ev,
&row->mRow_Object);
row->mRow_Object = 0; // just nil this slot -- cut ref down below
morkStore::SlotWeakStore((morkStore*) 0, ev,
&mRowObject_Store);
this->CutWeakRef(ev); // do last, because it might self destroy
}
else
MORK_ASSERT(morkBool_kFalse);
}
}
else

View File

@ -232,7 +232,8 @@ morkRowSpace::FindTableByKind(morkEnv* ev, mork_kind inTableKind)
morkTable*
morkRowSpace::NewTableWithTid(morkEnv* ev, mork_tid inTid,
mork_kind inTableKind)
mork_kind inTableKind,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
@ -242,7 +243,7 @@ morkRowSpace::NewTableWithTid(morkEnv* ev, mork_tid inTid,
nsIMdbHeap* heap = mSpace_Store->mPort_Heap;
morkTable* table = new(*heap, ev)
morkTable(ev, morkUsage::kHeap, heap, mSpace_Store, heap, this,
inTid, inTableKind, mustBeUnique);
inOptionalMetaRowOid, inTid, inTableKind, mustBeUnique);
if ( table )
{
if ( mRowSpace_Tables.AddTable(ev, table) )
@ -263,7 +264,8 @@ morkRowSpace::NewTableWithTid(morkEnv* ev, mork_tid inTid,
morkTable*
morkRowSpace::NewTable(morkEnv* ev, mork_kind inTableKind,
mdb_bool inMustBeUnique)
mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
@ -280,7 +282,7 @@ morkRowSpace::NewTable(morkEnv* ev, mork_kind inTableKind,
nsIMdbHeap* heap = mSpace_Store->mPort_Heap;
morkTable* table = new(*heap, ev)
morkTable(ev, morkUsage::kHeap, heap, mSpace_Store, heap, this,
id, inTableKind, inMustBeUnique);
inOptionalMetaRowOid, id, inTableKind, inMustBeUnique);
if ( table )
{
if ( mRowSpace_Tables.AddTable(ev, table) )

View File

@ -113,10 +113,10 @@ public: // other space methods
// CutAllRows() puts all rows and cells back into the pool.
morkTable* NewTable(morkEnv* ev, mork_kind inTableKind,
mdb_bool inMustBeUnique);
mdb_bool inMustBeUnique, const mdbOid* inOptionalMetaRowOid);
morkTable* NewTableWithTid(morkEnv* ev, mork_tid inTid,
mork_kind inTableKind);
mork_kind inTableKind, const mdbOid* inOptionalMetaRowOid);
morkTable* FindTableByKind(morkEnv* ev, mork_kind inTableKind);
morkTable* FindTableByTid(morkEnv* ev, mork_tid inTid)

View File

@ -217,14 +217,6 @@ morkStore::morkStore(morkEnv* ev, const morkUsage& inUsage,
, mStore_GroundAtomSpace( 0 )
, mStore_GroundColumnSpace( 0 )
, mStore_MorkNoneToken( 0 )
, mStore_CharsetToken( 0 )
, mStore_AtomScopeToken( 0 )
, mStore_RowScopeToken( 0 )
, mStore_TableScopeToken( 0 )
, mStore_ColumnScopeToken( 0 )
, mStore_TableKindToken( 0 )
, mStore_RowSpaces(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioPortHeap)
, mStore_AtomSpaces(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioPortHeap)
, mStore_Pool(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioPortHeap)
@ -233,26 +225,6 @@ morkStore::morkStore(morkEnv* ev, const morkUsage& inUsage,
{
mNode_Derived = morkDerived_kStore;
if ( ev->Good() )
mStore_MorkNoneToken = this->StringToToken(ev, "mork:none");
if ( ev->Good() )
mStore_CharsetToken = this->StringToToken(ev, "charset");
if ( ev->Good() )
mStore_AtomScopeToken = this->StringToToken(ev, "atomScope");
if ( ev->Good() )
mStore_RowScopeToken = this->StringToToken(ev, "rowScope");
if ( ev->Good() )
mStore_TableScopeToken = this->StringToToken(ev, "tableScope");
if ( ev->Good() )
mStore_ColumnScopeToken = this->StringToToken(ev, "columnScope");
if ( ev->Good() )
mStore_TableKindToken = this->StringToToken(ev, "tableKind");
}
}
@ -603,6 +575,20 @@ morkStore::CreateStoreFile(morkEnv* ev,
}
return ev->Good();
}
morkAtom*
morkStore::CopyAtom(morkEnv* ev, const morkAtom* inAtom)
// copy inAtom (from some other store) over to this store
{
morkAtom* outAtom = 0;
if ( inAtom )
{
mdbYarn yarn;
if ( inAtom->AliasYarn(&yarn) )
outAtom = this->YarnToAtom(ev, &yarn);
}
return outAtom;
}
morkAtom*
morkStore::YarnToAtom(morkEnv* ev, const mdbYarn* inYarn)
@ -691,7 +677,7 @@ morkStore::MidToTable(morkEnv* ev, const morkMid& inMid)
{
mdbOid tempOid;
this->MidToOid(ev, inMid, &tempOid);
return this->OidToTable(ev, &tempOid);
return this->OidToTable(ev, &tempOid, /*metarow*/ (mdbOid*) 0);
}
mork_bool
@ -769,10 +755,10 @@ morkStore::TokenToString(morkEnv* ev, mdb_token inToken, mdbYarn* outTokenName)
this->SmallTokenToOneByteYarn(ev, inToken, outTokenName);
}
void
morkStore::SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
const mdbOid* inOid)
{
// void
// morkStore::SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
// const mdbOid* inOid)
// {
// mork_token mStore_MorkNoneToken; // token for "mork:none" // fill=9
// mork_column mStore_CharsetToken; // token for "charset" // fill=7
// mork_column mStore_AtomScopeToken; // token for "atomScope" // fill=9
@ -781,55 +767,55 @@ morkStore::SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
// mork_column mStore_ColumnScopeToken; // token for "columnScope" // fill=11
// mork_kind mStore_TableKindToken; // token for "tableKind" // fill=9
// ---------------------ruler-for-token-length-above---123456789012
if ( inOid->mOid_Scope == morkStore_kColumnSpaceScope && inAtom->IsWeeBook() )
{
const mork_u1* body = ((const morkWeeBookAtom*) inAtom)->mWeeBookAtom_Body;
mork_size size = inAtom->mAtom_Size;
if ( size >= 7 && size <= 11 )
{
if ( size == 9 )
{
if ( *body == 'm' )
{
if ( MORK_MEMCMP(body, "mork:none", 9) == 0 )
mStore_MorkNoneToken = inAtom->mBookAtom_Id;
}
else if ( *body == 'a' )
{
if ( MORK_MEMCMP(body, "atomScope", 9) == 0 )
mStore_AtomScopeToken = inAtom->mBookAtom_Id;
}
else if ( *body == 't' )
{
if ( MORK_MEMCMP(body, "tableKind", 9) == 0 )
mStore_TableKindToken = inAtom->mBookAtom_Id;
}
}
else if ( size == 7 && *body == 'c' )
{
if ( MORK_MEMCMP(body, "charset", 7) == 0 )
mStore_CharsetToken = inAtom->mBookAtom_Id;
}
else if ( size == 8 && *body == 'r' )
{
if ( MORK_MEMCMP(body, "rowScope", 8) == 0 )
mStore_RowScopeToken = inAtom->mBookAtom_Id;
}
else if ( size == 10 && *body == 't' )
{
if ( MORK_MEMCMP(body, "tableScope", 10) == 0 )
mStore_TableScopeToken = inAtom->mBookAtom_Id;
}
else if ( size == 11 && *body == 'c' )
{
if ( MORK_MEMCMP(body, "columnScope", 11) == 0 )
mStore_ColumnScopeToken = inAtom->mBookAtom_Id;
}
}
}
}
//
// if ( inOid->mOid_Scope == morkStore_kColumnSpaceScope && inAtom->IsWeeBook() )
// {
// const mork_u1* body = ((const morkWeeBookAtom*) inAtom)->mWeeBookAtom_Body;
// mork_size size = inAtom->mAtom_Size;
//
// if ( size >= 7 && size <= 11 )
// {
// if ( size == 9 )
// {
// if ( *body == 'm' )
// {
// if ( MORK_MEMCMP(body, "mork:none", 9) == 0 )
// mStore_MorkNoneToken = inAtom->mBookAtom_Id;
// }
// else if ( *body == 'a' )
// {
// if ( MORK_MEMCMP(body, "atomScope", 9) == 0 )
// mStore_AtomScopeToken = inAtom->mBookAtom_Id;
// }
// else if ( *body == 't' )
// {
// if ( MORK_MEMCMP(body, "tableKind", 9) == 0 )
// mStore_TableKindToken = inAtom->mBookAtom_Id;
// }
// }
// else if ( size == 7 && *body == 'c' )
// {
// if ( MORK_MEMCMP(body, "charset", 7) == 0 )
// mStore_CharsetToken = inAtom->mBookAtom_Id;
// }
// else if ( size == 8 && *body == 'r' )
// {
// if ( MORK_MEMCMP(body, "rowScope", 8) == 0 )
// mStore_RowScopeToken = inAtom->mBookAtom_Id;
// }
// else if ( size == 10 && *body == 't' )
// {
// if ( MORK_MEMCMP(body, "tableScope", 10) == 0 )
// mStore_TableScopeToken = inAtom->mBookAtom_Id;
// }
// else if ( size == 11 && *body == 'c' )
// {
// if ( MORK_MEMCMP(body, "columnScope", 11) == 0 )
// mStore_ColumnScopeToken = inAtom->mBookAtom_Id;
// }
// }
// }
// }
morkAtom*
morkStore::AddAlias(morkEnv* ev, const morkMid& inMid, mork_cscode inForm)
@ -858,15 +844,15 @@ morkStore::AddAlias(morkEnv* ev, const morkMid& inMid, mork_cscode inForm)
outAtom = atomSpace->MakeBookAtomCopyWithAid(ev,
*keyAtom, (mork_aid) oid->mOid_Id);
if ( outAtom && outAtom->IsWeeBook() )
{
if ( oid->mOid_Scope == morkStore_kColumnSpaceScope )
{
mork_size size = outAtom->mAtom_Size;
if ( size >= 7 && size <= 11 )
this->SyncTokenIdChange(ev, outAtom, oid);
}
}
// if ( outAtom && outAtom->IsWeeBook() )
// {
// if ( oid->mOid_Scope == morkStore_kColumnSpaceScope )
// {
// mork_size size = outAtom->mAtom_Size;
// if ( size >= 7 && size <= 11 )
// this->SyncTokenIdChange(ev, outAtom, oid);
// }
// }
}
}
}
@ -874,6 +860,36 @@ morkStore::AddAlias(morkEnv* ev, const morkMid& inMid, mork_cscode inForm)
return outAtom;
}
#define morkStore_kMaxCopyTokenSize 512 /* if larger, cannot be copied */
mork_token
morkStore::CopyToken(morkEnv* ev, mdb_token inToken, morkStore* inStore)
// copy inToken from inStore over to this store
{
mork_token outToken = 0;
if ( inStore == this ) // same store?
outToken = inToken; // just return token unchanged
else
{
char yarnBuf[ morkStore_kMaxCopyTokenSize ];
mdbYarn yarn;
yarn.mYarn_Buf = yarnBuf;
yarn.mYarn_Fill = 0;
yarn.mYarn_Size = morkStore_kMaxCopyTokenSize;
yarn.mYarn_More = 0;
yarn.mYarn_Form = 0;
yarn.mYarn_Grow = 0;
inStore->TokenToString(ev, inToken, &yarn);
if ( ev->Good() )
{
morkBuf buf(yarn.mYarn_Buf, yarn.mYarn_Fill);
outToken = this->BufToToken(ev, &buf);
}
}
return outToken;
}
mork_token
morkStore::BufToToken(morkEnv* ev, const morkBuf* inBuf)
{
@ -1064,14 +1080,16 @@ morkStore::GetTable(morkEnv* ev, const mdbOid* inOid)
morkTable*
morkStore::NewTable(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind, mdb_bool inMustBeUnique)
mdb_kind inTableKind, mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
{
morkTable* outTable = 0;
if ( ev->Good() )
{
morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inRowScope);
if ( rowSpace )
outTable = rowSpace->NewTable(ev, inTableKind, inMustBeUnique);
outTable = rowSpace->NewTable(ev, inTableKind, inMustBeUnique,
inOptionalMetaRowOid);
}
return outTable;
}
@ -1136,7 +1154,8 @@ morkStore::OidToRow(morkEnv* ev, const mdbOid* inOid)
}
morkTable*
morkStore::OidToTable(morkEnv* ev, const mdbOid* inOid)
morkStore::OidToTable(morkEnv* ev, const mdbOid* inOid,
const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
// OidToTable() finds old table with oid, or makes new one if not found.
{
morkTable* outTable = 0;
@ -1148,8 +1167,9 @@ morkStore::OidToTable(morkEnv* ev, const mdbOid* inOid)
outTable = rowSpace->mRowSpace_Tables.GetTable(ev, inOid->mOid_Id);
if ( !outTable && ev->Good() )
{
mork_kind tableKind = mStore_MorkNoneToken;
outTable = rowSpace->NewTableWithTid(ev, inOid->mOid_Id, tableKind);
mork_kind tableKind = morkStore_kNoneToken;
outTable = rowSpace->NewTableWithTid(ev, inOid->mOid_Id, tableKind,
inOptionalMetaRowOid);
}
}
}

View File

@ -119,6 +119,15 @@ public: // typesafe refcounting inlines calling inherited morkNode methods
#define morkStore_kGroundAtomSpace 'a' /* for mStore_GroundAtomSpace*/
#define morkStore_kStreamBufSize (8 * 1024) /* okay buffer size */
#define morkStore_kReservedColumnCount 0x20 /* for well-known columns */
#define morkStore_kNoneToken ((mork_token) 'n')
#define morkStore_kFormColumn ((mork_column) 'f')
#define morkStore_kAtomScopeColumn ((mork_column) 'a')
#define morkStore_kRowScopeColumn ((mork_column) 'r')
#define morkStore_kMetaScope ((mork_scope) 'm')
#define morkStore_kKindColumn ((mork_column) 'k')
/*| morkStore:
|*/
class morkStore : public morkPort {
@ -151,14 +160,6 @@ public: // state is public because the entire Mork system is private
morkStream* mStore_OutStream; // stream using file used by the writer
mork_token mStore_MorkNoneToken; // token for "mork:none"
mork_column mStore_CharsetToken; // token for "charset"
mork_column mStore_AtomScopeToken; // token for "atomScope"
mork_column mStore_RowScopeToken; // token for "rowScope"
mork_column mStore_TableScopeToken; // token for "tableScope"
mork_column mStore_ColumnScopeToken; // token for "columnScope"
mork_kind mStore_TableKindToken; // token for "tableKind"
morkRowSpaceMap mStore_RowSpaces; // maps mork_scope -> morkSpace
morkAtomSpaceMap mStore_AtomSpaces; // maps mork_scope -> morkSpace
@ -169,8 +170,8 @@ public: // state is public because the entire Mork system is private
public: // coping with any changes to store token slots above:
void SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
const mdbOid* inOid);
// void SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
// const mdbOid* inOid);
public: // building an atom inside mStore_BookAtom from a char* string
@ -252,6 +253,12 @@ public: // other store methods
const char* inFilePath,
const mdbOpenPolicy* inOpenPolicy);
morkAtom* CopyAtom(morkEnv* ev, const morkAtom* inAtom);
// copy inAtom (from some other store) over to this store
mork_token CopyToken(morkEnv* ev, mdb_token inToken, morkStore* inStore);
// copy inToken from inStore over to this store
mork_token BufToToken(morkEnv* ev, const morkBuf* inBuf);
mork_token StringToToken(morkEnv* ev, const char* inTokenName);
mork_token QueryToken(morkEnv* ev, const char* inTokenName);
@ -270,7 +277,8 @@ public: // other store methods
morkRow* OidToRow(morkEnv* ev, const mdbOid* inOid);
// OidToRow() finds old row with oid, or makes new one if not found.
morkTable* OidToTable(morkEnv* ev, const mdbOid* inOid);
morkTable* OidToTable(morkEnv* ev, const mdbOid* inOid,
const mdbOid* inOptionalMetaRowOid);
// OidToTable() finds old table with oid, or makes new one if not found.
static void SmallTokenToOneByteYarn(morkEnv* ev, mdb_token inToken,
@ -287,7 +295,8 @@ public: // other store methods
morkTable* GetTable(morkEnv* ev, const mdbOid* inOid);
morkTable* NewTable(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind, mdb_bool inMustBeUnique);
mdb_kind inTableKind, mdb_bool inMustBeUnique,
const mdbOid* inOptionalMetaRowOid);
morkPortTableCursor* GetPortTableCursor(morkEnv* ev, mdb_scope inRowScope,
mdb_kind inTableKind) ;

View File

@ -92,10 +92,12 @@ morkTable::~morkTable() /*i*/ // assert CloseTable() executed earlier
morkTable::morkTable(morkEnv* ev, /*i*/
const morkUsage& inUsage, nsIMdbHeap* ioHeap,
morkStore* ioStore, nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mork_tid inTid, mork_kind inKind, mork_bool inMustBeUnique)
: morkObject(ev, inUsage, ioHeap, (morkHandle*) 0)
, mTable_Store( 0 )
, mTable_RowSpace( 0 )
, mTable_MetaRow( 0 )
, mTable_Id( inTid )
, mTable_RowMap(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap,
morkTable_kStartRowMapSlotCount)
@ -112,6 +114,13 @@ morkTable::morkTable(morkEnv* ev, /*i*/
{
morkStore::SlotWeakStore(ioStore, ev, &mTable_Store);
morkRowSpace::SlotWeakRowSpace(ioRowSpace, ev, &mTable_RowSpace);
if ( inOptionalMetaRowOid )
mTable_MetaRowOid = *inOptionalMetaRowOid;
else
{
mTable_MetaRowOid.mOid_Scope = 0;
mTable_MetaRowOid.mOid_Id = morkRow_kMinusOneRid;
}
if ( ev->Good() )
mNode_Derived = morkDerived_kTable;
}
@ -194,6 +203,33 @@ morkTable::NilRowSpaceError(morkEnv* ev)
ev->NewError("nil mTable_RowSpace");
}
morkRow*
morkTable::GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid)
{
morkRow* outRow = mTable_MetaRow;
if ( !outRow )
{
morkStore* store = mTable_Store;
mdbOid* oid = &mTable_MetaRowOid;
if ( inOptionalMetaRowOid && !oid->mOid_Scope )
*oid = *inOptionalMetaRowOid;
if ( oid->mOid_Scope ) // oid already recorded in table?
outRow = store->OidToRow(ev, oid);
else
{
outRow = store->NewRow(ev, morkStore_kMetaScope);
if ( outRow ) // need to record new oid in table?
*oid = outRow->mRow_Oid;
}
mTable_MetaRow = outRow;
if ( outRow ) // need to note another use of this row?
outRow->AddTableUse(ev);
}
return outRow;
}
void
morkTable::GetTableOid(morkEnv* ev, mdbOid* outOid)
{
@ -241,14 +277,10 @@ morkTable::ArrayHasOid(morkEnv* ev, const mdbOid* inOid)
return -1;
}
mork_pos
mork_bool
morkTable::MapHasOid(morkEnv* ev, const mdbOid* inOid)
{
morkRow* row = mTable_RowMap.GetOid(ev, inOid);
if ( row )
return 1;
return -1;
return ( mTable_RowMap.GetOid(ev, inOid) != 0 );
}
mork_bool

View File

@ -78,6 +78,9 @@ public: // state is public because the entire Mork system is private
// mTable_RowSpace->mSpace_Scope is row scope
morkRowSpace* mTable_RowSpace; // weak ref to containing space
morkRow* mTable_MetaRow; // table's actual meta row
mdbOid mTable_MetaRowOid; // oid for meta row
morkRowMap mTable_RowMap; // hash table of all members
morkArray mTable_RowArray; // array of morkRow pointers
@ -98,6 +101,7 @@ public: // morkTable construction & destruction
morkTable(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioNodeHeap, morkStore* ioStore,
nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mork_tid inTableId,
mork_kind inKind, mork_bool inMustBeUnique);
void CloseTable(morkEnv* ev); // called by CloseMorkNode();
@ -120,6 +124,8 @@ public: // warnings
static void CellUsesUnderflowWarning(morkEnv* ev);
public: // other table methods
morkRow* GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid);
mork_u2 AddCellUse(morkEnv* ev);
mork_u2 CutCellUse(morkEnv* ev);
@ -134,7 +140,7 @@ public: // other table methods
void GetTableOid(morkEnv* ev, mdbOid* outOid);
mork_pos ArrayHasOid(morkEnv* ev, const mdbOid* inOid);
mork_pos MapHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool MapHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool AddRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()

View File

@ -129,18 +129,16 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage,
, mWriter_MaxIndent( morkWriter_kMaxIndent )
, mWriter_MaxLine( morkWriter_kMaxLine )
, mWriter_TableCharset( 0 )
, mWriter_TableForm( 0 )
, mWriter_TableAtomScope( 0 )
, mWriter_TableRowScope( 0 )
, mWriter_TableTableScope( 0 )
, mWriter_TableColumnScope( 0 )
, mWriter_TableKind( 0 )
, mWriter_RowCharset( 0 )
, mWriter_RowForm( 0 )
, mWriter_RowAtomScope( 0 )
, mWriter_RowScope( 0 )
, mWriter_DictCharset( 0 )
, mWriter_DictForm( 0 )
, mWriter_DictAtomScope( 0 )
, mWriter_NeedDirtyAll( morkBool_kFalse )
@ -372,7 +370,7 @@ morkWriter::WriteYarn(morkEnv* ev, const mdbYarn* inYarn)
stream->Putc(ev, c);
++outSize; // c
}
else if ( c == ')' && c == '$' && c == '\\' )
else if ( c == ')' || c == '$' || c == '\\' )
{
stream->Putc(ev, '\\');
stream->Putc(ev, c);
@ -403,8 +401,8 @@ morkWriter::WriteAtom(morkEnv* ev, const morkAtom* inAtom)
if ( inAtom->AliasYarn(&yarn) )
{
if ( mWriter_DidStartDict && yarn.mYarn_Form != mWriter_DictCharset )
this->ChangeDictCharset(ev, yarn.mYarn_Form);
if ( mWriter_DidStartDict && yarn.mYarn_Form != mWriter_DictForm )
this->ChangeDictForm(ev, yarn.mYarn_Form);
outSize = this->WriteYarn(ev, &yarn);
// mWriter_LineSize += stream->Write(ev, inYarn->mYarn_Buf, outSize);
@ -424,10 +422,10 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace)
{
if ( mWriter_LineSize )
stream->PutLineBreak(ev);
stream->PutString(ev, "< <(atomScope=");
stream->PutString(ev, "< <(a=");
stream->Putc(ev, (int) scope);
++mWriter_LineSize;
stream->PutString(ev, ")> // (charset=iso-8859-1)");
stream->PutString(ev, ")> // (f=iso-8859-1)");
mWriter_LineSize = stream->PutIndent(ev, morkWriter_kDictAliasDepth);
}
else
@ -457,8 +455,8 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace)
atom->AliasYarn(&yarn);
mork_size size = ev->TokenAsHex(idBuf, atom->mBookAtom_Id);
if ( yarn.mYarn_Form != mWriter_DictCharset )
this->ChangeDictCharset(ev, yarn.mYarn_Form);
if ( yarn.mYarn_Form != mWriter_DictForm )
this->ChangeDictForm(ev, yarn.mYarn_Form);
mork_size pending = yarn.mYarn_Fill + size +
morkWriter_kYarnEscapeSlop + 4;
@ -648,7 +646,7 @@ morkWriter::OnDirtyAllDone(morkEnv* ev)
stream->Seek(ev, 0); // beginning of stream
if ( ev->Good() )
{
stream->PutStringThenNewline(ev, "// <!-- <mdb:mork:z v=\"1.1\"/> -->");
stream->PutStringThenNewline(ev, morkWriter_kFileHeader);
mWriter_LineSize = 0;
}
@ -968,17 +966,15 @@ morkWriter::PutTableDict(morkEnv* ev, morkTable* ioTable)
{
morkRowSpace* space = ioTable->mTable_RowSpace;
mWriter_TableRowScope = space->mSpace_Scope;
mWriter_TableCharset = 0; // (charset=iso-8859-1)
mWriter_TableAtomScope = 'a'; // (atomScope=a)
mWriter_TableTableScope = 't'; // (tableScope=t)
mWriter_TableColumnScope = 'c'; // (columnScope=c)
mWriter_TableForm = 0; // (f=iso-8859-1)
mWriter_TableAtomScope = 'v'; // (a=v)
mWriter_TableKind = ioTable->mTable_Kind;
mWriter_RowCharset = mWriter_TableCharset;
mWriter_RowForm = mWriter_TableForm;
mWriter_RowAtomScope = mWriter_TableAtomScope;
mWriter_RowScope = mWriter_TableRowScope;
mWriter_DictCharset = mWriter_TableCharset;
mWriter_DictForm = mWriter_TableForm;
mWriter_DictAtomScope = mWriter_TableAtomScope;
if ( ev->Good() )
@ -986,6 +982,14 @@ morkWriter::PutTableDict(morkEnv* ev, morkTable* ioTable)
if ( ev->Good() )
{
morkRow* r = ioTable->mTable_MetaRow;
if ( r )
{
if ( r->IsRow() )
this->PutRowDict(ev, r);
else
r->NonRowTypeError(ev);
}
morkArray* array = &ioTable->mTable_RowArray; // vector of rows
mork_fill fill = array->mArray_Fill; // count of rows
morkRow** rows = (morkRow**) array->mArray_Slots;
@ -994,7 +998,7 @@ morkWriter::PutTableDict(morkEnv* ev, morkTable* ioTable)
morkRow** end = rows + fill;
while ( rows < end && ev->Good() )
{
morkRow* r = *rows++; // next row to consider
r = *rows++; // next row to consider
if ( r && r->IsRow() )
this->PutRowDict(ev, r);
else
@ -1013,15 +1017,25 @@ morkWriter::WriteTokenToTokenMetaCell(morkEnv* ev,
mork_token inCol, mork_token inValue)
{
morkStream* stream = mWriter_Stream;
char buf[ 128 ]; // buffer for staging the two hex IDs
char* p = buf;
*p++ = '('; // we always start with open paren
*p++ = '^'; // indicates col is hex ID
mork_size colSize = ev->TokenAsHex(p, inCol);
p += colSize;
*p++ = '='; // we always start with open paren
mWriter_LineSize += stream->Write(ev, buf, colSize + 3);
if ( inCol < 0x80 )
{
stream->Putc(ev, '(');
stream->Putc(ev, (char) inCol);
stream->Putc(ev, '=');
}
else
{
char buf[ 128 ]; // buffer for staging the two hex IDs
char* p = buf;
*p++ = '('; // we always start with open paren
*p++ = '^'; // indicates col is hex ID
mork_size colSize = ev->TokenAsHex(p, inCol);
p += colSize;
*p++ = '=';
mWriter_LineSize += stream->Write(ev, buf, colSize + 3);
}
this->IndentAsNeeded(ev, morkWriter_kTableMetaCellValueDepth);
mdbYarn* yarn = &mWriter_ColYarn;
@ -1058,21 +1072,34 @@ morkWriter::WriteStringToTokenDictCell(morkEnv* ev,
}
void
morkWriter::ChangeDictCharset(morkEnv* ev, mork_cscode inNewForm)
morkWriter::ChangeDictForm(morkEnv* ev, mork_cscode inNewForm)
{
if ( inNewForm != mWriter_DictCharset )
if ( inNewForm != mWriter_DictForm )
{
morkStream* stream = mWriter_Stream;
if ( mWriter_LineSize )
stream->PutLineBreak(ev);
mWriter_LineSize = 0;
stream->Putc(ev, '<');
this->WriteStringToTokenDictCell(ev, "(charset=", mWriter_DictCharset);
stream->Putc(ev, '>');
++mWriter_LineSize;
char buf[ 128 ]; // buffer for staging the two hex IDs
char* p = buf;
*p++ = '<'; // we always start with open paren
*p++ = '('; // we always start with open paren
*p++ = (char) morkStore_kFormColumn;
*p++ = '^'; // indicates col is hex ID
mork_size formSize = ev->TokenAsHex(p, inNewForm);
p += formSize;
*p++ = ')';
*p++ = '>';
*p = 0;
mork_size pending = formSize + 6;
this->IndentOverMaxLine(ev, pending, morkWriter_kDictAliasDepth);
mWriter_LineSize += stream->Write(ev, buf, pending);
mWriter_DictCharset = inNewForm;
mWriter_DictForm = inNewForm;
}
}
@ -1091,16 +1118,16 @@ morkWriter::StartDict(morkEnv* ev)
stream->PutLineBreak(ev);
mWriter_LineSize = 0;
stream->PutLineBreak(ev);
if ( mWriter_DictCharset || mWriter_DictAtomScope != 'a' )
if ( mWriter_DictForm || mWriter_DictAtomScope != 'v' )
{
stream->Putc(ev, '<');
stream->Putc(ev, ' ');
stream->Putc(ev, '<');
mWriter_LineSize = 3;
if ( mWriter_DictCharset )
this->WriteStringToTokenDictCell(ev, "(charset=", mWriter_DictCharset);
if ( mWriter_DictAtomScope != 'a' )
this->WriteStringToTokenDictCell(ev, "(atomScope=", mWriter_DictAtomScope);
if ( mWriter_DictForm )
this->WriteStringToTokenDictCell(ev, "(f=", mWriter_DictForm);
if ( mWriter_DictAtomScope != 'v' )
this->WriteStringToTokenDictCell(ev, "(a=", mWriter_DictAtomScope);
stream->Putc(ev, '>');
++mWriter_LineSize;
@ -1149,19 +1176,28 @@ morkWriter::StartTable(morkEnv* ev, morkTable* ioTable)
*p = '{';
mWriter_LineSize += stream->Write(ev, buf, size + 3);
morkStore* store = mWriter_Store;
mork_scope rs = mWriter_TableRowScope;
if ( rs )
{
this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth);
this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs);
}
// mork_scope rs = mWriter_TableRowScope;
// if ( rs )
// {
// this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth);
// this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs);
// }
mork_kind tk = mWriter_TableKind;
if ( tk )
{
this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth);
this->WriteTokenToTokenMetaCell(ev, store->mStore_TableKindToken, tk);
this->WriteTokenToTokenMetaCell(ev, morkStore_kKindColumn, tk);
}
morkRow* r = ioTable->mTable_MetaRow;
if ( r )
{
if ( r->IsRow() )
this->PutRow(ev, r);
else
r->NonRowTypeError(ev);
}
stream->Putc(ev, '}'); // end meta
mWriter_LineSize = stream->PutIndent(ev, morkWriter_kRowCellDepth);
}
@ -1218,6 +1254,22 @@ morkWriter::PutRowDict(morkEnv* ev, morkRow* ioRow)
return ev->Good();
}
mork_bool
morkWriter::IsYarnAllValue(const mdbYarn* inYarn)
{
mork_fill fill = inYarn->mYarn_Fill;
const mork_u1* buf = (const mork_u1*) inYarn->mYarn_Buf;
const mork_u1* end = buf + fill;
--buf; // prepare for preincrement
while ( ++buf < end )
{
mork_ch c = *buf;
if ( !morkCh_IsValue(c) )
return morkBool_kFalse;
}
return morkBool_kTrue;
}
mork_bool
morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow)
{
@ -1243,17 +1295,39 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow)
char* p = idBuf;
colSize = ev->TokenAsHex(p, col);
p += colSize;
mdbYarn yarn; // to ref content inside atom
atom->AliasYarn(&yarn);
if ( atom->IsBook() ) // is it possible to write atom ID?
{
this->IndentAsNeeded(ev, morkWriter_kRowCellDepth);
*p++ = '^';
morkBookAtom* ba = (morkBookAtom*) atom;
mork_size valSize = ev->TokenAsHex(p, ba->mBookAtom_Id);
p += valSize;
*p = ')';
mWriter_LineSize += stream->Write(ev, buf, colSize + valSize + 4);
mork_size valSize = ev->TokenAsHex(p, ba->mBookAtom_Id);
mork_fill yarnFill = yarn.mYarn_Fill;
mork_bool putImmYarn = ( yarnFill <= valSize );
if ( putImmYarn )
putImmYarn = this->IsYarnAllValue(&yarn);
if ( putImmYarn ) // value no bigger than id?
{
p[ -1 ] = '='; // go back and clobber '^' with '=' instead
if ( yarnFill )
{
MORK_MEMCPY(p, yarn.mYarn_Buf, yarnFill);
p += yarnFill;
}
*p++ = ')';
mWriter_LineSize += stream->Write(ev, buf, p - buf);
}
else
{
p += valSize;
*p = ')';
mWriter_LineSize += stream->Write(ev, buf, colSize + valSize + 4);
}
if ( atom->mAtom_Change == morkChange_kAdd )
{
@ -1263,11 +1337,8 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow)
}
else // must write an anonymous atom
{
mdbYarn yarn; // to ref content inside atom
atom->AliasYarn(&yarn);
if ( yarn.mYarn_Form != mWriter_DictCharset )
this->ChangeDictCharset(ev, yarn.mYarn_Form);
if ( yarn.mYarn_Form != mWriter_DictForm )
this->ChangeDictForm(ev, yarn.mYarn_Form);
mork_size pending = yarn.mYarn_Fill + colSize +
morkWriter_kYarnEscapeSlop + 2;
@ -1299,11 +1370,10 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow)
mdbOid* roid = &ioRow->mRow_Oid;
mork_size ridSize = 0;
this->IndentAsNeeded(ev, morkWriter_kRowDepth);
//if ( morkBool_kTrue )
if ( ioRow->IsRowDirty() )
{
stream->PutIndent(ev, morkWriter_kRowDepth);
ioRow->SetRowClean();
mork_rid rid = roid->mOid_Id;
*p++ = '[';
@ -1322,6 +1392,8 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow)
}
else
{
this->IndentAsNeeded(ev, morkWriter_kRowDepth);
if ( roid->mOid_Scope == mWriter_TableRowScope )
ridSize = ev->TokenAsHex(p, roid->mOid_Id);
else

View File

@ -103,6 +103,9 @@
#define morkWriter_kRowCellDepth 4 /* */
#define morkWriter_kRowCellValueDepth 6 /* */
// v=1.1 retired on 23-Mar-98
#define morkWriter_kFileHeader "// <!-- <mdb:mork:z v=\"1.2\"/> -->"
class morkWriter : public morkNode { // row iterator
// public: // slots inherited from morkObject (meant to inform only)
@ -131,18 +134,16 @@ public: // state is public because the entire Mork system is private
mork_size mWriter_MaxIndent; // line size forcing a line break
mork_size mWriter_MaxLine; // line size forcing a value continuation
mork_cscode mWriter_TableCharset; // current charset metainfo
mork_cscode mWriter_TableForm; // current charset metainfo
mork_scope mWriter_TableAtomScope; // current atom scope
mork_scope mWriter_TableRowScope; // current row scope
mork_scope mWriter_TableTableScope; // current table scope
mork_scope mWriter_TableColumnScope; // current column scope
mork_kind mWriter_TableKind; // current table kind
mork_cscode mWriter_RowCharset; // current charset metainfo
mork_cscode mWriter_RowForm; // current charset metainfo
mork_scope mWriter_RowAtomScope; // current atom scope
mork_scope mWriter_RowScope; // current row scope
mork_cscode mWriter_DictCharset; // current charset metainfo
mork_cscode mWriter_DictForm; // current charset metainfo
mork_scope mWriter_DictAtomScope; // current atom scope
mork_bool mWriter_NeedDirtyAll; // need to call DirtyAll()
@ -199,7 +200,7 @@ public: // typing & errors
static void UnsupportedPhaseError(morkEnv* ev);
public: // inlines
void ChangeDictCharset(morkEnv* ev, mork_cscode inNewForm);
void ChangeDictForm(morkEnv* ev, mork_cscode inNewForm);
mork_bool DidStartDict() const { return mWriter_DidStartDict; }
mork_bool DidEndDict() const { return mWriter_DidEndDict; }
@ -269,6 +270,8 @@ public: // writing node content second pass
public: // other writer methods
mork_bool IsYarnAllValue(const mdbYarn* inYarn);
mork_size WriteYarn(morkEnv* ev, const mdbYarn* inYarn);
// return number of atom bytes written on the current line (which
// implies that escaped line breaks will make the size value smaller

View File

@ -60,6 +60,10 @@
#include "morkFile.h"
#endif
#ifndef _MORKWRITER_
#include "morkWriter.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
@ -371,6 +375,7 @@ orkinFactory::CanOpenFilePort(
{
if ( inFilePath && inFirst512Bytes && outCanOpen )
{
canOpenAsPort = this->CanOpenMorkTextFile(ev, inFirst512Bytes);
}
else
ev->NilPointerError();
@ -448,6 +453,21 @@ orkinFactory::ThumbToOpenPort( // redeeming a completed thumb from OpenFilePort(
}
// } ----- end port methods -----
mork_bool
orkinFactory::CanOpenMorkTextFile(morkEnv* ev,
const mdbYarn* inFirst512Bytes)
{
mork_bool outBool = morkBool_kFalse;
mork_size headSize = MORK_STRLEN(morkWriter_kFileHeader);
const mdbYarn* y = inFirst512Bytes;
if ( y && y->mYarn_Buf && y->mYarn_Fill >= headSize )
{
mork_u1* buf = (mork_u1*) y->mYarn_Buf;
outBool = ( MORK_MEMCMP(morkWriter_kFileHeader, buf, headSize) == 0 );
}
return outBool;
}
// { ----- begin store methods -----
/*virtual*/ mdb_err
orkinFactory::CanOpenFileStore(
@ -468,8 +488,8 @@ orkinFactory::CanOpenFileStore(
if ( inFilePath && inFirst512Bytes && outCanOpenAsStore )
{
// right now always say true; later we should look for magic patterns
canOpenAsStore = morkBool_kTrue; // don't bother checking
canOpenAsPort = morkBool_kTrue;
canOpenAsStore = this->CanOpenMorkTextFile(ev, inFirst512Bytes);
canOpenAsPort = canOpenAsStore;
}
else
ev->NilPointerError();

View File

@ -92,6 +92,8 @@ public: // utilities:
mdb_err* outErr) const;
morkEnv* GetInternalFactoryEnv(mdb_err* outErr);
mork_bool CanOpenMorkTextFile(morkEnv* ev, const mdbYarn* inFirst512Bytes);
public: // type identification
mork_bool IsOrkinFactory() const

View File

@ -48,6 +48,10 @@
#include "morkRowObject.h"
#endif
#ifndef _MORKCELLOBJECT_
#include "morkCellObject.h"
#endif
#ifndef _MORKSTORE_
#include "morkStore.h"
#endif
@ -68,6 +72,10 @@
#include "orkinRowCellCursor.h"
#endif
#ifndef _ORKINCELL_
#include "orkinCell.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
/* public virtual*/
@ -463,7 +471,7 @@ orkinRow::CutColumn( // make sure a column is absent from the row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
row->CutColumn(ev, inColumn);
outErr = ev->AsErr();
}
return outErr;
@ -479,7 +487,7 @@ orkinRow::CutAllColumns( // remove all columns from the row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
row->CutAllColumns(ev);
outErr = ev->AsErr();
}
return outErr;
@ -539,7 +547,39 @@ orkinRow::AddCell( // copy a cell from another row to this row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
morkCell* cell = 0;
orkinCell* ocell = (orkinCell*) inCell; // must verify this cast:
if ( ocell->CanUseCell(mev, morkBool_kFalse, &outErr, &cell) )
{
morkCellObject* cellObj = (morkCellObject*) ocell->mHandle_Object;
morkRow* cellRow = cellObj->mCellObject_Row;
if ( cellRow )
{
if ( row != cellRow )
{
morkStore* store = row->GetRowSpaceStore(ev);
morkStore* cellStore = cellRow->GetRowSpaceStore(ev);
if ( store && cellStore )
{
mork_column col = cell->GetColumn();
morkAtom* atom = cell->mCell_Atom;
mdbYarn yarn;
atom->AliasYarn(&yarn); // works even when atom is nil
if ( store != cellStore )
col = store->CopyToken(ev, col, cellStore);
if ( ev->Good() )
row->AddColumn(ev, col, &yarn, store);
}
else
ev->NilPointerError();
}
}
else
ev->NilPointerError();
}
outErr = ev->AsErr();
}
return outErr;
@ -627,7 +667,11 @@ orkinRow::SetRow( // make exact duplicate of another row
&outErr, &row);
if ( ev )
{
ev->StubMethodOnlyError();
morkRow* source = 0;
if ( this->CanUseRow(mev, morkBool_kFalse, &outErr, &source) )
{
row->SetRow(ev, source);
}
outErr = ev->AsErr();
}
return outErr;

View File

@ -677,6 +677,7 @@ orkinStore::NewTable( // make one new table of specific type
mdb_scope inRowScope, // row scope for row ids
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) // acquire scoped collection of rows
{
mdb_err outErr = 0;
@ -686,7 +687,7 @@ orkinStore::NewTable( // make one new table of specific type
{
morkTable* table =
((morkStore*) mHandle_Object)->NewTable(ev, inRowScope,
inTableKind, inMustBeUnique);
inTableKind, inMustBeUnique, inOptionalMetaRowOid);
if ( table && ev->Good() )
outTable = table->AcquireTableHandle(ev);
outErr = ev->AsErr();
@ -695,6 +696,36 @@ orkinStore::NewTable( // make one new table of specific type
*acqTable = outTable;
return outErr;
}
/*virtual*/ mdb_err
orkinStore::NewTableWithOid( // make one new table of specific type
nsIMdbEnv* mev, // context
const mdbOid* inOid, // caller assigned oid
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable) // acquire scoped collection of rows
{
mdb_err outErr = 0;
nsIMdbTable* outTable = 0;
morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkTable* table = ((morkStore*) mHandle_Object)->OidToTable(ev, inOid,
inOptionalMetaRowOid);
if ( table && ev->Good() )
{
table->mTable_Kind = inTableKind;
if ( inMustBeUnique )
table->mTable_MustBeUnique = inMustBeUnique;
outTable = table->AcquireTableHandle(ev);
}
outErr = ev->AsErr();
}
if ( acqTable )
*acqTable = outTable;
return outErr;
}
// } ----- end table methods -----
// { ----- begin row scope methods -----

View File

@ -274,6 +274,15 @@ public: // type identification
mdb_scope inRowScope, // row scope for row ids
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable); // acquire scoped collection of rows
virtual mdb_err NewTableWithOid( // make one new table of specific type
nsIMdbEnv* ev, // context
const mdbOid* inOid, // caller assigned oid
mdb_kind inTableKind, // the type of table to access
mdb_bool inMustBeUnique, // whether store can hold only one of these
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
nsIMdbTable** acqTable); // acquire scoped collection of rows
// } ----- end table methods -----

View File

@ -383,6 +383,61 @@ orkinTable::GetRowScope(nsIMdbEnv* mev, mdb_scope* outRowScope)
return outErr;
}
/*virtual*/ mdb_err
orkinTable::GetMetaRow( nsIMdbEnv* mev,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mdbOid* outOid, // output meta row oid, can be nil to suppress output
nsIMdbRow** acqRow) // acquire table's unique singleton meta row
// The purpose of a meta row is to support the persistent recording of
// meta info about a table as cells put into the distinguished meta row.
// Each table has exactly one meta row, which is not considered a member
// of the collection of rows inside the table. The only way to tell
// whether a row is a meta row is by the fact that it is returned by this
// GetMetaRow() method from some table. Otherwise nothing distinguishes
// a meta row from any other row. A meta row can be used anyplace that
// any other row can be used, and can even be put into other tables (or
// the same table) as a table member, if this is useful for some reason.
// The first attempt to access a table's meta row using GetMetaRow() will
// cause the meta row to be created if it did not already exist. When the
// meta row is created, it will have the row oid that was previously
// requested for this table's meta row; or if no oid was ever explicitly
// specified for this meta row, then a unique oid will be generated in
// the row scope named "metaScope" (so obviously MDB clients should not
// manually allocate any row IDs from that special meta scope namespace).
// The meta row oid can be specified either when the table is created, or
// else the first time that GetMetaRow() is called, by passing a non-nil
// pointer to an oid for parameter inOptionalMetaRowOid. The meta row's
// actual oid is returned in outOid (if this is a non-nil pointer), and
// it will be different from inOptionalMetaRowOid when the meta row was
// already given a different oid earlier.
{
mdb_err outErr = 0;
nsIMdbRow* outRow = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkTable* table = (morkTable*) mHandle_Object;
morkRow* row = table->GetMetaRow(ev, inOptionalMetaRowOid);
if ( row && ev->Good() )
{
if ( outOid )
*outOid = row->mRow_Oid;
outRow = row->AcquireRowHandle(ev, table->mTable_Store);
}
outErr = ev->AsErr();
}
if ( acqRow )
*acqRow = outRow;
if ( ev->Bad() && outOid )
{
outOid->mOid_Scope = 0;
outOid->mOid_Id = morkRow_kMinusOneRid;
}
return outErr;
}
// } ----- end attribute methods -----
// { ----- begin cursor methods -----
@ -456,6 +511,23 @@ orkinTable::AddOid( // make sure the row with inOid is a table member
/*virtual*/ mdb_err
orkinTable::HasOid( // test for the table position of a row member
nsIMdbEnv* mev, // context
const mdbOid* inOid, // row to find in table
mdb_bool* outHasOid) // whether inOid is a member row
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
if ( outHasOid )
*outHasOid = ((morkTable*) mHandle_Object)->MapHasOid(ev, inOid);
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
orkinTable::OidToPos( // test for the table position of a row member
nsIMdbEnv* mev, // context
const mdbOid* inOid, // row to find in table
mdb_pos* outPos) // zero-based ordinal position of row in table
@ -481,7 +553,17 @@ orkinTable::CutOid( // make sure the row with inOid is not a member
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
morkTable* table = (morkTable*) mHandle_Object;
morkStore* store = table->mTable_Store;
if ( inOid && store )
{
morkRow* row = store->GetRow(ev, inOid);
if ( row )
table->CutRow(ev, row);
}
else
ev->NilPointerError();
outErr = ev->AsErr();
}
return outErr;
@ -496,12 +578,30 @@ orkinTable::NewRow( // create a new row instance in table
nsIMdbRow** acqRow) // create new row
{
mdb_err outErr = 0;
nsIMdbRow* outRow = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
morkTable* table = (morkTable*) mHandle_Object;
morkStore* store = table->mTable_Store;
if ( ioOid && store )
{
morkRow* row = 0;
if ( ioOid->mOid_Id == morkRow_kMinusOneRid )
row = store->NewRow(ev, ioOid->mOid_Scope);
else
row = store->NewRowWithOid(ev, ioOid);
if ( row && table->AddRow(ev, row) )
outRow = row->AcquireRowHandle(ev, store);
}
else
ev->NilPointerError();
outErr = ev->AsErr();
}
if ( acqRow )
*acqRow = outRow;
return outErr;
}
@ -527,6 +627,30 @@ orkinTable::AddRow( // make sure the row with inOid is a table member
/*virtual*/ mdb_err
orkinTable::HasRow( // test for the table position of a row member
nsIMdbEnv* mev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_bool* outBool) // zero-based ordinal position of row in table
{
mdb_err outErr = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
morkRow* row = 0;
orkinRow* orow = (orkinRow*) ioRow;
if ( orow->CanUseRow(mev, /*inMutable*/ morkBool_kFalse, &outErr, &row) )
{
morkTable* table = (morkTable*) mHandle_Object;
if ( outBool )
*outBool = table->MapHasOid(ev, &row->mRow_Oid);
}
outErr = ev->AsErr();
}
return outErr;
}
/*virtual*/ mdb_err
orkinTable::RowToPos( // test for the table position of a row member
nsIMdbEnv* mev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos) // zero-based ordinal position of row in table
@ -535,7 +659,15 @@ orkinTable::HasRow( // test for the table position of a row member
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
morkRow* row = 0;
orkinRow* orow = (orkinRow*) ioRow;
if ( orow->CanUseRow(mev, /*inMutable*/ morkBool_kFalse, &outErr, &row) )
{
morkTable* table = (morkTable*) mHandle_Object;
mork_pos pos = table->ArrayHasOid(ev, &row->mRow_Oid);
if ( outPos )
*outPos = pos;
}
outErr = ev->AsErr();
}
return outErr;
@ -611,7 +743,7 @@ orkinTable::SearchColumnsHint( // advise re future expected search cols
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -626,7 +758,7 @@ orkinTable::SortColumnsHint( // advise re future expected sort columns
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -644,7 +776,7 @@ orkinTable::StartBatchChangeHint( // advise before many adds and cuts
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -668,7 +800,7 @@ orkinTable::EndBatchChangeHint( // advise before many adds and cuts
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -689,7 +821,9 @@ orkinTable::CanSortColumn( // query which col is currently used for sorting
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
if ( outCanSort )
*outCanSort = morkBool_kFalse;
outErr = ev->AsErr();
}
return outErr;
@ -703,12 +837,15 @@ orkinTable::NewSortColumn( // change col used for sorting in the table
nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort
{
mdb_err outErr = 0;
nsIMdbThumb* outThumb = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqThumb )
*acqThumb = outThumb;
return outErr;
}
// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
@ -723,12 +860,15 @@ orkinTable::NewSortColumnWithCompare( // change sort col w/ explicit compare
nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort
{
mdb_err outErr = 0;
nsIMdbThumb* outThumb = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqThumb )
*acqThumb = outThumb;
return outErr;
}
// Note the table will hold a reference to inCompare if this object is used
@ -743,12 +883,15 @@ orkinTable::GetSortColumn( // query which col is currently sorted
mdb_column* outColumn) // col the table uses for sorting (or zero)
{
mdb_err outErr = 0;
mdb_column col = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( outColumn )
*outColumn = col;
return outErr;
}
@ -760,12 +903,15 @@ orkinTable::CloneSortColumn( // view same table with a different sort
nsIMdbThumb** acqThumb) // acquire thumb for incremental table clone
{
mdb_err outErr = 0;
nsIMdbThumb* outThumb = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqThumb )
*acqThumb = outThumb;
return outErr;
}
// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
@ -778,12 +924,15 @@ orkinTable::ThumbToCloneSortTable( // redeem complete CloneSortColumn() thumb
nsIMdbTable** acqTable) // new table instance (or old if sort unchanged)
{
mdb_err outErr = 0;
nsIMdbTable* outTable = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
outErr = ev->AsErr();
}
if ( acqTable )
*acqTable = outTable;
return outErr;
}
// } ----- end sorting methods -----
@ -841,7 +990,8 @@ orkinTable::AddIndex( // create a sorting index for column if possible
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -859,7 +1009,8 @@ orkinTable::CutIndex( // stop supporting a specific column index
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -875,7 +1026,9 @@ orkinTable::HasIndex( // query for current presence of a column index
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
if ( outHasIndex )
*outHasIndex = morkBool_kFalse;
outErr = ev->AsErr();
}
return outErr;
@ -890,7 +1043,7 @@ orkinTable::EnableIndexOnSort( // create an index for col on first sort
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;
@ -906,7 +1059,9 @@ orkinTable::QueryIndexOnSort( // check whether index on sort is enabled
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
if ( outIndexOnSort )
*outIndexOnSort = morkBool_kFalse;
outErr = ev->AsErr();
}
return outErr;
@ -921,7 +1076,7 @@ orkinTable::DisableIndexOnSort( // prevent future index creation on sort
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev )
{
ev->StubMethodOnlyError();
// ev->StubMethodOnlyError(); // legal to do nothing
outErr = ev->AsErr();
}
return outErr;

View File

@ -35,7 +35,7 @@
#include "morkHandle.h"
#endif
#ifndef _MORKTable_
#ifndef _MORKTABLE_
#include "morkTable.h"
#endif
@ -164,11 +164,38 @@ public: // type identification
// { ===== begin nsIMdbTable methods =====
// { ----- begin attribute methods -----
// { ----- begin meta attribute methods -----
virtual mdb_err GetTableKind(nsIMdbEnv* ev, mdb_kind* outTableKind);
virtual mdb_err GetRowScope(nsIMdbEnv* ev, mdb_scope* outRowScope);
// } ----- end attribute methods -----
virtual mdb_err GetMetaRow(
nsIMdbEnv* ev, // context
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mdbOid* outOid, // output meta row oid, can be nil to suppress output
nsIMdbRow** acqRow); // acquire table's unique singleton meta row
// The purpose of a meta row is to support the persistent recording of
// meta info about a table as cells put into the distinguished meta row.
// Each table has exactly one meta row, which is not considered a member
// of the collection of rows inside the table. The only way to tell
// whether a row is a meta row is by the fact that it is returned by this
// GetMetaRow() method from some table. Otherwise nothing distinguishes
// a meta row from any other row. A meta row can be used anyplace that
// any other row can be used, and can even be put into other tables (or
// the same table) as a table member, if this is useful for some reason.
// The first attempt to access a table's meta row using GetMetaRow() will
// cause the meta row to be created if it did not already exist. When the
// meta row is created, it will have the row oid that was previously
// requested for this table's meta row; or if no oid was ever explicitly
// specified for this meta row, then a unique oid will be generated in
// the row scope named "metaScope" (so obviously MDB clients should not
// manually allocate any row IDs from that special meta scope namespace).
// The meta row oid can be specified either when the table is created, or
// else the first time that GetMetaRow() is called, by passing a non-nil
// pointer to an oid for parameter inOptionalMetaRowOid. The meta row's
// actual oid is returned in outOid (if this is a non-nil pointer), and
// it will be different from inOptionalMetaRowOid when the meta row was
// already given a different oid earlier.
// } ----- end meta attribute methods -----
// { ----- begin cursor methods -----
virtual mdb_err GetTableRowCursor( // make a cursor, starting iteration at inRowPos
@ -183,7 +210,11 @@ public: // type identification
mdb_pos inRowPos, // zero-based ordinal position of row in table
mdbOid* outOid); // row oid at the specified position
// Note that HasRow() performs the inverse oid->pos mapping
virtual mdb_err RowToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos); // zero-based ordinal position of row in table
// } ----- end row position methods -----
// { ----- begin oid set methods -----
@ -192,6 +223,11 @@ public: // type identification
const mdbOid* inOid); // row to ensure membership in table
virtual mdb_err HasOid( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_bool* outHasOid); // whether inOid is a member row
virtual mdb_err OidToPos( // test for the table position of a row member
nsIMdbEnv* ev, // context
const mdbOid* inOid, // row to find in table
mdb_pos* outPos); // zero-based ordinal position of row in table
@ -214,7 +250,7 @@ public: // type identification
virtual mdb_err HasRow( // test for the table position of a row member
nsIMdbEnv* ev, // context
nsIMdbRow* ioRow, // row to find in table
mdb_pos* outPos); // zero-based ordinal position of row in table
mdb_bool* outHasRow); // whether row is a table member
virtual mdb_err CutRow( // make sure the row with inOid is not a member
nsIMdbEnv* ev, // context

View File

@ -144,7 +144,7 @@ nsresult nsDBFolderInfo::AddToNewMDB()
nsIMdbStore *store = m_mdb->GetStore();
// create the unique table for the dbFolderInfo.
mdb_err err = store->NewTable(m_mdb->GetEnv(), m_rowScopeToken,
m_tableKindToken, PR_TRUE, &m_mdbTable);
m_tableKindToken, PR_TRUE, nsnull, &m_mdbTable);
// make sure the oid of the table is 1.
struct mdbOid folderInfoTableOID;
@ -179,6 +179,7 @@ nsresult nsDBFolderInfo::InitFromExistingDB()
mdb_pos rowPos;
mdb_count outTableCount; // current number of such tables
mdb_bool mustBeUnique; // whether port can hold only one of these
mdb_bool hasOid;
ret = store->GetTableKind(m_mdb->GetEnv(), m_rowScopeToken, m_tableKindToken, &outTableCount,
&mustBeUnique, &m_mdbTable);
// NS_ASSERTION(mustBeUnique && outTableCount == 1, "only one global db info allowed");
@ -186,7 +187,7 @@ nsresult nsDBFolderInfo::InitFromExistingDB()
if (m_mdbTable)
{
// find singleton row for global info.
ret = m_mdbTable->HasOid(m_mdb->GetEnv(), &gDBFolderInfoOID, &rowPos);
ret = m_mdbTable->HasOid(m_mdb->GetEnv(), &gDBFolderInfoOID, &hasOid);
if (ret == NS_OK)
{
nsIMdbTableRowCursor *rowCursor;

View File

@ -27,6 +27,8 @@
#include "nsRDFCID.h"
#include "nsIRDFResource.h"
#include "nsFileStream.h"
#include "nsIMimeHeaderConverter.h"
//#include "nsMimeHeaderConverter.h"
@ -37,6 +39,7 @@
#include "nsCollationCID.h"
#include "nsIPref.h"
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
@ -448,13 +451,37 @@ NS_IMETHODIMP nsMsgDatabase::OpenMDB(const char *dbName, PRBool create)
else
{
mdbOpenPolicy inOpenPolicy;
mdb_bool canOpen;
mdbYarn outFormatVersion;
char bufFirst512Bytes[512];
mdbYarn first512Bytes;
inOpenPolicy.mOpenPolicy_ScopePlan.mScopeStringSet_Count = 0;
inOpenPolicy.mOpenPolicy_MinMemory = 0;
inOpenPolicy.mOpenPolicy_MaxLazy = 0;
first512Bytes.mYarn_Buf = bufFirst512Bytes;
first512Bytes.mYarn_Size = 512;
first512Bytes.mYarn_Fill = 512;
first512Bytes.mYarn_Form = 0; // what to do with this? we're storing csid in the msg hdr...
ret = myMDBFactory->OpenFileStore(m_mdbEnv, NULL, nativeFileName, &inOpenPolicy,
&thumb);
{
nsIOFileStream *dbStream = new nsIOFileStream(nsFileSpec(dbName));
PRInt32 bytesRead = dbStream->read(bufFirst512Bytes, sizeof(bufFirst512Bytes));
first512Bytes.mYarn_Fill = bytesRead;
dbStream->close();
delete dbStream;
}
ret = myMDBFactory->CanOpenFilePort(m_mdbEnv, nativeFileName, // the file to investigate
&first512Bytes, &canOpen, &outFormatVersion);
if (ret == 0 && canOpen)
{
inOpenPolicy.mOpenPolicy_ScopePlan.mScopeStringSet_Count = 0;
inOpenPolicy.mOpenPolicy_MinMemory = 0;
inOpenPolicy.mOpenPolicy_MaxLazy = 0;
ret = myMDBFactory->OpenFileStore(m_mdbEnv, NULL, nativeFileName, &inOpenPolicy,
&thumb);
}
else
ret = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
}
if (NS_SUCCEEDED(ret) && thumb)
{
@ -627,7 +654,7 @@ nsresult nsMsgDatabase::InitNewDB()
nsIMdbStore *store = GetStore();
// create the unique table for the dbFolderInfo.
mdb_err err = store->NewTable(GetEnv(), m_hdrRowScopeToken,
m_hdrTableKindToken, PR_FALSE, &m_mdbAllMsgHeadersTable);
m_hdrTableKindToken, PR_FALSE, nsnull, &m_mdbAllMsgHeadersTable);
// m_mdbAllMsgHeadersTable->BecomeContent(GetEnv(), &gAllMsgHdrsTableOID);
m_dbFolderInfo = dbFolderInfo;
@ -701,8 +728,7 @@ nsresult nsMsgDatabase::InitMDBInfo()
NS_IMETHODIMP nsMsgDatabase::GetMsgHdrForKey(nsMsgKey key, nsIMessage **pmsgHdr)
{
nsresult err = NS_OK;
mdb_pos rowPos;
mdb_pos desiredRowPos;
mdb_bool hasOid;
mdbOid rowObjectId;
@ -712,29 +738,15 @@ NS_IMETHODIMP nsMsgDatabase::GetMsgHdrForKey(nsMsgKey key, nsIMessage **pmsgHdr)
*pmsgHdr = NULL;
rowObjectId.mOid_Id = key;
rowObjectId.mOid_Scope = m_hdrRowScopeToken;
err = m_mdbAllMsgHeadersTable->HasOid(GetEnv(), &rowObjectId, &desiredRowPos);
if (err == NS_OK)
err = m_mdbAllMsgHeadersTable->HasOid(GetEnv(), &rowObjectId, &hasOid);
if (err == NS_OK && m_mdbStore)
{
nsIMdbTableRowCursor* rowCursor;
rowPos = -1;
err = m_mdbAllMsgHeadersTable->GetTableRowCursor(GetEnv(), rowPos, &rowCursor);
if (err == NS_OK && rowCursor /*rowPos >= 0*/) // ### is rowPos > 0 the right thing to check?
{
do
{
nsIMdbRow *hdrRow;
err = rowCursor->NextRow(GetEnv(), &hdrRow, &rowPos);
if (!NS_SUCCEEDED(err) || rowPos < 0 || !hdrRow)
break;
if (rowPos == desiredRowPos)
{
err = CreateMsgHdr(hdrRow, m_dbName, key, pmsgHdr);
break;
}
}
while (TRUE);
nsIMdbRow *hdrRow;
NS_RELEASE(rowCursor);
err = m_mdbStore->GetRow(GetEnv(), &rowObjectId, &hdrRow);
if (err == NS_OK && hdrRow)
{
err = CreateMsgHdr(hdrRow, m_dbName, key, pmsgHdr);
}
}