1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef _MDB_
7 #  include "mdb.h"
8 #endif
9 
10 #ifndef _MORK_
11 #  include "mork.h"
12 #endif
13 
14 #ifndef _MORKNODE_
15 #  include "morkNode.h"
16 #endif
17 
18 #ifndef _MORKOBJECT_
19 #  include "morkObject.h"
20 #endif
21 
22 #ifndef _MORKENV_
23 #  include "morkEnv.h"
24 #endif
25 
26 #ifndef _MORKCELLOBJECT_
27 #  include "morkCellObject.h"
28 #endif
29 
30 #ifndef _MORKROWOBJECT_
31 #  include "morkRowObject.h"
32 #endif
33 
34 #ifndef _MORKROW_
35 #  include "morkRow.h"
36 #endif
37 
38 #ifndef _MORKCELL_
39 #  include "morkCell.h"
40 #endif
41 
42 #ifndef _MORKSTORE_
43 #  include "morkStore.h"
44 #endif
45 
46 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
47 
48 // ````` ````` ````` ````` `````
49 // { ===== begin morkNode interface =====
50 
CloseMorkNode(morkEnv * ev)51 /*public virtual*/ void morkCellObject::CloseMorkNode(
52     morkEnv* ev)  // CloseCellObject() only if open
53 {
54   if (this->IsOpenNode()) {
55     this->MarkClosing();
56     this->CloseCellObject(ev);
57     this->MarkShut();
58   }
59 }
60 
61 /*public virtual*/
~morkCellObject()62 morkCellObject::~morkCellObject()  // assert CloseCellObject() executed earlier
63 {
64   CloseMorkNode(mMorkEnv);
65   MORK_ASSERT(mCellObject_Row == 0);
66 }
67 
68 /*public non-poly*/
morkCellObject(morkEnv * ev,const morkUsage & inUsage,nsIMdbHeap * ioHeap,morkRow * ioRow,morkCell * ioCell,mork_column inCol,mork_pos inPos)69 morkCellObject::morkCellObject(morkEnv* ev, const morkUsage& inUsage,
70                                nsIMdbHeap* ioHeap, morkRow* ioRow,
71                                morkCell* ioCell, mork_column inCol,
72                                mork_pos inPos)
73     : morkObject(ev, inUsage, ioHeap, morkColor_kNone, (morkHandle*)0),
74       mCellObject_RowObject(0),
75       mCellObject_Row(0),
76       mCellObject_Cell(0),
77       mCellObject_Col(inCol),
78       mCellObject_RowSeed(0),
79       mCellObject_Pos((mork_u2)inPos) {
80   if (ev->Good()) {
81     if (ioRow && ioCell) {
82       if (ioRow->IsRow()) {
83         morkStore* store = ioRow->GetRowSpaceStore(ev);
84         if (store) {
85           morkRowObject* rowObj = ioRow->AcquireRowObject(ev, store);
86           if (rowObj) {
87             mCellObject_Row = ioRow;
88             mCellObject_Cell = ioCell;
89             mCellObject_RowSeed = ioRow->mRow_Seed;
90 
91             // morkRowObject::SlotStrongRowObject(rowObj, ev,
92             //  &mCellObject_RowObject);
93 
94             mCellObject_RowObject = rowObj;  // assume control of strong ref
95           }
96           if (ev->Good()) mNode_Derived = morkDerived_kCellObject;
97         }
98       } else
99         ioRow->NonRowTypeError(ev);
100     } else
101       ev->NilPointerError();
102   }
103 }
104 
NS_IMPL_ISUPPORTS_INHERITED(morkCellObject,morkObject,nsIMdbCell)105 NS_IMPL_ISUPPORTS_INHERITED(morkCellObject, morkObject, nsIMdbCell)
106 
107 /*public non-poly*/ void morkCellObject::CloseCellObject(
108     morkEnv* ev)  // called by CloseMorkNode();
109 {
110   if (this->IsNode()) {
111     NS_RELEASE(mCellObject_RowObject);
112     mCellObject_Row = 0;
113     mCellObject_Cell = 0;
114     mCellObject_RowSeed = 0;
115     this->CloseObject(ev);
116     this->MarkShut();
117   } else
118     this->NonNodeError(ev);
119 }
120 
121 // } ===== end morkNode methods =====
122 // ````` ````` ````` ````` `````
123 
ResyncWithRow(morkEnv * ev)124 mork_bool morkCellObject::ResyncWithRow(morkEnv* ev) {
125   morkRow* row = mCellObject_Row;
126   mork_pos pos = 0;
127   morkCell* cell = row->GetCell(ev, mCellObject_Col, &pos);
128   if (cell) {
129     mCellObject_Pos = (mork_u2)pos;
130     mCellObject_Cell = cell;
131     mCellObject_RowSeed = row->mRow_Seed;
132   } else {
133     mCellObject_Cell = 0;
134     this->MissingRowColumnError(ev);
135   }
136   return ev->Good();
137 }
138 
GetCellAtom(morkEnv * ev) const139 morkAtom* morkCellObject::GetCellAtom(morkEnv* ev) const {
140   morkCell* cell = mCellObject_Cell;
141   if (cell)
142     return cell->GetAtom();
143   else
144     this->NilCellError(ev);
145 
146   return (morkAtom*)0;
147 }
148 
WrongRowObjectRowError(morkEnv * ev)149 /*static*/ void morkCellObject::WrongRowObjectRowError(morkEnv* ev) {
150   ev->NewError("mCellObject_Row != mCellObject_RowObject->mRowObject_Row");
151 }
152 
NilRowError(morkEnv * ev)153 /*static*/ void morkCellObject::NilRowError(morkEnv* ev) {
154   ev->NewError("nil mCellObject_Row");
155 }
156 
NilRowObjectError(morkEnv * ev)157 /*static*/ void morkCellObject::NilRowObjectError(morkEnv* ev) {
158   ev->NewError("nil mCellObject_RowObject");
159 }
160 
NilCellError(morkEnv * ev)161 /*static*/ void morkCellObject::NilCellError(morkEnv* ev) {
162   ev->NewError("nil mCellObject_Cell");
163 }
164 
NonCellObjectTypeError(morkEnv * ev)165 /*static*/ void morkCellObject::NonCellObjectTypeError(morkEnv* ev) {
166   ev->NewError("non morkCellObject");
167 }
168 
MissingRowColumnError(morkEnv * ev)169 /*static*/ void morkCellObject::MissingRowColumnError(morkEnv* ev) {
170   ev->NewError("mCellObject_Col not in mCellObject_Row");
171 }
172 
AcquireCellHandle(morkEnv * ev)173 nsIMdbCell* morkCellObject::AcquireCellHandle(morkEnv* ev) {
174   nsIMdbCell* outCell = this;
175   NS_ADDREF(outCell);
176   return outCell;
177 }
178 
CanUseCell(nsIMdbEnv * mev,mork_bool inMutable,nsresult * outErr,morkCell ** outCell)179 morkEnv* morkCellObject::CanUseCell(nsIMdbEnv* mev, mork_bool inMutable,
180                                     nsresult* outErr, morkCell** outCell) {
181   morkEnv* outEnv = 0;
182   morkCell* cell = 0;
183   morkEnv* ev = morkEnv::FromMdbEnv(mev);
184   if (ev) {
185     if (IsCellObject()) {
186       if (IsMutable() || !inMutable) {
187         morkRowObject* rowObj = mCellObject_RowObject;
188         if (rowObj) {
189           morkRow* row = mCellObject_Row;
190           if (row) {
191             if (rowObj->mRowObject_Row == row) {
192               mork_u2 oldSeed = mCellObject_RowSeed;
193               if (row->mRow_Seed == oldSeed || ResyncWithRow(ev)) {
194                 cell = mCellObject_Cell;
195                 if (cell) {
196                   outEnv = ev;
197                 } else
198                   NilCellError(ev);
199               }
200             } else
201               WrongRowObjectRowError(ev);
202           } else
203             NilRowError(ev);
204         } else
205           NilRowObjectError(ev);
206       } else
207         NonMutableNodeError(ev);
208     } else
209       NonCellObjectTypeError(ev);
210   }
211   *outErr = ev->AsErr();
212   MORK_ASSERT(outEnv);
213   *outCell = cell;
214 
215   return outEnv;
216 }
217 
218 // { ----- begin attribute methods -----
SetBlob(nsIMdbEnv *,nsIMdbBlob *)219 NS_IMETHODIMP morkCellObject::SetBlob(nsIMdbEnv* /* mev */,
220                                       nsIMdbBlob* /* ioBlob */) {
221   NS_ASSERTION(false, "not implemented");
222   return NS_ERROR_NOT_IMPLEMENTED;
223 }  // reads inBlob slots
224 
225 // when inBlob is in the same suite, this might be fastest cell-to-cell
226 
227 NS_IMETHODIMP
ClearBlob(nsIMdbEnv *)228 morkCellObject::ClearBlob(  // make empty (so content has zero length)
229     nsIMdbEnv* /* mev */) {
230   NS_ASSERTION(false, "not implemented");
231   return NS_ERROR_NOT_IMPLEMENTED;
232   // remember row->MaybeDirtySpaceStoreAndRow();
233 }
234 // clearing a yarn is like SetYarn() with empty yarn instance content
235 
GetBlobFill(nsIMdbEnv * mev,mdb_fill * outFill)236 NS_IMETHODIMP morkCellObject::GetBlobFill(nsIMdbEnv* mev, mdb_fill* outFill)
237 // Same value that would be put into mYarn_Fill, if one called GetYarn()
238 // with a yarn instance that had mYarn_Buf==nil and mYarn_Size==0.
239 {
240   NS_ASSERTION(false, "not implemented");
241   return NS_ERROR_NOT_IMPLEMENTED;
242 }  // size of blob
243 
SetYarn(nsIMdbEnv * mev,const mdbYarn * inYarn)244 NS_IMETHODIMP morkCellObject::SetYarn(nsIMdbEnv* mev, const mdbYarn* inYarn) {
245   nsresult outErr = NS_OK;
246   morkCell* cell = 0;
247   morkEnv* ev =
248       this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
249   if (ev) {
250     morkRow* row = mCellObject_Row;
251     if (row) {
252       morkStore* store = row->GetRowSpaceStore(ev);
253       if (store) {
254         cell->SetYarn(ev, inYarn, store);
255         if (row->IsRowClean() && store->mStore_CanDirty)
256           row->MaybeDirtySpaceStoreAndRow();
257       }
258     } else
259       ev->NilPointerError();
260 
261     outErr = ev->AsErr();
262   }
263 
264   return outErr;
265 }  // reads from yarn slots
266 // make this text object contain content from the yarn's buffer
267 
GetYarn(nsIMdbEnv * mev,mdbYarn * outYarn)268 NS_IMETHODIMP morkCellObject::GetYarn(nsIMdbEnv* mev, mdbYarn* outYarn) {
269   nsresult outErr = NS_OK;
270   morkCell* cell = 0;
271   morkEnv* ev =
272       this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
273   if (ev) {
274     morkAtom* atom = cell->GetAtom();
275     morkAtom::GetYarn(atom, outYarn);
276     outErr = ev->AsErr();
277   }
278 
279   return outErr;
280 }  // writes some yarn slots
281 // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
282 
AliasYarn(nsIMdbEnv * mev,mdbYarn * outYarn)283 NS_IMETHODIMP morkCellObject::AliasYarn(nsIMdbEnv* mev, mdbYarn* outYarn) {
284   nsresult outErr = NS_OK;
285   morkCell* cell = 0;
286   morkEnv* ev =
287       this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
288   if (ev) {
289     morkAtom* atom = cell->GetAtom();
290     morkAtom::AliasYarn(atom, outYarn);
291     outErr = ev->AsErr();
292   }
293 
294   return outErr;
295 }  // writes ALL yarn slots
296 
297 // } ----- end attribute methods -----
298 
299 // } ===== end nsIMdbBlob methods =====
300 
301 // { ===== begin nsIMdbCell methods =====
302 
303 // { ----- begin attribute methods -----
SetColumn(nsIMdbEnv * mev,mdb_column inColumn)304 NS_IMETHODIMP morkCellObject::SetColumn(nsIMdbEnv* mev, mdb_column inColumn) {
305   NS_ASSERTION(false, "not implemented");
306   return NS_ERROR_NOT_IMPLEMENTED;
307   // remember row->MaybeDirtySpaceStoreAndRow();
308 }
309 
GetColumn(nsIMdbEnv * mev,mdb_column * outColumn)310 NS_IMETHODIMP morkCellObject::GetColumn(nsIMdbEnv* mev, mdb_column* outColumn) {
311   nsresult outErr = NS_OK;
312   mdb_column col = 0;
313   morkCell* cell = 0;
314   morkEnv* ev =
315       this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
316   if (ev) {
317     col = mCellObject_Col;
318     outErr = ev->AsErr();
319   }
320   if (outColumn) *outColumn = col;
321   return outErr;
322 }
323 
324 NS_IMETHODIMP
GetCellInfo(nsIMdbEnv * mev,mdb_column * outColumn,mdb_fill * outBlobFill,mdbOid * outChildOid,mdb_bool * outIsRowChild)325 morkCellObject::GetCellInfo(  // all cell metainfo except actual content
326     nsIMdbEnv* mev,
327     mdb_column* outColumn,    // the column in the containing row
328     mdb_fill* outBlobFill,    // the size of text content in bytes
329     mdbOid* outChildOid,      // oid of possible row or table child
330     mdb_bool* outIsRowChild)  // nonzero if child, and a row child
331 // Checking all cell metainfo is a good way to avoid forcing a large cell
332 // in to memory when you don't actually want to use the content.
333 {
334   NS_ASSERTION(false, "not implemented");
335   return NS_ERROR_NOT_IMPLEMENTED;
336 }
337 
GetRow(nsIMdbEnv * mev,nsIMdbRow ** acqRow)338 NS_IMETHODIMP morkCellObject::GetRow(
339     nsIMdbEnv* mev,  // parent row for this cell
340     nsIMdbRow** acqRow) {
341   nsresult outErr = NS_OK;
342   nsIMdbRow* outRow = 0;
343   morkCell* cell = 0;
344   morkEnv* ev =
345       this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
346   if (ev) {
347     outRow = mCellObject_RowObject->AcquireRowHandle(ev);
348 
349     outErr = ev->AsErr();
350   }
351   if (acqRow) *acqRow = outRow;
352   return outErr;
353 }
354 
GetPort(nsIMdbEnv * mev,nsIMdbPort ** acqPort)355 NS_IMETHODIMP morkCellObject::GetPort(nsIMdbEnv* mev,  // port containing cell
356                                       nsIMdbPort** acqPort) {
357   nsresult outErr = NS_OK;
358   nsIMdbPort* outPort = 0;
359   morkCell* cell = 0;
360   morkEnv* ev =
361       this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
362   if (ev) {
363     if (mCellObject_Row) {
364       morkStore* store = mCellObject_Row->GetRowSpaceStore(ev);
365       if (store) outPort = store->AcquireStoreHandle(ev);
366     } else
367       ev->NilPointerError();
368 
369     outErr = ev->AsErr();
370   }
371   if (acqPort) *acqPort = outPort;
372   return outErr;
373 }
374 // } ----- end attribute methods -----
375 
376 // { ----- begin children methods -----
377 NS_IMETHODIMP
HasAnyChild(nsIMdbEnv * mev,mdbOid * outOid,mdb_bool * outIsRow)378 morkCellObject::HasAnyChild(  // does cell have a child instead of text?
379     nsIMdbEnv* mev,
380     mdbOid* outOid,      // out id of row or table (or unbound if no child)
381     mdb_bool* outIsRow)  // nonzero if child is a row (rather than a table)
382 {
383   nsresult outErr = NS_OK;
384   mdb_bool isRow = morkBool_kFalse;
385   outOid->mOid_Scope = 0;
386   outOid->mOid_Id = morkId_kMinusOne;
387   morkCell* cell = 0;
388   morkEnv* ev =
389       this->CanUseCell(mev, /*inMutable*/ morkBool_kTrue, &outErr, &cell);
390   if (ev) {
391     morkAtom* atom = GetCellAtom(ev);
392     if (atom) {
393       isRow = atom->IsRowOid();
394       if (isRow || atom->IsTableOid())
395         *outOid = ((morkOidAtom*)atom)->mOidAtom_Oid;
396     }
397 
398     outErr = ev->AsErr();
399   }
400   if (outIsRow) *outIsRow = isRow;
401 
402   return outErr;
403 }
404 
405 NS_IMETHODIMP
GetAnyChild(nsIMdbEnv * mev,nsIMdbRow ** acqRow,nsIMdbTable ** acqTable)406 morkCellObject::GetAnyChild(  // access table of specific attribute
407     nsIMdbEnv* mev,           // context
408     nsIMdbRow** acqRow,       // child row (or null)
409     nsIMdbTable** acqTable)   // child table (or null)
410 {
411   NS_ASSERTION(false, "not implemented");
412   return NS_ERROR_NOT_IMPLEMENTED;
413 }
414 
415 NS_IMETHODIMP
SetChildRow(nsIMdbEnv * mev,nsIMdbRow * ioRow)416 morkCellObject::SetChildRow(  // access table of specific attribute
417     nsIMdbEnv* mev,           // context
418     nsIMdbRow* ioRow) {
419   NS_ASSERTION(false, "not implemented");
420   return NS_ERROR_NOT_IMPLEMENTED;
421 }  // inRow must be bound inside this same db port
422 
GetChildRow(nsIMdbEnv * mev,nsIMdbRow ** acqRow)423 NS_IMETHODIMP morkCellObject::GetChildRow(  // access row of specific attribute
424     nsIMdbEnv* mev,                         // context
425     nsIMdbRow** acqRow)  // acquire child row (or nil if no child)
426 {
427   NS_ASSERTION(false, "not implemented");
428   return NS_ERROR_NOT_IMPLEMENTED;
429 }
430 
431 NS_IMETHODIMP
SetChildTable(nsIMdbEnv * mev,nsIMdbTable * inTable)432 morkCellObject::SetChildTable(  // access table of specific attribute
433     nsIMdbEnv* mev,             // context
434     nsIMdbTable* inTable)       // table must be bound inside this same db port
435 {
436   NS_ASSERTION(false, "not implemented");
437   return NS_ERROR_NOT_IMPLEMENTED;
438   // remember row->MaybeDirtySpaceStoreAndRow();
439 }
440 
441 NS_IMETHODIMP
GetChildTable(nsIMdbEnv * mev,nsIMdbTable ** acqTable)442 morkCellObject::GetChildTable(  // access table of specific attribute
443     nsIMdbEnv* mev,             // context
444     nsIMdbTable** acqTable)     // acquire child tabdle (or nil if no chil)
445 {
446   NS_ASSERTION(false, "not implemented");
447   return NS_ERROR_NOT_IMPLEMENTED;
448 }
449 // } ----- end children methods -----
450 
451 // } ===== end nsIMdbCell methods =====
452 
453 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
454