/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _MDB_ # include "mdb.h" #endif #ifndef _MORK_ # include "mork.h" #endif #ifndef _MORKNODE_ # include "morkNode.h" #endif #ifndef _MORKROWOBJECT_ # include "morkRowObject.h" #endif #ifndef _MORKENV_ # include "morkEnv.h" #endif #ifndef _MORKSTORE_ # include "morkStore.h" #endif #ifndef _MORKROWCELLCURSOR_ # include "morkRowCellCursor.h" #endif #ifndef _MORKCELLOBJECT_ # include "morkCellObject.h" #endif #ifndef _MORKROW_ # include "morkRow.h" #endif // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` // { ===== begin morkNode interface ===== /*public virtual*/ void morkRowObject::CloseMorkNode( morkEnv* ev) // CloseRowObject() only if open { if (this->IsOpenNode()) { this->MarkClosing(); this->CloseRowObject(ev); this->MarkShut(); } } /*public virtual*/ morkRowObject::~morkRowObject() // assert CloseRowObject() executed earlier { CloseMorkNode(mMorkEnv); MORK_ASSERT(this->IsShutNode()); } /*public non-poly*/ morkRowObject::morkRowObject(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, morkRow* ioRow, morkStore* ioStore) : morkObject(ev, inUsage, ioHeap, morkColor_kNone, (morkHandle*)0), mRowObject_Row(0), mRowObject_Store(0) { if (ev->Good()) { if (ioRow && ioStore) { mRowObject_Row = ioRow; mRowObject_Store = ioStore; // morkRowObjects don't ref-cnt the owning store. if (ev->Good()) mNode_Derived = morkDerived_kRowObject; } else ev->NilPointerError(); } } NS_IMPL_ISUPPORTS_INHERITED(morkRowObject, morkObject, nsIMdbRow) // { ===== begin nsIMdbCollection methods ===== // { ----- begin attribute methods ----- NS_IMETHODIMP morkRowObject::GetSeed(nsIMdbEnv* mev, mdb_seed* outSeed) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { *outSeed = (mdb_seed)mRowObject_Row->mRow_Seed; outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::GetCount(nsIMdbEnv* mev, mdb_count* outCount) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { *outCount = (mdb_count)mRowObject_Row->mRow_Length; outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::GetPort(nsIMdbEnv* mev, nsIMdbPort** acqPort) { nsresult outErr = NS_OK; nsIMdbPort* outPort = 0; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { morkRowSpace* rowSpace = mRowObject_Row->mRow_Space; if (rowSpace && rowSpace->mSpace_Store) { morkStore* store = mRowObject_Row->GetRowSpaceStore(ev); if (store) outPort = store->AcquireStoreHandle(ev); } else ev->NilPointerError(); outErr = ev->AsErr(); } if (acqPort) *acqPort = outPort; return outErr; } // } ----- end attribute methods ----- // { ----- begin cursor methods ----- NS_IMETHODIMP morkRowObject::GetCursor( // make a cursor starting iter at inMemberPos nsIMdbEnv* mev, // context mdb_pos inMemberPos, // zero-based ordinal pos of member in collection nsIMdbCursor** acqCursor) { return this->GetRowCellCursor(mev, inMemberPos, (nsIMdbRowCellCursor**)acqCursor); } // } ----- end cursor methods ----- // { ----- begin ID methods ----- NS_IMETHODIMP morkRowObject::GetOid(nsIMdbEnv* mev, mdbOid* outOid) { *outOid = mRowObject_Row->mRow_Oid; morkEnv* ev = morkEnv::FromMdbEnv(mev); return (ev) ? ev->AsErr() : NS_ERROR_FAILURE; } NS_IMETHODIMP morkRowObject::BecomeContent(nsIMdbEnv* mev, const mdbOid* inOid) { NS_ASSERTION(false, "not implemented"); return NS_ERROR_NOT_IMPLEMENTED; // remember row->MaybeDirtySpaceStoreAndRow(); } // } ----- end ID methods ----- // { ----- begin activity dropping methods ----- NS_IMETHODIMP morkRowObject::DropActivity( // tell collection usage no longer expected nsIMdbEnv* mev) { NS_ASSERTION(false, "not implemented"); return NS_ERROR_NOT_IMPLEMENTED; } // } ----- end activity dropping methods ----- // } ===== end nsIMdbCollection methods ===== // { ===== begin nsIMdbRow methods ===== // { ----- begin cursor methods ----- NS_IMETHODIMP morkRowObject::GetRowCellCursor( // make a cursor starting iteration at // inCellPos nsIMdbEnv* mev, // context mdb_pos inPos, // zero-based ordinal position of cell in row nsIMdbRowCellCursor** acqCursor) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); nsIMdbRowCellCursor* outCursor = 0; if (ev) { morkRowCellCursor* cursor = mRowObject_Row->NewRowCellCursor(ev, inPos); if (cursor) { if (ev->Good()) { cursor->mCursor_Seed = (mork_seed)inPos; outCursor = cursor; NS_ADDREF(cursor); } } outErr = ev->AsErr(); } if (acqCursor) *acqCursor = outCursor; return outErr; } // } ----- end cursor methods ----- // { ----- begin column methods ----- NS_IMETHODIMP morkRowObject::AddColumn( // make sure a particular column is inside row nsIMdbEnv* mev, // context mdb_column inColumn, // column to add const mdbYarn* inYarn) { nsresult outErr = NS_ERROR_FAILURE; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { if (mRowObject_Store && mRowObject_Row) mRowObject_Row->AddColumn(ev, inColumn, inYarn, mRowObject_Store); outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::CutColumn( // make sure a column is absent from the row nsIMdbEnv* mev, // context mdb_column inColumn) { nsresult outErr = NS_ERROR_FAILURE; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { mRowObject_Row->CutColumn(ev, inColumn); outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::CutAllColumns( // remove all columns from the row nsIMdbEnv* mev) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { mRowObject_Row->CutAllColumns(ev); outErr = ev->AsErr(); } return outErr; } // } ----- end column methods ----- // { ----- begin cell methods ----- NS_IMETHODIMP morkRowObject::NewCell( // get cell for specified column, or add new one nsIMdbEnv* mev, // context mdb_column inColumn, // column to add nsIMdbCell** acqCell) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { GetCell(mev, inColumn, acqCell); if (!*acqCell) { if (mRowObject_Store) { mdbYarn yarn; // to pass empty yarn into morkRowObject::AddColumn() yarn.mYarn_Buf = 0; yarn.mYarn_Fill = 0; yarn.mYarn_Size = 0; yarn.mYarn_More = 0; yarn.mYarn_Form = 0; yarn.mYarn_Grow = 0; AddColumn(ev, inColumn, &yarn); GetCell(mev, inColumn, acqCell); } } outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::AddCell( // copy a cell from another row to this row nsIMdbEnv* mev, // context const nsIMdbCell* inCell) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { morkCell* cell = 0; morkCellObject* cellObj = (morkCellObject*)inCell; if (cellObj->CanUseCell(mev, morkBool_kFalse, &outErr, &cell)) { morkRow* cellRow = cellObj->mCellObject_Row; if (cellRow) { if (mRowObject_Row != cellRow) { morkStore* store = mRowObject_Row->GetRowSpaceStore(ev); morkStore* cellStore = cellRow->GetRowSpaceStore(ev); if (store && cellStore) { mork_column col = cell->GetColumn(); morkAtom* atom = cell->mCell_Atom; mdbYarn yarn; morkAtom::AliasYarn(atom, &yarn); // works even when atom is nil if (store != cellStore) col = store->CopyToken(ev, col, cellStore); if (ev->Good()) AddColumn(ev, col, &yarn); } else ev->NilPointerError(); } } else ev->NilPointerError(); } outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::GetCell( // find a cell in this row nsIMdbEnv* mev, // context mdb_column inColumn, // column to find nsIMdbCell** acqCell) { nsresult outErr = NS_OK; nsIMdbCell* outCell = 0; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { if (inColumn) { mork_pos pos = 0; morkCell* cell = mRowObject_Row->GetCell(ev, inColumn, &pos); if (cell) { outCell = mRowObject_Row->AcquireCellHandle(ev, cell, inColumn, pos); } } else mRowObject_Row->ZeroColumnError(ev); outErr = ev->AsErr(); } if (acqCell) *acqCell = outCell; return outErr; } NS_IMETHODIMP morkRowObject::EmptyAllCells( // make all cells in row empty of content nsIMdbEnv* mev) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { EmptyAllCells(ev); outErr = ev->AsErr(); } return outErr; } // } ----- end cell methods ----- // { ----- begin row methods ----- NS_IMETHODIMP morkRowObject::AddRow( // add all cells in another row to this one nsIMdbEnv* mev, // context nsIMdbRow* ioSourceRow) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { morkRow* unsafeSource = (morkRow*)ioSourceRow; // unsafe cast // if ( unsafeSource->CanUseRow(mev, morkBool_kFalse, &outErr, &source) ) { mRowObject_Row->AddRow(ev, unsafeSource); } outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::SetRow( // make exact duplicate of another row nsIMdbEnv* mev, // context nsIMdbRow* ioSourceRow) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { morkRowObject* sourceObject = (morkRowObject*)ioSourceRow; // unsafe cast morkRow* unsafeSource = sourceObject->mRowObject_Row; // if ( unsafeSource->CanUseRow(mev, morkBool_kFalse, &outErr, &source) ) { mRowObject_Row->SetRow(ev, unsafeSource); } outErr = ev->AsErr(); } return outErr; } // } ----- end row methods ----- // { ----- begin blob methods ----- NS_IMETHODIMP morkRowObject::SetCellYarn( // synonym for AddColumn() nsIMdbEnv* mev, // context mdb_column inColumn, // column to add const mdbYarn* inYarn) { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { if (mRowObject_Store) AddColumn(ev, inColumn, inYarn); outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::GetCellYarn(nsIMdbEnv* mev, // context mdb_column inColumn, // column to read mdbYarn* outYarn) // writes some yarn slots // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { if (mRowObject_Store && mRowObject_Row) { morkAtom* atom = mRowObject_Row->GetColumnAtom(ev, inColumn); morkAtom::GetYarn(atom, outYarn); } outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::AliasCellYarn(nsIMdbEnv* mev, // context mdb_column inColumn, // column to alias mdbYarn* outYarn) // writes ALL yarn slots { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { if (mRowObject_Store && mRowObject_Row) { morkAtom* atom = mRowObject_Row->GetColumnAtom(ev, inColumn); morkAtom::AliasYarn(atom, outYarn); // note nil atom works and sets yarn correctly } outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::NextCellYarn( nsIMdbEnv* mev, // iterative version of GetCellYarn() mdb_column* ioColumn, // next column to read mdbYarn* outYarn) // writes some yarn slots // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form // // The ioColumn argument is an inout parameter which initially contains the // last column accessed and returns the next column corresponding to the // content read into the yarn. Callers should start with a zero column // value to say 'no previous column', which causes the first column to be // read. Then the value returned in ioColumn is perfect for the next call // to NextCellYarn(), since it will then be the previous column accessed. // Callers need only examine the column token returned to see which cell // in the row is being read into the yarn. When no more columns remain, // and the iteration has ended, ioColumn will return a zero token again. // So iterating over cells starts and ends with a zero column token. { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { if (mRowObject_Store && mRowObject_Row) mRowObject_Row->NextColumn(ev, ioColumn, outYarn); outErr = ev->AsErr(); } return outErr; } NS_IMETHODIMP morkRowObject::SeekCellYarn( // resembles nsIMdbRowCellCursor::SeekCell() nsIMdbEnv* mev, // context mdb_pos inPos, // position of cell in row sequence mdb_column* outColumn, // column for this particular cell mdbYarn* outYarn) // writes some yarn slots // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form // Callers can pass nil for outYarn to indicate no interest in content, so // only the outColumn value is returned. NOTE to subclasses: you must be // able to ignore outYarn when the pointer is nil; please do not crash. { nsresult outErr = NS_OK; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { if (mRowObject_Store && mRowObject_Row) mRowObject_Row->SeekColumn(ev, inPos, outColumn, outYarn); outErr = ev->AsErr(); } return outErr; } // } ----- end blob methods ----- // } ===== end nsIMdbRow methods ===== /*public non-poly*/ void morkRowObject::CloseRowObject( morkEnv* ev) // called by CloseMorkNode(); { if (this->IsNode()) { morkRow* row = mRowObject_Row; mRowObject_Row = 0; this->CloseObject(ev); this->MarkShut(); if (row) { MORK_ASSERT(row->mRow_Object == this); if (row->mRow_Object == this) { row->mRow_Object = 0; // just nil this slot -- cut ref down below mRowObject_Store = 0; // morkRowObjects don't ref-cnt the owning store. this->CutWeakRef( ev->AsMdbEnv()); // do last, because it might self destroy } } } else this->NonNodeError(ev); } // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` /*static*/ void morkRowObject::NonRowObjectTypeError(morkEnv* ev) { ev->NewError("non morkRowObject"); } /*static*/ void morkRowObject::NilRowError(morkEnv* ev) { ev->NewError("nil mRowObject_Row"); } /*static*/ void morkRowObject::NilStoreError(morkEnv* ev) { ev->NewError("nil mRowObject_Store"); } /*static*/ void morkRowObject::RowObjectRowNotSelfError(morkEnv* ev) { ev->NewError("mRowObject_Row->mRow_Object != self"); } nsIMdbRow* morkRowObject::AcquireRowHandle(morkEnv* ev) // mObject_Handle { AddRef(); return this; } // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789