/* -*- 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 //3456789_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; } //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789