db/mork/src/morkCellObject.cpp
author Jorg K <jorgk@jorgk.com>
Fri, 26 Jul 2019 21:20:49 +0200
changeset 35267 71349d370678bb201e7566a6e83950ac58385496
parent 34453 db283bd18902be05315471da36656dd2d678e25b
permissions -rw-r--r--
Bug 1568095 - Make morkAtom::GetYarn() static. r=benc a=jorgk

/* -*- 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 _MORKOBJECT_
#  include "morkObject.h"
#endif

#ifndef _MORKENV_
#  include "morkEnv.h"
#endif

#ifndef _MORKCELLOBJECT_
#  include "morkCellObject.h"
#endif

#ifndef _MORKROWOBJECT_
#  include "morkRowObject.h"
#endif

#ifndef _MORKROW_
#  include "morkRow.h"
#endif

#ifndef _MORKCELL_
#  include "morkCell.h"
#endif

#ifndef _MORKSTORE_
#  include "morkStore.h"
#endif

// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789

// ````` ````` ````` ````` `````
// { ===== begin morkNode interface =====

/*public virtual*/ void morkCellObject::CloseMorkNode(
    morkEnv* ev)  // CloseCellObject() only if open
{
  if (this->IsOpenNode()) {
    this->MarkClosing();
    this->CloseCellObject(ev);
    this->MarkShut();
  }
}

/*public virtual*/
morkCellObject::~morkCellObject()  // assert CloseCellObject() executed earlier
{
  CloseMorkNode(mMorkEnv);
  MORK_ASSERT(mCellObject_Row == 0);
}

/*public non-poly*/
morkCellObject::morkCellObject(morkEnv* ev, const morkUsage& inUsage,
                               nsIMdbHeap* ioHeap, morkRow* ioRow,
                               morkCell* ioCell, mork_column inCol,
                               mork_pos inPos)
    : morkObject(ev, inUsage, ioHeap, morkColor_kNone, (morkHandle*)0),
      mCellObject_RowObject(0),
      mCellObject_Row(0),
      mCellObject_Cell(0),
      mCellObject_Col(inCol),
      mCellObject_RowSeed(0),
      mCellObject_Pos((mork_u2)inPos) {
  if (ev->Good()) {
    if (ioRow && ioCell) {
      if (ioRow->IsRow()) {
        morkStore* store = ioRow->GetRowSpaceStore(ev);
        if (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);

            mCellObject_RowObject = rowObj;  // assume control of strong ref
          }
          if (ev->Good()) mNode_Derived = morkDerived_kCellObject;
        }
      } else
        ioRow->NonRowTypeError(ev);
    } else
      ev->NilPointerError();
  }
}

NS_IMPL_ISUPPORTS_INHERITED(morkCellObject, morkObject, nsIMdbCell)

/*public non-poly*/ void morkCellObject::CloseCellObject(
    morkEnv* ev)  // called by CloseMorkNode();
{
  if (this->IsNode()) {
    NS_RELEASE(mCellObject_RowObject);
    mCellObject_Row = 0;
    mCellObject_Cell = 0;
    mCellObject_RowSeed = 0;
    this->CloseObject(ev);
    this->MarkShut();
  } else
    this->NonNodeError(ev);
}

// } ===== end morkNode methods =====
// ````` ````` ````` ````` `````

mork_bool morkCellObject::ResyncWithRow(morkEnv* ev) {
  morkRow* row = mCellObject_Row;
  mork_pos pos = 0;
  morkCell* cell = row->GetCell(ev, mCellObject_Col, &pos);
  if (cell) {
    mCellObject_Pos = (mork_u2)pos;
    mCellObject_Cell = cell;
    mCellObject_RowSeed = row->mRow_Seed;
  } else {
    mCellObject_Cell = 0;
    this->MissingRowColumnError(ev);
  }
  return ev->Good();
}

morkAtom* morkCellObject::GetCellAtom(morkEnv* ev) const {
  morkCell* cell = mCellObject_Cell;
  if (cell)
    return cell->GetAtom();
  else
    this->NilCellError(ev);

  return (morkAtom*)0;
}

/*static*/ void morkCellObject::WrongRowObjectRowError(morkEnv* ev) {
  ev->NewError("mCellObject_Row != mCellObject_RowObject->mRowObject_Row");
}

/*static*/ void morkCellObject::NilRowError(morkEnv* ev) {
  ev->NewError("nil mCellObject_Row");
}

/*static*/ void morkCellObject::NilRowObjectError(morkEnv* ev) {
  ev->NewError("nil mCellObject_RowObject");
}

