1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
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.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
51 #include "morkHandle.h"
70 #ifndef _MORKROWOBJECT_
71 #include "morkRowObject.h"
74 #ifndef _MORKCELLOBJECT_
75 #include "morkCellObject.h"
79 #include "morkStore.h"
83 #include "orkinStore.h"
86 #ifndef _MORKROWSPACE_
87 #include "morkRowSpace.h"
90 #ifndef _MORKROWCELLCURSOR_
91 #include "morkRowCellCursor.h"
94 #ifndef _ORKINROWCELLCURSOR_
95 #include "orkinRowCellCursor.h"
99 #include "orkinCell.h"
102 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
105 orkinRow:: ~orkinRow() // morkHandle destructor does everything
109 /*protected non-poly construction*/
110 orkinRow::orkinRow(morkEnv
* ev
, // morkUsage is morkUsage_kPool
111 morkHandleFace
* ioFace
, // must not be nil, cookie for this handle
112 morkRowObject
* ioObject
) // must not be nil, the object for this handle
113 : morkHandle(ev
, ioFace
, ioObject
, morkMagic_kRow
)
115 // do not modify mNode_Derived; leave it equal to morkDerived_kHandle
119 /*static */ orkinRow
*
120 orkinRow::MakeRow(morkEnv
* ev
, morkRowObject
* ioObject
)
122 mork_bool isEnv
= ev
->IsEnv();
126 morkHandleFace
* face
= ev
->NewHandle(sizeof(orkinRow
));
128 return new(face
) orkinRow(ev
, face
, ioObject
);
130 ev
->OutOfMemoryError();
133 return (orkinRow
*) 0;
137 orkinRow::CanUseRow(nsIMdbEnv
* mev
, mork_bool inMutable
,
138 mdb_err
* outErr
, morkRow
** outRow
) const
141 morkRow
* innerRow
= 0;
142 morkEnv
* ev
= morkEnv::FromMdbEnv(mev
);
145 morkRowObject
* rowObj
= (morkRowObject
*)
146 this->GetGoodHandleObject(ev
, inMutable
, morkMagic_kRow
,
147 /*inClosedOkay*/ morkBool_kFalse
);
150 if ( rowObj
->IsRowObject() )
152 morkRow
* row
= rowObj
->mRowObject_Row
;
157 if ( row
->mRow_Object
== rowObj
)
163 rowObj
->RowObjectRowNotSelfError(ev
);
166 row
->NonRowTypeError(ev
);
169 rowObj
->NilRowError(ev
);
172 rowObj
->NonRowObjectTypeError(ev
);
174 *outErr
= ev
->AsErr();
183 orkinRow::CanUseRowStore(morkEnv
* ev
) const
185 morkStore
* outStore
= 0;
186 morkRowObject
* rowObj
= (morkRowObject
*) mHandle_Object
;
187 if ( rowObj
&& rowObj
->IsRowObject() )
189 morkStore
* store
= rowObj
->mRowObject_Store
;
192 if ( store
->IsStore() )
197 store
->NonStoreTypeError(ev
);
200 rowObj
->NilStoreError(ev
);
206 // { ===== begin nsISupports methods =====
207 NS_IMPL_QUERY_INTERFACE1(orkinRow
, nsIMdbRow
)
210 orkinRow::AddRef() // add strong ref with no
212 morkEnv
* ev
= mHandle_Env
;
213 if ( ev
&& ev
->IsEnv() )
214 return this->Handle_AddStrongRef(ev
->AsMdbEnv());
216 return morkEnv_kNonEnvTypeError
;
220 orkinRow::Release() // cut strong ref
222 morkEnv
* ev
= mHandle_Env
;
223 if ( ev
&& ev
->IsEnv() )
224 return this->Handle_CutStrongRef(ev
->AsMdbEnv());
226 return morkEnv_kNonEnvTypeError
;
228 // } ===== end nsIMdbObject methods =====
231 // { ===== begin nsIMdbObject methods =====
233 // { ----- begin attribute methods -----
235 orkinRow::IsFrozenMdbObject(nsIMdbEnv
* mev
, mdb_bool
* outIsReadonly
)
237 return this->Handle_IsFrozenMdbObject(mev
, outIsReadonly
);
239 // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
240 // } ----- end attribute methods -----
242 // { ----- begin factory methods -----
244 orkinRow::GetMdbFactory(nsIMdbEnv
* mev
, nsIMdbFactory
** acqFactory
)
246 return this->Handle_GetMdbFactory(mev
, acqFactory
);
248 // } ----- end factory methods -----
250 // { ----- begin ref counting for well-behaved cyclic graphs -----
252 orkinRow::GetWeakRefCount(nsIMdbEnv
* mev
, // weak refs
255 return this->Handle_GetWeakRefCount(mev
, outCount
);
258 orkinRow::GetStrongRefCount(nsIMdbEnv
* mev
, // strong refs
261 return this->Handle_GetStrongRefCount(mev
, outCount
);
265 orkinRow::AddWeakRef(nsIMdbEnv
* mev
)
267 return this->Handle_AddWeakRef(mev
);
270 orkinRow::AddStrongRef(nsIMdbEnv
* mev
)
272 return this->Handle_AddStrongRef(mev
);
276 orkinRow::CutWeakRef(nsIMdbEnv
* mev
)
278 return this->Handle_CutWeakRef(mev
);
281 orkinRow::CutStrongRef(nsIMdbEnv
* mev
)
283 return this->Handle_CutStrongRef(mev
);
287 orkinRow::CloseMdbObject(nsIMdbEnv
* mev
)
289 return this->Handle_CloseMdbObject(mev
);
293 orkinRow::IsOpenMdbObject(nsIMdbEnv
* mev
, mdb_bool
* outOpen
)
295 return this->Handle_IsOpenMdbObject(mev
, outOpen
);
297 // } ----- end ref counting -----
299 // } ===== end nsIMdbObject methods =====
302 // { ===== begin nsIMdbCollection methods =====
304 // { ----- begin attribute methods -----
306 orkinRow::GetSeed(nsIMdbEnv
* mev
,
311 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
315 *outSeed
= (mdb_seed
) row
->mRow_Seed
;
316 outErr
= ev
->AsErr();
321 orkinRow::GetCount(nsIMdbEnv
* mev
,
326 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
330 *outCount
= (mdb_count
) row
->mRow_Length
;
331 outErr
= ev
->AsErr();
337 orkinRow::GetPort(nsIMdbEnv
* mev
,
338 nsIMdbPort
** acqPort
)
341 nsIMdbPort
* outPort
= 0;
343 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
347 morkRowSpace
* rowSpace
= row
->mRow_Space
;
348 if ( rowSpace
&& rowSpace
->mSpace_Store
)
350 morkStore
* store
= row
->GetRowSpaceStore(ev
);
352 outPort
= store
->AcquireStoreHandle(ev
);
355 ev
->NilPointerError();
357 outErr
= ev
->AsErr();
364 // } ----- end attribute methods -----
366 // { ----- begin cursor methods -----
368 orkinRow::GetCursor( // make a cursor starting iter at inMemberPos
369 nsIMdbEnv
* mev
, // context
370 mdb_pos inMemberPos
, // zero-based ordinal pos of member in collection
371 nsIMdbCursor
** acqCursor
)
373 return this->GetRowCellCursor(mev
, inMemberPos
,
374 (nsIMdbRowCellCursor
**) acqCursor
);
376 // } ----- end cursor methods -----
378 // { ----- begin ID methods -----
380 orkinRow::GetOid(nsIMdbEnv
* mev
,
385 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
389 *outOid
= row
->mRow_Oid
;
390 outErr
= ev
->AsErr();
396 orkinRow::BecomeContent(nsIMdbEnv
* mev
,
402 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
406 // remember row->MaybeDirtySpaceStoreAndRow();
408 ev
->StubMethodOnlyError();
409 outErr
= ev
->AsErr();
413 // } ----- end ID methods -----
415 // { ----- begin activity dropping methods -----
417 orkinRow::DropActivity( // tell collection usage no longer expected
422 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
426 // ev->StubMethodOnlyError(); // do nothing
427 outErr
= ev
->AsErr();
431 // } ----- end activity dropping methods -----
433 // } ===== end nsIMdbCollection methods =====
435 // { ===== begin nsIMdbRow methods =====
437 // { ----- begin cursor methods -----
439 orkinRow::GetRowCellCursor( // make a cursor starting iteration at inRowPos
440 nsIMdbEnv
* mev
, // context
441 mdb_pos inPos
, // zero-based ordinal position of row in table
442 nsIMdbRowCellCursor
** acqCursor
)
445 nsIMdbRowCellCursor
* outCursor
= 0;
447 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
451 morkRowCellCursor
* cursor
= row
->NewRowCellCursor(ev
, inPos
);
456 cursor
->mCursor_Seed
= (mork_seed
) inPos
;
457 outCursor
= cursor
->AcquireRowCellCursorHandle(ev
);
460 cursor
->CutStrongRef(mev
);
462 outErr
= ev
->AsErr();
465 *acqCursor
= outCursor
;
468 // } ----- end cursor methods -----
470 // { ----- begin column methods -----
472 orkinRow::AddColumn( // make sure a particular column is inside row
473 nsIMdbEnv
* mev
, // context
474 mdb_column inColumn
, // column to add
475 const mdbYarn
* inYarn
)
479 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
483 morkStore
* store
= this->CanUseRowStore(ev
);
485 row
->AddColumn(ev
, inColumn
, inYarn
, store
);
487 outErr
= ev
->AsErr();
493 orkinRow::CutColumn( // make sure a column is absent from the row
494 nsIMdbEnv
* mev
, // context
499 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
503 row
->CutColumn(ev
, inColumn
);
504 outErr
= ev
->AsErr();
510 orkinRow::CutAllColumns( // remove all columns from the row
515 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
519 row
->CutAllColumns(ev
);
520 outErr
= ev
->AsErr();
524 // } ----- end column methods -----
526 // { ----- begin cell methods -----
528 orkinRow::NewCell( // get cell for specified column, or add new one
529 nsIMdbEnv
* mev
, // context
530 mdb_column inColumn
, // column to add
531 nsIMdbCell
** acqCell
)
534 nsIMdbCell
* outCell
= 0;
536 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
541 morkCell
* cell
= row
->GetCell(ev
, inColumn
, &pos
);
544 morkStore
* store
= this->CanUseRowStore(ev
);
547 mdbYarn yarn
; // to pass empty yarn into morkRow::AddColumn()
554 row
->AddColumn(ev
, inColumn
, &yarn
, store
);
555 cell
= row
->GetCell(ev
, inColumn
, &pos
);
559 outCell
= row
->AcquireCellHandle(ev
, cell
, inColumn
, pos
);
561 outErr
= ev
->AsErr();
569 orkinRow::AddCell( // copy a cell from another row to this row
570 nsIMdbEnv
* mev
, // context
571 const nsIMdbCell
* inCell
)
575 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
580 morkCellObject
* cellObj
= (morkCellObject
*) inCell
;
581 if ( cellObj
->CanUseCell(mev
, morkBool_kFalse
, &outErr
, &cell
) )
584 morkRow
* cellRow
= cellObj
->mCellObject_Row
;
587 if ( row
!= cellRow
)
589 morkStore
* store
= row
->GetRowSpaceStore(ev
);
590 morkStore
* cellStore
= cellRow
->GetRowSpaceStore(ev
);
591 if ( store
&& cellStore
)
593 mork_column col
= cell
->GetColumn();
594 morkAtom
* atom
= cell
->mCell_Atom
;
596 atom
->AliasYarn(&yarn
); // works even when atom is nil
598 if ( store
!= cellStore
)
599 col
= store
->CopyToken(ev
, col
, cellStore
);
601 row
->AddColumn(ev
, col
, &yarn
, store
);
604 ev
->NilPointerError();
608 ev
->NilPointerError();
611 outErr
= ev
->AsErr();
617 orkinRow::GetCell( // find a cell in this row
618 nsIMdbEnv
* mev
, // context
619 mdb_column inColumn
, // column to find
620 nsIMdbCell
** acqCell
)
623 nsIMdbCell
* outCell
= 0;
625 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
632 morkCell
* cell
= row
->GetCell(ev
, inColumn
, &pos
);
635 outCell
= row
->AcquireCellHandle(ev
, cell
, inColumn
, pos
);
639 row
->ZeroColumnError(ev
);
641 outErr
= ev
->AsErr();
649 orkinRow::EmptyAllCells( // make all cells in row empty of content
654 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
658 row
->EmptyAllCells(ev
);
659 outErr
= ev
->AsErr();
663 // } ----- end cell methods -----
665 // { ----- begin row methods -----
667 orkinRow::AddRow( // add all cells in another row to this one
668 nsIMdbEnv
* mev
, // context
669 nsIMdbRow
* ioSourceRow
)
673 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
678 orkinRow
* unsafeSource
= (orkinRow
*) ioSourceRow
; // unsafe cast
679 if ( unsafeSource
->CanUseRow(mev
, morkBool_kFalse
, &outErr
, &source
) )
681 row
->AddRow(ev
, source
);
683 outErr
= ev
->AsErr();
689 orkinRow::SetRow( // make exact duplicate of another row
690 nsIMdbEnv
* mev
, // context
691 nsIMdbRow
* ioSourceRow
)
695 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
700 orkinRow
* unsafeSource
= (orkinRow
*) ioSourceRow
; // unsafe cast
701 if ( unsafeSource
->CanUseRow(mev
, morkBool_kFalse
, &outErr
, &source
) )
703 row
->SetRow(ev
, source
);
705 outErr
= ev
->AsErr();
709 // } ----- end row methods -----
711 // { ----- begin blob methods -----
713 orkinRow::SetCellYarn( // synonym for AddColumn()
714 nsIMdbEnv
* mev
, // context
715 mdb_column inColumn
, // column to add
716 const mdbYarn
* inYarn
)
720 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
724 morkStore
* store
= this->CanUseRowStore(ev
);
726 row
->AddColumn(ev
, inColumn
, inYarn
, store
);
728 outErr
= ev
->AsErr();
733 orkinRow::GetCellYarn(
734 nsIMdbEnv
* mev
, // context
735 mdb_column inColumn
, // column to read
736 mdbYarn
* outYarn
) // writes some yarn slots
737 // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
741 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
745 morkStore
* store
= this->CanUseRowStore(ev
);
748 morkAtom
* atom
= row
->GetColumnAtom(ev
, inColumn
);
749 atom
->GetYarn(outYarn
);
750 // note nil atom works and sets yarn correctly
753 outErr
= ev
->AsErr();
759 orkinRow::AliasCellYarn(
760 nsIMdbEnv
* mev
, // context
761 mdb_column inColumn
, // column to alias
762 mdbYarn
* outYarn
) // writes ALL yarn slots
766 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
770 morkStore
* store
= this->CanUseRowStore(ev
);
773 morkAtom
* atom
= row
->GetColumnAtom(ev
, inColumn
);
774 atom
->AliasYarn(outYarn
);
775 // note nil atom works and sets yarn correctly
777 outErr
= ev
->AsErr();
783 orkinRow::NextCellYarn(nsIMdbEnv
* mev
, // iterative version of GetCellYarn()
784 mdb_column
* ioColumn
, // next column to read
785 mdbYarn
* outYarn
) // writes some yarn slots
786 // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
788 // The ioColumn argument is an inout parameter which initially contains the
789 // last column accessed and returns the next column corresponding to the
790 // content read into the yarn. Callers should start with a zero column
791 // value to say 'no previous column', which causes the first column to be
792 // read. Then the value returned in ioColumn is perfect for the next call
793 // to NextCellYarn(), since it will then be the previous column accessed.
794 // Callers need only examine the column token returned to see which cell
795 // in the row is being read into the yarn. When no more columns remain,
796 // and the iteration has ended, ioColumn will return a zero token again.
797 // So iterating over cells starts and ends with a zero column token.
801 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
805 morkStore
* store
= this->CanUseRowStore(ev
);
807 row
->NextColumn(ev
, ioColumn
, outYarn
);
809 outErr
= ev
->AsErr();
815 orkinRow::SeekCellYarn( // resembles nsIMdbRowCellCursor::SeekCell()
816 nsIMdbEnv
* mev
, // context
817 mdb_pos inPos
, // position of cell in row sequence
818 mdb_column
* outColumn
, // column for this particular cell
819 mdbYarn
* outYarn
) // writes some yarn slots
820 // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
821 // Callers can pass nil for outYarn to indicate no interest in content, so
822 // only the outColumn value is returned. NOTE to subclasses: you must be
823 // able to ignore outYarn when the pointer is nil; please do not crash.
828 morkEnv
* ev
= this->CanUseRow(mev
, /*inMutable*/ morkBool_kFalse
,
832 morkStore
* store
= this->CanUseRowStore(ev
);
834 row
->SeekColumn(ev
, inPos
, outColumn
, outYarn
);
836 outErr
= ev
->AsErr();
841 // } ----- end blob methods -----
844 // } ===== end nsIMdbRow methods =====
848 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789