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 _MORKROW_
#define _MORKROW_ 1
#ifndef _MORK_
# include "mork.h"
#endif
#ifndef _MORKCELL_
# include "morkCell.h"
#endif
// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class nsIMdbRow;
class nsIMdbCell;
#define morkDerived_kRow /*i*/ 0x5277 /* ascii 'Rw' */
#define morkRow_kMaxGcUses 0x0FF /* max for 8-bit unsigned int */
#define morkRow_kMaxLength 0x0FFFF /* max for 16-bit unsigned int */
#define morkRow_kMinusOneRid ((mork_rid)-1)
#define morkRow_kTag 'r' /* magic signature for mRow_Tag */
#define morkRow_kNotedBit ((mork_u1)(1 << 0)) /* space has change notes */
#define morkRow_kRewriteBit ((mork_u1)(1 << 1)) /* must rewrite all cells */
#define morkRow_kDirtyBit ((mork_u1)(1 << 2)) /* row has been changed */
class morkRow { // row of cells
public: // state is public because the entire Mork system is private
morkRowSpace* mRow_Space; // mRow_Space->SpaceScope() is the row scope
morkRowObject* mRow_Object; // refcount & other state for object sharing
morkCell* mRow_Cells;
mdbOid mRow_Oid;
mork_delta mRow_Delta; // space to note a single column change
mork_u2 mRow_Length; // physical count of cells in mRow_Cells
mork_u2 mRow_Seed; // count changes in mRow_Cells structure
mork_u1 mRow_GcUses; // persistent references from tables
mork_u1 mRow_Pad; // for u1 alignment
mork_u1 mRow_Flags; // one-byte flags slot
mork_u1 mRow_Tag; // one-byte tag (need u4 alignment pad)
public: // interpreting mRow_Delta
mork_bool HasRowDelta() const { return (mRow_Delta != 0); }
void ClearRowDelta() { mRow_Delta = 0; }
void SetRowDelta(mork_column inCol, mork_change inChange) {
morkDelta_Init(mRow_Delta, inCol, inChange);
}
mork_column GetDeltaColumn() const { return morkDelta_Column(mRow_Delta); }
mork_change GetDeltaChange() const { return morkDelta_Change(mRow_Delta); }
public: // noting row changes
void NoteRowSetAll(morkEnv* ev);
void NoteRowSetCol(morkEnv* ev, mork_column inCol);
void NoteRowAddCol(morkEnv* ev, mork_column inCol);
void NoteRowCutCol(morkEnv* ev, mork_column inCol);
public: // flags bit twiddling
void SetRowNoted() { mRow_Flags |= morkRow_kNotedBit; }
void SetRowRewrite() { mRow_Flags |= morkRow_kRewriteBit; }
void SetRowDirty() { mRow_Flags |= morkRow_kDirtyBit; }
void ClearRowNoted() { mRow_Flags &= (mork_u1)~morkRow_kNotedBit; }
void ClearRowRewrite() { mRow_Flags &= (mork_u1)~morkRow_kRewriteBit; }
void SetRowClean() {
mRow_Flags = 0;
mRow_Delta = 0;
}
mork_bool IsRowNoted() const { return (mRow_Flags & morkRow_kNotedBit) != 0; }
mork_bool IsRowRewrite() const {
return (mRow_Flags & morkRow_kRewriteBit) != 0;
}
mork_bool IsRowClean() const { return (mRow_Flags & morkRow_kDirtyBit) == 0; }
mork_bool IsRowDirty() const { return (mRow_Flags & morkRow_kDirtyBit) != 0; }
mork_bool IsRowUsed() const { return mRow_GcUses != 0; }
public: // other row methods
morkRow() {}
explicit morkRow(const mdbOid* inOid) : mRow_Oid(*inOid) {}
void InitRow(morkEnv* ev, const mdbOid* inOid, morkRowSpace* ioSpace,
mork_size inLength, morkPool* ioPool);
// if inLength is nonzero, cells will be allocated from ioPool
morkRowObject* AcquireRowObject(morkEnv* ev, morkStore* ioStore);
nsIMdbRow* AcquireRowHandle(morkEnv* ev, morkStore* ioStore);
nsIMdbCell* AcquireCellHandle(morkEnv* ev, morkCell* ioCell,
mdb_column inColumn, mork_pos inPos);
mork_u2 AddRowGcUse(morkEnv* ev);
mork_u2 CutRowGcUse(morkEnv* ev);
mork_bool MaybeDirtySpaceStoreAndRow();
public: // internal row methods
void cut_all_index_entries(morkEnv* ev);
// void cut_cell_from_space_index(morkEnv* ev, morkCell* ioCell);
mork_count CountOverlap(morkEnv* ev, morkCell* ioVector, mork_fill inFill);
// Count cells in ioVector that change existing cells in this row when
// ioVector is added to the row (as in TakeCells()). This is the set
// of cells with the same columns in ioVector and mRow_Cells, which do
// not have exactly the same value in mCell_Atom, and which do not both
// have change status equal to morkChange_kCut (because cutting a cut
// cell still yields a cell that has been cut). CountOverlap() also
// modifies the change attribute of any cell in ioVector to kDup when
// the change was previously kCut and the same column cell was found
// in this row with change also equal to kCut; this tells callers later
// they need not look for that cell in the row again on a second pass.
void MergeCells(morkEnv* ev, morkCell* ioVector, mork_fill inVecLength,
mork_fill inOldRowFill, mork_fill inOverlap);
// MergeCells() is the part of TakeCells() that does the insertion.
// inOldRowFill is the old value of mRow_Length, and inOverlap is the
// number of cells in the intersection that must be updated.
void TakeCells(morkEnv* ev, morkCell* ioVector, mork_fill inVecLength,
morkStore* ioStore);
morkCell* NewCell(morkEnv* ev, mdb_column inColumn, mork_pos* outPos,
morkStore* ioStore);
morkCell* GetCell(morkEnv* ev, mdb_column inColumn, mork_pos* outPos) const;
morkCell* CellAt(morkEnv* ev, mork_pos inPos) const;
mork_aid GetCellAtomAid(morkEnv* ev, mdb_column inColumn) const;
// GetCellAtomAid() finds the cell with column inColumn, and sees if the
// atom has a token ID, and returns the atom's ID if there is one. Or
// else zero is returned if there is no such column, or no atom, or if
// the atom has no ID to return. This method is intended to support
// efficient updating of column indexes for rows in a row space.
public: // external row methods
void DirtyAllRowContent(morkEnv* ev);
morkStore* GetRowSpaceStore(morkEnv* ev) const;
void AddColumn(morkEnv* ev, mdb_column inColumn, const mdbYarn* inYarn,
morkStore* ioStore);
morkAtom* GetColumnAtom(morkEnv* ev, mdb_column inColumn);
void NextColumn(morkEnv* ev, mdb_column* ioColumn, mdbYarn* outYarn);
void SeekColumn(morkEnv* ev, mdb_pos inPos, mdb_column* outColumn,
mdbYarn* outYarn);
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 OnZeroRowGcUse(morkEnv* ev);
// OnZeroRowGcUse() is called when CutRowGcUse() returns zero.
public: // dynamic typing
mork_bool IsRow() const { return mRow_Tag == morkRow_kTag; }
public: // hash and equal
mork_u4 HashRow() const {
return (mRow_Oid.mOid_Scope << 16) ^ mRow_Oid.mOid_Id;
}
mork_bool EqualRow(const morkRow* ioRow) const {
return ((mRow_Oid.mOid_Scope == ioRow->mRow_Oid.mOid_Scope) &&
(mRow_Oid.mOid_Id == ioRow->mRow_Oid.mOid_Id));
}
mork_bool EqualOid(const mdbOid* ioOid) const {
return ((mRow_Oid.mOid_Scope == ioOid->mOid_Scope) &&
(mRow_Oid.mOid_Id == ioOid->mOid_Id));
}
public: // errors
static void ZeroColumnError(morkEnv* ev);
static void LengthBeyondMaxError(morkEnv* ev);
static void NilCellsError(morkEnv* ev);
static void NonRowTypeError(morkEnv* ev);
static void NonRowTypeWarning(morkEnv* ev);
static void GcUsesUnderflowWarning(morkEnv* ev);
private: // copying is not allowed
morkRow(const morkRow& other);
morkRow& operator=(const morkRow& other);
};
// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKROW_ */