Back to index

lightning-sunbird  0.9+nobinonly
morkRowObject.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef _MDB_
00039 #include "mdb.h"
00040 #endif
00041 
00042 #ifndef _MORK_
00043 #include "mork.h"
00044 #endif
00045 
00046 #ifndef _MORKNODE_
00047 #include "morkNode.h"
00048 #endif
00049 
00050 #ifndef _MORKROWOBJECT_
00051 #include "morkRowObject.h"
00052 #endif
00053 
00054 #ifndef _MORKENV_
00055 #include "morkEnv.h"
00056 #endif
00057 
00058 #ifndef _MORKSTORE_
00059 #include "morkStore.h"
00060 #endif
00061 
00062 #ifndef _MORKROWCELLCURSOR_
00063 #include "morkRowCellCursor.h"
00064 #endif
00065 
00066 #ifndef _MORKCELLOBJECT_
00067 #include "morkCellObject.h"
00068 #endif
00069 
00070 #ifndef _MORKROW_
00071 #include "morkRow.h"
00072 #endif
00073 
00074 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00075 
00076 // ````` ````` ````` ````` ````` 
00077 // { ===== begin morkNode interface =====
00078 
00079 /*public virtual*/ void
00080 morkRowObject::CloseMorkNode(morkEnv* ev) // CloseRowObject() only if open
00081 {
00082   if ( this->IsOpenNode() )
00083   {
00084     this->MarkClosing();
00085     this->CloseRowObject(ev);
00086     this->MarkShut();
00087   }
00088 }
00089 
00090 /*public virtual*/
00091 morkRowObject::~morkRowObject() // assert CloseRowObject() executed earlier
00092 {
00093   CloseMorkNode(mMorkEnv);
00094   MORK_ASSERT(this->IsShutNode());
00095 }
00096 
00097 /*public non-poly*/
00098 morkRowObject::morkRowObject(morkEnv* ev,
00099   const morkUsage& inUsage, nsIMdbHeap* ioHeap,
00100      morkRow* ioRow, morkStore* ioStore)
00101 : morkObject(ev, inUsage, ioHeap, morkColor_kNone, (morkHandle*) 0)
00102 , mRowObject_Row( 0 )
00103 , mRowObject_Store( 0 )
00104 {
00105   if ( ev->Good() )
00106   {
00107     if ( ioRow && ioStore )
00108     {
00109       mRowObject_Row = ioRow;
00110       mRowObject_Store = ioStore; // morkRowObjects don't ref-cnt the owning store.
00111       
00112       if ( ev->Good() )
00113         mNode_Derived = morkDerived_kRowObject;
00114     }
00115     else
00116       ev->NilPointerError();
00117   }
00118 }
00119 
00120 NS_IMPL_ISUPPORTS_INHERITED1(morkRowObject, morkObject, nsIMdbRow)
00121 // { ===== begin nsIMdbCollection methods =====
00122 
00123 // { ----- begin attribute methods -----
00124 NS_IMETHODIMP
00125 morkRowObject::GetSeed(nsIMdbEnv* mev,
00126   mdb_seed* outSeed)
00127 {
00128   mdb_err outErr = 0;
00129   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00130   if ( ev )
00131   {
00132     *outSeed = (mdb_seed) mRowObject_Row->mRow_Seed;
00133     outErr = ev->AsErr();
00134   }
00135   return outErr;
00136 }
00137 NS_IMETHODIMP
00138 morkRowObject::GetCount(nsIMdbEnv* mev,
00139   mdb_count* outCount)
00140 {
00141   mdb_err outErr = 0;
00142   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00143   if ( ev )
00144   {
00145     *outCount = (mdb_count) mRowObject_Row->mRow_Length;
00146     outErr = ev->AsErr();
00147   }
00148   return outErr;
00149 }
00150 
00151 NS_IMETHODIMP
00152 morkRowObject::GetPort(nsIMdbEnv* mev,
00153   nsIMdbPort** acqPort)
00154 {
00155   mdb_err outErr = 0;
00156   nsIMdbPort* outPort = 0;
00157   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00158   if ( ev )
00159   {
00160     morkRowSpace* rowSpace = mRowObject_Row->mRow_Space;
00161     if ( rowSpace && rowSpace->mSpace_Store )
00162     {
00163       morkStore* store = mRowObject_Row->GetRowSpaceStore(ev);
00164       if ( store )
00165         outPort = store->AcquireStoreHandle(ev);
00166     }
00167     else
00168       ev->NilPointerError();
00169       
00170     outErr = ev->AsErr();
00171   }
00172   if ( acqPort )
00173     *acqPort = outPort;
00174     
00175   return outErr;
00176 }
00177 // } ----- end attribute methods -----
00178 
00179 // { ----- begin cursor methods -----
00180 NS_IMETHODIMP
00181 morkRowObject::GetCursor( // make a cursor starting iter at inMemberPos
00182   nsIMdbEnv* mev, // context
00183   mdb_pos inMemberPos, // zero-based ordinal pos of member in collection
00184   nsIMdbCursor** acqCursor)
00185 {
00186   return this->GetRowCellCursor(mev, inMemberPos,
00187     (nsIMdbRowCellCursor**) acqCursor);
00188 }
00189 // } ----- end cursor methods -----
00190 
00191 // { ----- begin ID methods -----
00192 NS_IMETHODIMP
00193 morkRowObject::GetOid(nsIMdbEnv* mev,
00194   mdbOid* outOid)
00195 {
00196   *outOid = mRowObject_Row->mRow_Oid;
00197   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00198   return (ev) ? ev->AsErr() : NS_ERROR_FAILURE;
00199 }
00200 
00201 NS_IMETHODIMP
00202 morkRowObject::BecomeContent(nsIMdbEnv* mev,
00203   const mdbOid* inOid)
00204 {
00205   NS_ASSERTION(PR_FALSE, "not implemented");
00206   return NS_ERROR_NOT_IMPLEMENTED;
00207   // remember row->MaybeDirtySpaceStoreAndRow();
00208 }
00209 // } ----- end ID methods -----
00210 
00211 // { ----- begin activity dropping methods -----
00212 NS_IMETHODIMP
00213 morkRowObject::DropActivity( // tell collection usage no longer expected
00214   nsIMdbEnv* mev)
00215 {
00216   NS_ASSERTION(PR_FALSE, "not implemented");
00217   return NS_ERROR_NOT_IMPLEMENTED;
00218 }
00219 // } ----- end activity dropping methods -----
00220 
00221 // } ===== end nsIMdbCollection methods =====
00222 
00223 // { ===== begin nsIMdbRow methods =====
00224 
00225 // { ----- begin cursor methods -----
00226 NS_IMETHODIMP
00227 morkRowObject::GetRowCellCursor( // make a cursor starting iteration at inCellPos
00228   nsIMdbEnv* mev, // context
00229   mdb_pos inPos, // zero-based ordinal position of cell in row
00230   nsIMdbRowCellCursor** acqCursor)
00231 {
00232   mdb_err outErr = 0;
00233   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00234   nsIMdbRowCellCursor* outCursor = 0;
00235   if ( ev )
00236   {
00237     morkRowCellCursor* cursor = mRowObject_Row->NewRowCellCursor(ev, inPos);
00238     if ( cursor )
00239     {
00240       if ( ev->Good() )
00241       {
00242         cursor->mCursor_Seed = (mork_seed) inPos;
00243         outCursor = cursor;
00244         NS_ADDREF(cursor);
00245       }
00246     }
00247     outErr = ev->AsErr();
00248   }
00249   if ( acqCursor )
00250     *acqCursor = outCursor;
00251   return outErr;
00252 }
00253 // } ----- end cursor methods -----
00254 
00255 // { ----- begin column methods -----
00256 NS_IMETHODIMP
00257 morkRowObject::AddColumn( // make sure a particular column is inside row
00258   nsIMdbEnv* mev, // context
00259   mdb_column inColumn, // column to add
00260   const mdbYarn* inYarn)
00261 {
00262   mdb_err outErr = NS_ERROR_FAILURE;
00263   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00264   if ( ev )
00265   {
00266     if ( mRowObject_Store && mRowObject_Row)
00267       mRowObject_Row->AddColumn(ev, inColumn, inYarn, mRowObject_Store);
00268       
00269     outErr = ev->AsErr();
00270   }
00271   return outErr;
00272 }
00273 
00274 NS_IMETHODIMP
00275 morkRowObject::CutColumn( // make sure a column is absent from the row
00276   nsIMdbEnv* mev, // context
00277   mdb_column inColumn)
00278 {
00279   mdb_err outErr = NS_ERROR_FAILURE;
00280   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00281   if ( ev )
00282   {
00283     mRowObject_Row->CutColumn(ev, inColumn);
00284     outErr = ev->AsErr();
00285   }
00286   return outErr;
00287 }
00288 
00289 NS_IMETHODIMP
00290 morkRowObject::CutAllColumns( // remove all columns from the row
00291   nsIMdbEnv* mev)
00292 {
00293   mdb_err outErr = 0;
00294   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00295   if ( ev )
00296   {
00297     mRowObject_Row->CutAllColumns(ev);
00298     outErr = ev->AsErr();
00299   }
00300   return outErr;
00301 }
00302 // } ----- end column methods -----
00303 
00304 // { ----- begin cell methods -----
00305 NS_IMETHODIMP
00306 morkRowObject::NewCell( // get cell for specified column, or add new one
00307   nsIMdbEnv* mev, // context
00308   mdb_column inColumn, // column to add
00309   nsIMdbCell** acqCell)
00310 {
00311   mdb_err outErr = 0;
00312   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00313   if ( ev )
00314   {
00315     GetCell(mev, inColumn, acqCell);
00316     if ( !*acqCell )
00317     {
00318       if ( mRowObject_Store )
00319       {
00320         mdbYarn yarn; // to pass empty yarn into morkRowObject::AddColumn()
00321         yarn.mYarn_Buf = 0;
00322         yarn.mYarn_Fill = 0;
00323         yarn.mYarn_Size = 0;
00324         yarn.mYarn_More = 0;
00325         yarn.mYarn_Form = 0;
00326         yarn.mYarn_Grow = 0;
00327         AddColumn(ev, inColumn, &yarn);
00328         GetCell(mev, inColumn, acqCell);
00329       }
00330     }
00331       
00332     outErr = ev->AsErr();
00333   }
00334   return outErr;
00335 }
00336   
00337 NS_IMETHODIMP
00338 morkRowObject::AddCell( // copy a cell from another row to this row
00339   nsIMdbEnv* mev, // context
00340   const nsIMdbCell* inCell)
00341 {
00342   mdb_err outErr = 0;
00343   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00344   if ( ev )
00345   {
00346     morkCell* cell = 0;
00347     morkCellObject* cellObj = (morkCellObject*) inCell;
00348     if ( cellObj->CanUseCell(mev, morkBool_kFalse, &outErr, &cell) )
00349     {
00350 
00351       morkRow* cellRow = cellObj->mCellObject_Row;
00352       if ( cellRow )
00353       {
00354         if ( mRowObject_Row != cellRow )
00355         {
00356           morkStore* store = mRowObject_Row->GetRowSpaceStore(ev);
00357           morkStore* cellStore = cellRow->GetRowSpaceStore(ev);
00358           if ( store && cellStore )
00359           {
00360             mork_column col = cell->GetColumn();
00361             morkAtom* atom = cell->mCell_Atom;
00362             mdbYarn yarn;
00363             atom->AliasYarn(&yarn); // works even when atom is nil
00364             
00365             if ( store != cellStore )
00366               col = store->CopyToken(ev, col, cellStore);
00367             if ( ev->Good() )
00368               AddColumn(ev, col, &yarn);
00369           }
00370           else
00371             ev->NilPointerError();
00372         }
00373       }
00374       else
00375         ev->NilPointerError();
00376     }
00377 
00378     outErr = ev->AsErr();
00379   }
00380   return outErr;
00381 }
00382   
00383 NS_IMETHODIMP
00384 morkRowObject::GetCell( // find a cell in this row
00385   nsIMdbEnv* mev, // context
00386   mdb_column inColumn, // column to find
00387   nsIMdbCell** acqCell)
00388 {
00389   mdb_err outErr = 0;
00390   nsIMdbCell* outCell = 0;
00391   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00392 
00393   if ( ev )
00394   {
00395     if ( inColumn )
00396     {
00397       mork_pos pos = 0;
00398       morkCell* cell = mRowObject_Row->GetCell(ev, inColumn, &pos);
00399       if ( cell )
00400       {
00401         outCell = mRowObject_Row->AcquireCellHandle(ev, cell, inColumn, pos);
00402       }
00403     }
00404     else
00405       mRowObject_Row->ZeroColumnError(ev);
00406       
00407     outErr = ev->AsErr();
00408   }
00409   if ( acqCell )
00410     *acqCell = outCell;
00411   return outErr;
00412 }
00413   
00414 NS_IMETHODIMP
00415 morkRowObject::EmptyAllCells( // make all cells in row empty of content
00416   nsIMdbEnv* mev)
00417 {
00418   mdb_err outErr = 0;
00419   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00420   if ( ev )
00421   {
00422     EmptyAllCells(ev);
00423     outErr = ev->AsErr();
00424   }
00425   return outErr;
00426 }
00427 // } ----- end cell methods -----
00428 
00429 // { ----- begin row methods -----
00430 NS_IMETHODIMP
00431 morkRowObject::AddRow( // add all cells in another row to this one
00432   nsIMdbEnv* mev, // context
00433   nsIMdbRow* ioSourceRow)
00434 {
00435   mdb_err outErr = 0;
00436   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00437   if ( ev )
00438   {
00439     morkRow* unsafeSource = (morkRow*) ioSourceRow; // unsafe cast
00440 //    if ( unsafeSource->CanUseRow(mev, morkBool_kFalse, &outErr, &source) )
00441     {
00442       mRowObject_Row->AddRow(ev, unsafeSource);
00443     }
00444     outErr = ev->AsErr();
00445   }
00446   return outErr;
00447 }
00448   
00449 NS_IMETHODIMP
00450 morkRowObject::SetRow( // make exact duplicate of another row
00451   nsIMdbEnv* mev, // context
00452   nsIMdbRow* ioSourceRow)
00453 {
00454   mdb_err outErr = 0;
00455   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00456   if ( ev )
00457   {
00458     morkRowObject *sourceObject = (morkRowObject *) ioSourceRow; // unsafe cast
00459     morkRow* unsafeSource = sourceObject->mRowObject_Row;
00460 //    if ( unsafeSource->CanUseRow(mev, morkBool_kFalse, &outErr, &source) )
00461     {
00462       mRowObject_Row->SetRow(ev, unsafeSource);
00463     }
00464     outErr = ev->AsErr();
00465   }
00466   return outErr;
00467 }
00468 // } ----- end row methods -----
00469 
00470 // { ----- begin blob methods -----
00471 NS_IMETHODIMP
00472 morkRowObject::SetCellYarn( // synonym for AddColumn()
00473   nsIMdbEnv* mev, // context
00474   mdb_column inColumn, // column to add
00475   const mdbYarn* inYarn)
00476 {
00477   mdb_err outErr = 0;
00478   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00479   if ( ev )
00480   {
00481     if ( mRowObject_Store )
00482       AddColumn(ev, inColumn, inYarn);
00483       
00484     outErr = ev->AsErr();
00485   }
00486   return outErr;
00487 }
00488 NS_IMETHODIMP
00489 morkRowObject::GetCellYarn(
00490   nsIMdbEnv* mev, // context
00491   mdb_column inColumn, // column to read 
00492   mdbYarn* outYarn)  // writes some yarn slots 
00493 // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
00494 {
00495   mdb_err outErr = 0;
00496   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00497   if ( ev )
00498   {
00499     if ( mRowObject_Store && mRowObject_Row)
00500     {
00501       morkAtom* atom = mRowObject_Row->GetColumnAtom(ev, inColumn);
00502       atom->GetYarn(outYarn);
00503       // note nil atom works and sets yarn correctly
00504     }
00505       
00506     outErr = ev->AsErr();
00507   }
00508   return outErr;
00509 }
00510 
00511 NS_IMETHODIMP
00512 morkRowObject::AliasCellYarn(
00513   nsIMdbEnv* mev, // context
00514     mdb_column inColumn, // column to alias
00515     mdbYarn* outYarn) // writes ALL yarn slots
00516 {
00517   mdb_err outErr = 0;
00518   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00519   if ( ev )
00520   {
00521     if ( mRowObject_Store && mRowObject_Row)
00522     {
00523       morkAtom* atom = mRowObject_Row->GetColumnAtom(ev, inColumn);
00524       atom->AliasYarn(outYarn);
00525       // note nil atom works and sets yarn correctly
00526     }
00527     outErr = ev->AsErr();
00528   }
00529   return outErr;
00530 }
00531 
00532 NS_IMETHODIMP
00533 morkRowObject::NextCellYarn(nsIMdbEnv* mev, // iterative version of GetCellYarn()
00534   mdb_column* ioColumn, // next column to read
00535   mdbYarn* outYarn)  // writes some yarn slots 
00536 // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
00537 //
00538 // The ioColumn argument is an inout parameter which initially contains the
00539 // last column accessed and returns the next column corresponding to the
00540 // content read into the yarn.  Callers should start with a zero column
00541 // value to say 'no previous column', which causes the first column to be
00542 // read.  Then the value returned in ioColumn is perfect for the next call
00543 // to NextCellYarn(), since it will then be the previous column accessed.
00544 // Callers need only examine the column token returned to see which cell
00545 // in the row is being read into the yarn.  When no more columns remain,
00546 // and the iteration has ended, ioColumn will return a zero token again.
00547 // So iterating over cells starts and ends with a zero column token.
00548 {
00549   mdb_err outErr = 0;
00550   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00551   if ( ev )
00552   {
00553     if ( mRowObject_Store && mRowObject_Row)
00554       mRowObject_Row->NextColumn(ev, ioColumn, outYarn);
00555       
00556     outErr = ev->AsErr();
00557   }
00558   return outErr;
00559 }
00560 
00561 NS_IMETHODIMP
00562 morkRowObject::SeekCellYarn( // resembles nsIMdbRowCellCursor::SeekCell()
00563   nsIMdbEnv* mev, // context
00564   mdb_pos inPos, // position of cell in row sequence
00565   mdb_column* outColumn, // column for this particular cell
00566   mdbYarn* outYarn) // writes some yarn slots
00567 // copy content into the yarn buffer, and update mYarn_Fill and mYarn_Form
00568 // Callers can pass nil for outYarn to indicate no interest in content, so
00569 // only the outColumn value is returned.  NOTE to subclasses: you must be
00570 // able to ignore outYarn when the pointer is nil; please do not crash.
00571 
00572 {
00573   mdb_err outErr = 0;
00574   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00575   if ( ev )
00576   {
00577     if ( mRowObject_Store && mRowObject_Row)
00578       mRowObject_Row->SeekColumn(ev, inPos, outColumn, outYarn);
00579       
00580     outErr = ev->AsErr();
00581   }
00582   return outErr;
00583 }
00584 
00585 // } ----- end blob methods -----
00586 
00587 
00588 // } ===== end nsIMdbRow methods =====
00589 
00590 
00591 
00592 /*public non-poly*/ void
00593 morkRowObject::CloseRowObject(morkEnv* ev) // called by CloseMorkNode();
00594 {
00595   if ( this )
00596   {
00597     if ( this->IsNode() )
00598     {
00599       morkRow* row = mRowObject_Row;
00600       mRowObject_Row = 0;
00601       this->CloseObject(ev);
00602       this->MarkShut();
00603 
00604       if ( row )
00605       {
00606         MORK_ASSERT(row->mRow_Object == this);
00607         if ( row->mRow_Object == this )
00608         {
00609           row->mRow_Object = 0; // just nil this slot -- cut ref down below
00610           
00611           mRowObject_Store = 0; // morkRowObjects don't ref-cnt the owning store.
00612             
00613           this->CutWeakRef(ev->AsMdbEnv()); // do last, because it might self destroy
00614         }
00615       }
00616     }
00617     else
00618       this->NonNodeError(ev);
00619   }
00620   else
00621     ev->NilPointerError();
00622 }
00623 
00624 // } ===== end morkNode methods =====
00625 // ````` ````` ````` ````` ````` 
00626 
00627 /*static*/ void
00628 morkRowObject::NonRowObjectTypeError(morkEnv* ev)
00629 {
00630   ev->NewError("non morkRowObject");
00631 }
00632 
00633 /*static*/ void
00634 morkRowObject::NilRowError(morkEnv* ev)
00635 {
00636   ev->NewError("nil mRowObject_Row");
00637 }
00638 
00639 /*static*/ void
00640 morkRowObject::NilStoreError(morkEnv* ev)
00641 {
00642   ev->NewError("nil mRowObject_Store");
00643 }
00644 
00645 /*static*/ void
00646 morkRowObject::RowObjectRowNotSelfError(morkEnv* ev)
00647 {
00648   ev->NewError("mRowObject_Row->mRow_Object != self");
00649 }
00650 
00651 
00652 nsIMdbRow*
00653 morkRowObject::AcquireRowHandle(morkEnv* ev) // mObject_Handle
00654 {
00655   AddRef();
00656   return this;
00657 }
00658 
00659 
00660 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789