/////////////////////////////////////////////////////////////////////////////// // CreateChildArray /////////////////////////////////////////////////////////////////////////////// void cHierDatabaseIter::CreateChildArray() //throw (eArchive, eHierDatabase) { ASSERT( ! Done() ); ASSERT( ! CanDescend() ); if( Done() ) { throw eHierDatabase( _T("Attempt to call iter::CreateChildArray() when done is true")); } if( CanDescend() ) { throw eHierDatabase( _T("Attempt to call iter::CreateChildArray() when child already exists")); } cHierArrayInfo newInfo; cHierAddr infoAddr; // write the new info newInfo.mParent = mInfoAddr; infoAddr = util_WriteObject( mpDb, &newInfo ); mIter->mChild = infoAddr; // // rewrite the current object, since its child info just changed // util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); }
/////////////////////////////////////////////////////////////////////////////// // AtRoot /////////////////////////////////////////////////////////////////////////////// bool cHierDatabaseIter::AtRoot() const //throw (eHierDatabase) { bool bResult = ( mInfoAddr == mpDb->mRootArrayAddr ); // TODO -- maybe I want to put this in a #ifdef? // if( bResult ) { // we are at the root; assert that we have no parent... // ASSERT( mInfo.mParent.IsNull() ); if( ! mInfo.mParent.IsNull() ) { throw eHierDatabase( _T("Root node of db has a non-null parent") ); } } else { // if we are not at the root, assert that we have a parent... ASSERT( ! mInfo.mParent.IsNull() ); if( mInfo.mParent.IsNull() ) { throw eHierDatabase( _T("Non-root node of db has a null parent!") ); } } return bResult; }
/////////////////////////////////////////////////////////////////////////////// // SetFCOData /////////////////////////////////////////////////////////////////////////////// void cDbDataSourceIter::SetFCOData( const iFCO* pFCO ) //throw (eError) { ASSERT( ! Done() ); if( Done() ) { throw eHierDatabase( _T("Attempt to set FCO data when the iterator is done.") ); } // TODO -- assert and throw if the fco's type is not the same as our creation function // There is no way to do this through the serializable interface, but when there is, // we should do the above assertion. // // if data already exists here, we first remove it; // if( mDbIter.HasData() ) { mDbIter.RemoveData(); } // // write the fco's property set to a memory archive... // // TODO -- does this need to be static? static cMemoryArchive arch; arch.Seek ( 0, cBidirArchive::BEGINNING ); cSerializerImpl ser (arch, cSerializerImpl::S_WRITE); ser.Init(); ser.WriteObject ( pFCO->GetPropSet() ); ser.Finit(); // // write this to the archive... // mDbIter.SetData( arch.GetMemory(), arch.CurrentPos() ); }
/////////////////////////////////////////////////////////////////////////////// // DeleteChildArray /////////////////////////////////////////////////////////////////////////////// void cHierDatabaseIter::DeleteChildArray() //throw (eArchive, eHierDatabase) { ASSERT( ! Done() ); ASSERT( CanDescend() ); cDebug d("cHierDatabaseIter::DeleteChildArray"); if( Done() ) { d.TraceDetail("Attempt to DeleteChildArray() when Done() == true; returning\n"); return; } if( ! CanDescend() ) { d.TraceDetail("Attempt to DeleteChildArray() when none exists; returning\n"); return; } // // make sure that the child index is empty... // if( ! ChildArrayEmpty() ) { ASSERT( false ); throw eHierDatabase( _T("Attempt to delete a child array that still has entries") ); } // // ok, no we can remove it... // mpDb->RemoveItem( cBlockRecordFile::tAddr( mIter->mChild.mBlockNum, mIter->mChild.mIndex ) ); mIter->mChild = cHierAddr(); util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); }
/////////////////////////////////////////////////////////////////////////////// // GetName /////////////////////////////////////////////////////////////////////////////// const TCHAR* cHierDatabaseIter::GetName() const { ASSERT( ! Done() ); if( Done() ) { throw eHierDatabase( _T("Attempt to call iter::GetName() when done is true")); } return mIter->mName.c_str(); }
static inline void util_ThrowIfNull( const cHierAddr& addr, const TSTRING& context ) { ASSERT( ! addr.IsNull() ); if( addr.IsNull() ) { TSTRING msg(_T("Attempt to access null address")); if( ! context.empty() ) { msg += _T(" in ") + context; } throw eHierDatabase( msg ); } }
/////////////////////////////////////////////////////////////////////////////// // GetData /////////////////////////////////////////////////////////////////////////////// int8* cHierDatabaseIter::GetData(int32& length) const //throw (eArchive, eHierDatabase) { ASSERT( HasData() ); if( ! HasData() ) { throw eHierDatabase( _T("Attempt to get data from a node when HasData() is false")); } // // note that we can only get data for reading; perhaps in the future I will add // support for retrieving data for writing as well. // return mpDb->GetDataForReading( cBlockRecordFile::tAddr(mIter->mData.mBlockNum, mIter->mData.mIndex), length ); }
/////////////////////////////////////////////////////////////////////////////// // DeleteEntry /////////////////////////////////////////////////////////////////////////////// void cHierDatabaseIter::DeleteEntry() //throw (eArchive, eHierDatabase) { ASSERT( ! Done() ); ASSERT( ! CanDescend() ); // this node can't have any children. cDebug d("cHierDatabaseIter::DeleteEntry"); if( Done() ) { d.TraceDetail("Attempt to DeleteEntry() when Done() == true; returning\n"); return; } if( CanDescend() ) { throw eHierDatabase( _T("Attempt to delete an entry that still has children.\n")); } // // first, we should set the previous node's next pointer... // cHierAddr curAddr = GetCurrentAddr(); if( mIter == mEntries.begin() ) { // we are changing the info's mArray pointer // mInfo.mArray = mIter->mNext; util_RewriteObject( mpDb, &mInfo, mInfoAddr ); } else { // altering the previous node... // mIter--; mIter->mNext = (mIter+1)->mNext; util_RewriteObject( mpDb, &(*mIter), GetCurrentAddr() ); mIter++; } // // now, delete the node from the file and from our array... // mpDb->RemoveItem( cBlockRecordFile::tAddr( curAddr.mBlockNum, curAddr.mIndex ) ); mIter = mEntries.erase(mIter); }