/*static*/ void morkCellObject::NilCellError(morkEnv* ev) {
  ev->NewError("nil mCellObject_Cell");
}

/*static*/ void morkCellObject::NonCellObjectTypeError(morkEnv* ev) {
  ev->NewError("non morkCellObject");
}

/*static*/ void morkCellObject::MissingRowColumnError(morkEnv* ev) {
  ev->NewError("mCellObject_Col not in mCellObject_Row");
}

nsIMdbCell* morkCellObject::AcquireCellHandle(morkEnv* ev) {
  nsIMdbCell* outCell = this;
  NS_ADDREF(outCell);
  return outCell;
}

morkEnv* morkCellObject::CanUseCell(nsIMdbEnv* mev, mork_bool inMutable,
                                    nsresult* outErr, morkCell** outCell) {
  morkEnv* outEnv = 0;
  morkCell* cell = 0;
  morkEnv* ev = morkEnv::FromMdbEnv(mev);
  if (ev) {
    if (IsCellObject()) {
      if (IsMutable() || !inMutable) {
        morkRowObject* rowObj = mCellObject_RowObject;
        if (rowObj) {
          morkRow* row = mCellObject_Row;
          if (row) {
            if (rowObj->mRowObject_Row == row) {
              mork_u2 oldSeed = mCellObject_RowSeed;
              if (row->mRow_Seed == oldSeed || ResyncWithRow(ev)) {
                cell = mCellObject_Cell;
                if (cell) {
                  outEnv = ev;
                } else
                  NilCellError(ev);
              }
            } else
              WrongRowObjectRowError(ev);
          } else
            NilRowError(ev);
        } else
          NilRowObjectError(ev);
      } else
        NonMutableNodeError(ev);
    } else
      NonCellObjectTypeError(ev);
  }
  *outErr = ev->AsErr();
  MORK_ASSERT(outEnv);
  *outCell = cell;

  return outEnv;
}

// { ----- begin attribute methods -----
NS_IMETHODIMP morkCellObject::SetBlob(nsIMdbEnv* /* mev */,
                                      nsIMdbBlob* /* ioBlob */) {
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
}  // reads inBlob slots

// when inBlob is in the same suite, this might be fastest cell-to-cell

NS_IMETHODIMP
morkCellObject::ClearBlob(  // make empty (so content has zero length)
    nsIMdbEnv* /* mev */) {
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
  // remember row->MaybeDirtySpaceStoreAndRow();
}
// clearing a yarn is like SetYarn() with empty yarn instance content

NS_IMETHODIMP morkCellObject::GetBlobFill(nsIMdbEnv* mev, mdb_fill* outFill)
// Same value that would be put into mYarn_Fill, if one called GetYarn()
// with a yarn instance that had mYarn_Buf==nil and mYarn_Size==0.
{
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
}  // size of blob

NS_IMETHODIMP morkCellObject::SetYarn(nsIMdbEnv* mev, const mdbYarn* inYarn) {
  nsresult outErr = NS_OK;
  morkCell* cell = 0;
  morkEnv* ev =
      this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
  if (ev) {
    morkRow* row = mCellObject_Row;
    if (row) {
      morkStore* store = row->GetRowSpaceStore(ev);
      if (store) {
        cell->SetYarn(ev, inYarn, store);
        if (row->IsRowClean() && store->mStore_CanDirty)
          row->MaybeDirtySpaceStoreAndRow();
      }
    } else
      ev->NilPointerError();

    outErr = ev->AsErr();
  }

  return outErr;
}  // reads from yarn slots
// make this text object contain content from the yarn's buffer

NS_IMETHODIMP morkCellObject::GetYarn(nsIMdbEnv* mev, mdbYarn* outYarn) {
  nsresult outErr = NS_OK;
  morkCell* cell = 0;
  morkEnv* ev =
      this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
  if (ev) {
    morkAtom* atom = cell->GetAtom();
    morkAtom::GetYarn(atom, outYarn);
    outErr = ev->AsErr();
  }

  return outErr;
}  // writes some yarn slots
// copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form

NS_IMETHODIMP morkCellObject::AliasYarn(nsIMdbEnv* mev, mdbYarn* outYarn) {
  nsresult outErr = NS_OK;
  morkCell* cell = 0;
  morkEnv* ev =
      this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
  if (ev) {
    morkAtom* atom = cell->GetAtom();
    morkAtom::AliasYarn(atom, outYarn);
    outErr = ev->AsErr();
  }

  return outErr;
}  // writes ALL yarn slots

// } ----- end attribute methods -----

