1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1999
20
* the Initial Developer. All Rights Reserved.
25
* Alternatively, the contents of this file may be used under the terms of
26
* either the GNU General Public License Version 2 or later (the "GPL"), or
27
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the NPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the NPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
52
#include "morkHandle.h"
59
#ifndef _MORKCELLOBJECT_
60
#include "morkCellObject.h"
63
#ifndef _MORKROWOBJECT_
64
#include "morkRowObject.h"
68
#include "orkinCell.h"
88
#include "morkSpace.h"
91
#ifndef _MORKROWSPACE_
92
#include "morkRowSpace.h"
96
#include "morkStore.h"
99
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
102
orkinCell:: ~orkinCell() // morkHandle destructor does everything
106
/*protected non-poly construction*/
107
orkinCell::orkinCell(morkEnv* ev, // morkUsage is morkUsage_kPool
108
morkHandleFace* ioFace, // must not be nil, cookie for this handle
109
morkCellObject* ioObject) // must not be nil, the object for this handle
110
: morkHandle(ev, ioFace, ioObject, morkMagic_kCell)
112
// do not modify mNode_Derived; leave it equal to morkDerived_kHandle
116
/*static */ orkinCell*
117
orkinCell::MakeCell(morkEnv* ev, morkCellObject* ioObject)
119
mork_bool isEnv = ev->IsEnv();
123
morkHandleFace* face = ev->NewHandle(sizeof(orkinCell));
125
return new(face) orkinCell(ev, face, ioObject);
127
ev->OutOfMemoryError();
130
return (orkinCell*) 0;
133
// ResyncWithRow() moved to the morkCellObject class:
135
// orkinCell::ResyncWithRow(morkEnv* ev)
137
// morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
138
// morkRow* row = cellObj->mCellObject_Row;
140
// morkCell* cell = row->GetCell(ev, cellObj->mCellObject_Col, &pos);
143
// cellObj->mCellObject_Pos = pos;
144
// cellObj->mCellObject_Cell = cell;
145
// cellObj->mCellObject_RowSeed = row->mRow_Seed;
149
// cellObj->mCellObject_Cell = 0;
150
// cellObj->MissingRowColumnError(ev);
152
// return ev->Good();
156
orkinCell::CanUseCell(nsIMdbEnv* mev, mork_bool inMutable,
157
mdb_err* outErr, morkCell** outCell) const
161
morkEnv* ev = morkEnv::FromMdbEnv(mev);
164
morkCellObject* cellObj = (morkCellObject*)
165
this->GetGoodHandleObject(ev, inMutable, morkMagic_kCell,
166
/*inClosedOkay*/ morkBool_kFalse);
169
if ( cellObj->IsCellObject() )
171
if ( cellObj->IsMutable() || !inMutable )
173
morkRowObject* rowObj = cellObj->mCellObject_RowObject;
176
morkRow* row = cellObj->mCellObject_Row;
179
if ( rowObj->mRowObject_Row == row )
181
mork_u2 oldSeed = cellObj->mCellObject_RowSeed;
182
if ( row->mRow_Seed == oldSeed || cellObj->ResyncWithRow(ev) )
184
cell = cellObj->mCellObject_Cell;
190
cellObj->NilCellError(ev);
194
cellObj->WrongRowObjectRowError(ev);
197
cellObj->NilRowError(ev);
200
cellObj->NilRowObjectError(ev);
203
cellObj->NonMutableNodeError(ev);
206
cellObj->NonCellObjectTypeError(ev);
208
*outErr = ev->AsErr();
216
// { ===== begin nsIMdbISupports methods =====
217
NS_IMPL_QUERY_INTERFACE0(orkinCell)
220
orkinCell::AddRef() // add strong ref with no
222
morkEnv* ev = mHandle_Env;
223
if ( ev && ev->IsEnv() )
224
return this->Handle_AddStrongRef(ev->AsMdbEnv());
226
return morkEnv_kNonEnvTypeError;
230
orkinCell::Release() // cut strong ref
232
morkEnv* ev = mHandle_Env;
233
if ( ev && ev->IsEnv() )
234
return this->Handle_CutStrongRef(ev->AsMdbEnv());
236
return morkEnv_kNonEnvTypeError;
238
// } ===== end nsIMdbISupports methods =====
240
// { ===== begin nsIMdbObject methods =====
242
// { ----- begin attribute methods -----
244
orkinCell::IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly)
246
return this->Handle_IsFrozenMdbObject(mev, outIsReadonly);
248
// same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
249
// } ----- end attribute methods -----
251
// { ----- begin factory methods -----
253
orkinCell::GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory)
255
return this->Handle_GetMdbFactory(mev, acqFactory);
257
// } ----- end factory methods -----
259
// { ----- begin ref counting for well-behaved cyclic graphs -----
261
orkinCell::GetWeakRefCount(nsIMdbEnv* mev, // weak refs
264
return this->Handle_GetWeakRefCount(mev, outCount);
267
orkinCell::GetStrongRefCount(nsIMdbEnv* mev, // strong refs
270
return this->Handle_GetStrongRefCount(mev, outCount);
274
orkinCell::AddWeakRef(nsIMdbEnv* mev)
276
return this->Handle_AddWeakRef(mev);
279
orkinCell::AddStrongRef(nsIMdbEnv* mev)
281
return this->Handle_AddStrongRef(mev);
285
orkinCell::CutWeakRef(nsIMdbEnv* mev)
287
return this->Handle_CutWeakRef(mev);
290
orkinCell::CutStrongRef(nsIMdbEnv* mev)
292
return this->Handle_CutStrongRef(mev);
296
orkinCell::CloseMdbObject(nsIMdbEnv* mev)
298
return this->Handle_CloseMdbObject(mev);
302
orkinCell::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen)
304
return this->Handle_IsOpenMdbObject(mev, outOpen);
306
// } ----- end ref counting -----
308
// } ===== end nsIMdbObject methods =====
310
// { ===== begin nsIMdbBlob methods =====
312
// { ----- begin attribute methods -----
314
orkinCell::SetBlob(nsIMdbEnv* mev,
320
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
324
// remember row->MaybeDirtySpaceStoreAndRow();
326
ev->StubMethodOnlyError();
327
outErr = ev->AsErr();
331
} // reads inBlob slots
332
// when inBlob is in the same suite, this might be fastest cell-to-cell
335
orkinCell::ClearBlob( // make empty (so content has zero length)
340
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
344
// remember row->MaybeDirtySpaceStoreAndRow();
346
ev->StubMethodOnlyError();
347
outErr = ev->AsErr();
352
// clearing a yarn is like SetYarn() with empty yarn instance content
355
orkinCell::GetBlobFill(nsIMdbEnv* mev,
357
// Same value that would be put into mYarn_Fill, if one called GetYarn()
358
// with a yarn instance that had mYarn_Buf==nil and mYarn_Size==0.
363
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
367
ev->StubMethodOnlyError();
368
outErr = ev->AsErr();
377
orkinCell::SetYarn(nsIMdbEnv* mev,
378
const mdbYarn* inYarn)
382
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
386
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
387
morkRow* row = cellObj->mCellObject_Row;
390
morkStore* store = row->GetRowSpaceStore(ev);
393
cell->SetYarn(ev, inYarn, store);
394
if ( row->IsRowClean() && store->mStore_CanDirty )
395
row->MaybeDirtySpaceStoreAndRow();
399
ev->NilPointerError();
401
outErr = ev->AsErr();
405
} // reads from yarn slots
406
// make this text object contain content from the yarn's buffer
409
orkinCell::GetYarn(nsIMdbEnv* mev,
414
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
418
morkAtom* atom = cell->GetAtom();
419
atom->GetYarn(outYarn);
420
outErr = ev->AsErr();
424
} // writes some yarn slots
425
// copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
428
orkinCell::AliasYarn(nsIMdbEnv* mev,
433
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
437
morkAtom* atom = cell->GetAtom();
438
atom->AliasYarn(outYarn);
439
outErr = ev->AsErr();
443
} // writes ALL yarn slots
445
// } ----- end attribute methods -----
447
// } ===== end nsIMdbBlob methods =====
449
// { ===== begin nsIMdbCell methods =====
451
// { ----- begin attribute methods -----
453
orkinCell::SetColumn(nsIMdbEnv* mev, mdb_column inColumn)
455
MORK_USED_1(inColumn);
458
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
462
// remember row->MaybeDirtySpaceStoreAndRow();
464
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
465
MORK_USED_1(cellObj);
467
ev->StubMethodOnlyError();
468
outErr = ev->AsErr();
475
orkinCell::GetColumn(nsIMdbEnv* mev, mdb_column* outColumn)
480
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
484
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
485
col = cellObj->mCellObject_Col;
486
outErr = ev->AsErr();
494
orkinCell::GetCellInfo( // all cell metainfo except actual content
496
mdb_column* outColumn, // the column in the containing row
497
mdb_fill* outBlobFill, // the size of text content in bytes
498
mdbOid* outChildOid, // oid of possible row or table child
499
mdb_bool* outIsRowChild) // nonzero if child, and a row child
500
// Checking all cell metainfo is a good way to avoid forcing a large cell
501
// in to memory when you don't actually want to use the content.
504
mdb_bool isRowChild = morkBool_kFalse;
506
childOid.mOid_Scope = 0;
507
childOid.mOid_Id = 0;
508
mork_fill blobFill = 0;
509
mdb_column column = 0;
511
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
515
morkCellObject* cellObj;
516
cellObj = (morkCellObject*) mHandle_Object;
517
ev->StubMethodOnlyError();
518
outErr = ev->AsErr();
521
*outIsRowChild = isRowChild;
523
*outChildOid = childOid;
525
*outBlobFill = blobFill;
534
orkinCell::GetRow(nsIMdbEnv* mev, // parent row for this cell
538
nsIMdbRow* outRow = 0;
540
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
544
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
545
morkRowObject* rowObj = cellObj->mCellObject_RowObject;
546
outRow = rowObj->AcquireRowHandle(ev);
548
outErr = ev->AsErr();
556
orkinCell::GetPort(nsIMdbEnv* mev, // port containing cell
557
nsIMdbPort** acqPort)
560
nsIMdbPort* outPort = 0;
562
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
566
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
567
morkRow* row = cellObj->mCellObject_Row;
570
morkStore* store = row->GetRowSpaceStore(ev);
572
outPort = store->AcquireStoreHandle(ev);
575
ev->NilPointerError();
577
outErr = ev->AsErr();
583
// } ----- end attribute methods -----
585
// { ----- begin children methods -----
587
orkinCell::HasAnyChild( // does cell have a child instead of text?
589
mdbOid* outOid, // out id of row or table (or unbound if no child)
590
mdb_bool* outIsRow) // nonzero if child is a row (rather than a table)
593
mdb_bool isRow = morkBool_kFalse;
594
outOid->mOid_Scope = 0;
595
outOid->mOid_Id = morkId_kMinusOne;
597
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
601
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
602
morkAtom* atom = cellObj->GetCellAtom(ev);
605
isRow = atom->IsRowOid();
606
if ( isRow || atom->IsTableOid() )
607
*outOid = ((morkOidAtom*) atom)->mOidAtom_Oid;
610
outErr = ev->AsErr();
619
orkinCell::GetAnyChild( // access table of specific attribute
620
nsIMdbEnv* mev, // context
621
nsIMdbRow** acqRow, // child row (or null)
622
nsIMdbTable** acqTable) // child table (or null)
625
nsIMdbRow* outRow = 0;
626
nsIMdbTable* outTable = 0;
628
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
632
morkCellObject* cellObj;
633
cellObj = (morkCellObject*) mHandle_Object;
634
ev->StubMethodOnlyError();
635
outErr = ev->AsErr();
637
MORK_ASSERT(acqTable);
639
*acqTable = outTable;
649
orkinCell::SetChildRow( // access table of specific attribute
650
nsIMdbEnv* mev, // context
656
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
660
// remember row->MaybeDirtySpaceStoreAndRow();
662
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
663
MORK_USED_1(cellObj);
665
ev->StubMethodOnlyError();
666
outErr = ev->AsErr();
670
} // inRow must be bound inside this same db port
673
orkinCell::GetChildRow( // access row of specific attribute
674
nsIMdbEnv* mev, // context
675
nsIMdbRow** acqRow) // acquire child row (or nil if no child)
678
nsIMdbRow* outRow = 0;
680
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
684
morkCellObject* cellObj;
685
cellObj = (morkCellObject*) mHandle_Object;
686
ev->StubMethodOnlyError();
687
outErr = ev->AsErr();
697
orkinCell::SetChildTable( // access table of specific attribute
698
nsIMdbEnv* mev, // context
699
nsIMdbTable* inTable) // table must be bound inside this same db port
701
MORK_USED_1(inTable);
704
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
708
// remember row->MaybeDirtySpaceStoreAndRow();
710
morkCellObject* cellObj = (morkCellObject*) mHandle_Object;
711
MORK_USED_1(cellObj);
713
ev->StubMethodOnlyError();
714
outErr = ev->AsErr();
721
orkinCell::GetChildTable( // access table of specific attribute
722
nsIMdbEnv* mev, // context
723
nsIMdbTable** acqTable) // acquire child tabdle (or nil if no chil)
726
nsIMdbTable* outTable = 0;
728
morkEnv* ev = this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue,
732
morkCellObject* cellObj;
733
cellObj = (morkCellObject*) mHandle_Object;
734
ev->StubMethodOnlyError();
735
outErr = ev->AsErr();
738
*acqTable = outTable;
742
// } ----- end children methods -----
744
// } ===== end nsIMdbCell methods =====
747
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789