Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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 _MORKENV_
# include "morkEnv.h"
#endif
#ifndef _MORKCURSOR_
# include "morkCursor.h"
#endif
#ifndef _MORKTABLEROWCURSOR_
# include "morkTableRowCursor.h"
#endif
#ifndef _MORKSTORE_
# include "morkStore.h"
#endif
#ifndef _MORKTABLE_
# include "morkTable.h"
#endif
#ifndef _MORKROW_
# include "morkRow.h"
#endif
// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====
/*public virtual*/ void morkTableRowCursor::CloseMorkNode(
morkEnv* ev) // CloseTableRowCursor() only if open
{
if (this->IsOpenNode()) {
this->MarkClosing();
this->CloseTableRowCursor(ev);
this->MarkShut();
}
}
/*public virtual*/
morkTableRowCursor::~morkTableRowCursor() // CloseTableRowCursor() executed
// earlier
{
CloseMorkNode(mMorkEnv);
MORK_ASSERT(this->IsShutNode());
}
/*public non-poly*/
morkTableRowCursor::morkTableRowCursor(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, morkTable* ioTable,
mork_pos inRowPos)
: morkCursor(ev, inUsage, ioHeap), mTableRowCursor_Table(0) {
if (ev->Good()) {
if (ioTable) {
mCursor_Pos = inRowPos;
mCursor_Seed = ioTable->TableSeed();
morkTable::SlotWeakTable(ioTable, ev, &mTableRowCursor_Table);
if (ev->Good()) mNode_Derived = morkDerived_kTableRowCursor;
} else
ev->NilPointerError();
}
}
NS_IMPL_ISUPPORTS_INHERITED(morkTableRowCursor, morkCursor,
nsIMdbTableRowCursor)
/*public non-poly*/ void morkTableRowCursor::CloseTableRowCursor(morkEnv* ev) {
if (this->IsNode()) {
mCursor_Pos = -1;
mCursor_Seed = 0;
morkTable::SlotWeakTable((morkTable*)0, ev, &mTableRowCursor_Table);
this->CloseCursor(ev);
this->MarkShut();
} else
this->NonNodeError(ev);
}
// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````
// { ----- begin attribute methods -----
/*virtual*/ nsresult morkTableRowCursor::GetCount(nsIMdbEnv* mev,
mdb_count* outCount) {
nsresult outErr = NS_OK;
mdb_count count = 0;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
count = GetMemberCount(ev);
outErr = ev->AsErr();
}
if (outCount) *outCount = count;
return outErr;
}
/*virtual*/ nsresult morkTableRowCursor::GetSeed(nsIMdbEnv* mev,
mdb_seed* outSeed) {
NS_ASSERTION(false, "not implemented");
return NS_ERROR_NOT_IMPLEMENTED;
}
/*virtual*/ nsresult morkTableRowCursor::SetPos(nsIMdbEnv* mev, mdb_pos inPos) {
mCursor_Pos = inPos;
return NS_OK;
}
/*virtual*/ nsresult morkTableRowCursor::GetPos(nsIMdbEnv* mev,
mdb_pos* outPos) {
*outPos = mCursor_Pos;
return NS_OK;
}
/*virtual*/ nsresult morkTableRowCursor::SetDoFailOnSeedOutOfSync(
nsIMdbEnv* mev, mdb_bool inFail) {
mCursor_DoFailOnSeedOutOfSync = inFail;
return NS_OK;
}
/*virtual*/ nsresult morkTableRowCursor::GetDoFailOnSeedOutOfSync(
nsIMdbEnv* mev, mdb_bool* outFail) {
NS_ENSURE_ARG_POINTER(outFail);
*outFail = mCursor_DoFailOnSeedOutOfSync;
return NS_OK;
}
// } ----- end attribute methods -----
// { ===== begin nsIMdbTableRowCursor methods =====
// { ----- begin attribute methods -----
NS_IMETHODIMP
morkTableRowCursor::GetTable(nsIMdbEnv* mev, nsIMdbTable** acqTable) {
nsresult outErr = NS_OK;
nsIMdbTable* outTable = 0;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
if (mTableRowCursor_Table)
outTable = mTableRowCursor_Table->AcquireTableHandle(ev);
outErr = ev->AsErr();
}
if (acqTable) *acqTable = outTable;
return outErr;
}
// } ----- end attribute methods -----
// { ----- begin oid iteration methods -----
NS_IMETHODIMP
morkTableRowCursor::NextRowOid( // get row id of next row in the table
nsIMdbEnv* mev, // context
mdbOid* outOid, // out row oid
mdb_pos* outRowPos) {
nsresult outErr = NS_OK;
mork_pos pos = -1;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
if (outOid) {
pos = NextRowOid(ev, outOid);
} else
ev->NilPointerError();
outErr = ev->AsErr();
}
if (outRowPos) *outRowPos = pos;
return outErr;
}
NS_IMETHODIMP
morkTableRowCursor::PrevRowOid( // get row id of previous row in the table
nsIMdbEnv* mev, // context
mdbOid* outOid, // out row oid
mdb_pos* outRowPos) {
nsresult outErr = NS_OK;
mork_pos pos = -1;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
if (outOid) {
pos = PrevRowOid(ev, outOid);
} else
ev->NilPointerError();
outErr = ev->AsErr();
}
if (outRowPos) *outRowPos = pos;
return outErr;
}
// } ----- end oid iteration methods -----
// { ----- begin row iteration methods -----
NS_IMETHODIMP
morkTableRowCursor::NextRow( // get row cells from table for cells already in
// row
nsIMdbEnv* mev, // context
nsIMdbRow** acqRow, // acquire next row in table
mdb_pos* outRowPos) {
nsresult outErr = NS_OK;
nsIMdbRow* outRow = 0;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
mdbOid oid; // place to put oid we intend to ignore
morkRow* row = NextRow(ev, &oid, outRowPos);
if (row) {
morkStore* store = row->GetRowSpaceStore(ev);
if (store) outRow = row->AcquireRowHandle(ev, store);
}
outErr = ev->AsErr();
}
if (acqRow) *acqRow = outRow;
return outErr;
}
NS_IMETHODIMP
morkTableRowCursor::PrevRow( // get row cells from table for cells already in
// row
nsIMdbEnv* mev, // context
nsIMdbRow** acqRow, // acquire previous row in table
mdb_pos* outRowPos) {
nsresult outErr = NS_OK;
nsIMdbRow* outRow = 0;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
mdbOid oid; // place to put oid we intend to ignore
morkRow* row = PrevRow(ev, &oid, outRowPos);
if (row) {
morkStore* store = row->GetRowSpaceStore(ev);
if (store) outRow = row->AcquireRowHandle(ev, store);
}
outErr = ev->AsErr();
}
if (acqRow) *acqRow = outRow;
return outErr;
}
// } ----- end row iteration methods -----
// { ----- begin duplicate row removal methods -----
NS_IMETHODIMP
morkTableRowCursor::CanHaveDupRowMembers(
nsIMdbEnv* mev, // cursor might hold dups?
mdb_bool* outCanHaveDups) {
nsresult outErr = NS_OK;
mdb_bool canHaveDups = mdbBool_kFalse;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
canHaveDups = CanHaveDupRowMembers(ev);
outErr = ev->AsErr();
}
if (outCanHaveDups) *outCanHaveDups = canHaveDups;
return outErr;
}
NS_IMETHODIMP
morkTableRowCursor::MakeUniqueCursor( // clone cursor, removing duplicate rows
nsIMdbEnv* mev, // context
nsIMdbTableRowCursor** acqCursor) // acquire clone with no dups
// Note that MakeUniqueCursor() is never necessary for a cursor which was
// created by table method nsIMdbTable::GetTableRowCursor(), because a table
// never contains the same row as a member more than once. However, a cursor
// created by table method nsIMdbTable::FindRowMatches() might contain the
// same row more than once, because the same row can generate a hit by more
// than one column with a matching string prefix. Note this method can
// return the very same cursor instance with just an incremented refcount,
// when the original cursor could not contain any duplicate rows (calling
// CanHaveDupRowMembers() shows this case on a false return). Otherwise
// this method returns a different cursor instance. Callers should not use
// this MakeUniqueCursor() method lightly, because it tends to defeat the
// purpose of lazy programming techniques, since it can force creation of
// an explicit row collection in a new cursor's representation, in order to
// inspect the row membership and remove any duplicates; this can have big
// impact if a collection holds tens of thousands of rows or more, when
// the original cursor with dups simply referenced rows indirectly by row
// position ranges, without using an explicit row set representation.
// Callers are encouraged to use nsIMdbCursor::GetCount() to determine
// whether the row collection is very large (tens of thousands), and to
// delay calling MakeUniqueCursor() when possible, until a user interface
// element actually demands the creation of an explicit set representation.
{
nsresult outErr = NS_OK;
nsIMdbTableRowCursor* outCursor = 0;
morkEnv* ev = morkEnv::FromMdbEnv(mev);
if (ev) {
AddRef();
outCursor = this;
outErr = ev->AsErr();
}
if (acqCursor) *acqCursor = outCursor;
return outErr;
}
// } ----- end duplicate row removal methods -----
// } ===== end nsIMdbTableRowCursor methods =====
/*static*/ void morkTableRowCursor::NonTableRowCursorTypeError(morkEnv* ev) {
ev->NewError("non morkTableRowCursor");
}
mdb_pos morkTableRowCursor::NextRowOid(morkEnv* ev, mdbOid* outOid) {
mdb_pos outPos = -1;
(void)this->NextRow(ev, outOid, &outPos);
return outPos;
}
mdb_pos morkTableRowCursor::PrevRowOid(morkEnv* ev, mdbOid* outOid) {
mdb_pos outPos = -1;
(void)this->PrevRow(ev, outOid, &outPos);
return outPos;
}
mork_bool morkTableRowCursor::CanHaveDupRowMembers(morkEnv* ev) {
return morkBool_kFalse; // false default is correct
}
mork_count morkTableRowCursor::GetMemberCount(morkEnv* ev) {
morkTable* table = mTableRowCursor_Table;
if (table)
return table->mTable_RowArray.mArray_Fill;
else
return 0;
}
morkRow* morkTableRowCursor::PrevRow(morkEnv* ev, mdbOid* outOid,
mdb_pos* outPos) {
morkRow* outRow = 0;
mork_pos pos = -1;
morkTable* table = mTableRowCursor_Table;
if (table) {
if (table->IsOpenNode()) {
morkArray* array = &table->mTable_RowArray;
pos = mCursor_Pos - 1;
if (pos >= 0 && pos < (mork_pos)(array->mArray_Fill)) {
mCursor_Pos = pos; // update for next time
morkRow* row = (morkRow*)array->At(pos);
if (row) {
if (row->IsRow()) {
outRow = row;
*outOid = row->mRow_Oid;
} else
row->NonRowTypeError(ev);
} else
ev->NilPointerError();
} else {
outOid->mOid_Scope = 0;
outOid->mOid_Id = morkId_kMinusOne;
}
} else
table->NonOpenNodeError(ev);
} else
ev->NilPointerError();
*outPos = pos;
return outRow;
}
morkRow* morkTableRowCursor::NextRow(morkEnv* ev, mdbOid* outOid,
mdb_pos* outPos) {
morkRow* outRow = 0;
mork_pos pos = -1;
morkTable* table = mTableRowCursor_Table;
if (table) {
if (table->IsOpenNode()) {
morkArray* array = &table->mTable_RowArray;
pos = mCursor_Pos;
if (pos < 0)
pos = 0;
else
++pos;
if (pos < (mork_pos)(array->mArray_Fill)) {
mCursor_Pos = pos; // update for next time
morkRow* row = (morkRow*)array->At(pos);
if (row) {
if (row->IsRow()) {
outRow = row;
*outOid = row->mRow_Oid;
} else
row->NonRowTypeError(ev);
} else
ev->NilPointerError();
} else {
outOid->mOid_Scope = 0;
outOid->mOid_Id = morkId_kMinusOne;
}
} else
table->NonOpenNodeError(ev);
} else
ev->NilPointerError();
*outPos = pos;
return outRow;
}
// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789