// } ===== end nsIMdbBlob methods =====

// { ===== begin nsIMdbCell methods =====

// { ----- begin attribute methods -----
NS_IMETHODIMP morkCellObject::SetColumn(nsIMdbEnv* mev, mdb_column inColumn) {
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
  // remember row->MaybeDirtySpaceStoreAndRow();
}

NS_IMETHODIMP morkCellObject::GetColumn(nsIMdbEnv* mev, mdb_column* outColumn) {
  nsresult outErr = NS_OK;
  mdb_column col = 0;
  morkCell* cell = 0;
  morkEnv* ev =
      this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
  if (ev) {
    col = mCellObject_Col;
    outErr = ev->AsErr();
  }
  if (outColumn) *outColumn = col;
  return outErr;
}

NS_IMETHODIMP
morkCellObject::GetCellInfo(  // all cell metainfo except actual content
    nsIMdbEnv* mev,
    mdb_column* outColumn,    // the column in the containing row
    mdb_fill* outBlobFill,    // the size of text content in bytes
    mdbOid* outChildOid,      // oid of possible row or table child
    mdb_bool* outIsRowChild)  // nonzero if child, and a row child
// Checking all cell metainfo is a good way to avoid forcing a large cell
// in to memory when you don't actually want to use the content.
{
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP morkCellObject::GetRow(
    nsIMdbEnv* mev,  // parent row for this cell
    nsIMdbRow** acqRow) {
  nsresult outErr = NS_OK;
  nsIMdbRow* outRow = 0;
  morkCell* cell = 0;
  morkEnv* ev =
      this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
  if (ev) {
    outRow = mCellObject_RowObject->AcquireRowHandle(ev);

    outErr = ev->AsErr();
  }
  if (acqRow) *acqRow = outRow;
  return outErr;
}

NS_IMETHODIMP morkCellObject::GetPort(nsIMdbEnv* mev,  // port containing cell
                                      nsIMdbPort** acqPort) {
  nsresult outErr = NS_OK;
  nsIMdbPort* outPort = 0;
  morkCell* cell = 0;
  morkEnv* ev =
      this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
  if (ev) {
    if (mCellObject_Row) {
      morkStore* store = mCellObject_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 children methods -----
NS_IMETHODIMP
morkCellObject::HasAnyChild(  // does cell have a child instead of text?
    nsIMdbEnv* mev,
    mdbOid* outOid,      // out id of row or table (or unbound if no child)
    mdb_bool* outIsRow)  // nonzero if child is a row (rather than a table)
{
  nsresult outErr = NS_OK;
  mdb_bool isRow = morkBool_kFalse;
  outOid->mOid_Scope = 0;
  outOid->mOid_Id = morkId_kMinusOne;
  morkCell* cell = 0;
  morkEnv* ev =
      this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
  if (ev) {
    morkAtom* atom = GetCellAtom(ev);
    if (atom) {
      isRow = atom->IsRowOid();
      if (isRow || atom->IsTableOid())
        *outOid = ((morkOidAtom*)atom)->mOidAtom_Oid;
    }

    outErr = ev->AsErr();
  }
  if (outIsRow) *outIsRow = isRow;

  return outErr;
}

NS_IMETHODIMP
morkCellObject::GetAnyChild(  // access table of specific attribute
    nsIMdbEnv* mev,           // context
    nsIMdbRow** acqRow,       // child row (or null)
    nsIMdbTable** acqTable)   // child table (or null)
{
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
morkCellObject::SetChildRow(  // access table of specific attribute
    nsIMdbEnv* mev,           // context
    nsIMdbRow* ioRow) {
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
}  // inRow must be bound inside this same db port

NS_IMETHODIMP morkCellObject::GetChildRow(  // access row of specific attribute
    nsIMdbEnv* mev,                         // context
    nsIMdbRow** acqRow)  // acquire child row (or nil if no child)
{
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
morkCellObject::SetChildTable(  // access table of specific attribute
    nsIMdbEnv* mev,             // context
    nsIMdbTable* inTable)       // table must be bound inside this same db port
{
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
  // remember row->MaybeDirtySpaceStoreAndRow();
}

NS_IMETHODIMP
morkCellObject::GetChildTable(  // access table of specific attribute
    nsIMdbEnv* mev,             // context
    nsIMdbTable** acqTable)     // acquire child tabdle (or nil if no chil)
{
  NS_ASSERTION(false, "not implemented");
  return NS_ERROR_NOT_IMPLEMENTED;
}
// } ----- end children methods -----

// } ===== end nsIMdbCell methods =====

// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789