From b1522d279d22725a731cb8db93ec2d077028374c Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 26 May 2010 05:35:02 +0000 Subject: More tweaks and informational functions. --- src/array.h | 50 +++++++++++++++++++++++++++++ src/myriad.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/myriad.h | 58 +++++++++++++++++++++++++++------- src/tools/myriad.cpp | 17 ++++++++-- src/unit/array.unit | 19 +++++++++++ 5 files changed, 219 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/array.h b/src/array.h index 39efb9e..ede43cc 100644 --- a/src/array.h +++ b/src/array.h @@ -297,6 +297,17 @@ namespace Bu return *this; } + iterator operator+( int iAmnt ) + { + if( iPos < 0 ) + throw ArrayException( + "Cannot increment iterator past end of array."); + iPos += iAmnt; + if( iPos >= src.getSize() ) + iPos = -1; + return *this; + } + iterator operator--( int ) { if( iPos < 0 ) @@ -316,6 +327,15 @@ namespace Bu iPos = -1; return *this; } + + iterator operator-( int iAmnt ) + { + if( iPos < src.getSize() ) + iPos -= iAmnt; + if( iPos <= 0 ) + iPos = -1; + return *this; + } bool operator==( const iterator &oth ) const { @@ -477,6 +497,36 @@ namespace Bu return const_iterator( *this, -1 ); } + MyType &insert( iterator i, const value &rVal ) + { + if( i.iPos == -1 ) + { + append( rVal ); + return *this; + } + + _hardCopy(); + if( core->iSize == core->iCapacity ) + { + core->setCapacity( core->iCapacity + inc ); + } + core->iSize++; + + core->va.construct( + &core->pData[core->iSize-1], + core->pData[core->iSize-2] + ); + for( int iPos = core->iSize-2; iPos > i.iPos; iPos-- ) + { + core->va.destroy( &core->pData[iPos] ); + core->va.construct( &core->pData[iPos], core->pData[iPos-1] ); + } + core->va.destroy( &core->pData[i.iPos] ); + core->va.construct( &core->pData[i.iPos], rVal ); + + return *this; + } + /** * If order is important, use this. It will delete the suggested item * and move the rest of the data up a spot. This is a time O(n) diff --git a/src/myriad.cpp b/src/myriad.cpp index 2f5c14f..9d7a849 100644 --- a/src/myriad.cpp +++ b/src/myriad.cpp @@ -151,6 +151,7 @@ void Bu::Myriad::initialize() // << ", pIn->tell()=" << pIn->tell() << sio.nl; s.aBlocks.append( iBId ); bsBlockUsed.setBit( iBId ); + iUsed++; if( (j == 0 && k == iHeaderBlocks-1) ) { // sio << "Myriad: - End of prepartition, unlocking skipping." @@ -172,6 +173,13 @@ void Bu::Myriad::initialize() void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) { + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + delete *i; + } + aStreams.clear(); + iUsed = 0; + int iHeaderSize = 14 + 8 + 4; int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); char cBuf = 1; @@ -192,6 +200,7 @@ void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) // << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; bsBlockUsed.setSize( iPreAllocate, true ); + iUsed++; char *pBlock = new char[iBlockSize]; memset( pBlock, 0, iBlockSize ); @@ -240,6 +249,7 @@ void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) { pStr->aBlocks.append( j ); bsBlockUsed.setBit( j ); + iUsed++; } aStreams.append( pStr ); @@ -283,6 +293,7 @@ void Bu::Myriad::updateHeader() // << " to header." << sio.nl; aStreams[0]->aBlocks.append( iBlock ); bsBlockUsed.setBit( iBlock ); + iUsed++; iHeaderSize += 4; iNewBlocks = blkDiv( iHeaderSize, iBlockSize ); } @@ -339,6 +350,7 @@ int Bu::Myriad::createStream( int iPreAllocate ) // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; pStr->aBlocks.append( iFreeBlock ); bsBlockUsed.setBit( iFreeBlock ); + iUsed++; } bHeaderChanged = true; @@ -346,6 +358,52 @@ int Bu::Myriad::createStream( int iPreAllocate ) return pStr->iId; } +int Bu::Myriad::createStreamWithId( int iId, int iPreAllocate ) +{ + try + { + findStream( iId ); + throw MyriadException( MyriadException::streamExists, + "There is already a stream with the given id."); + } + catch( MyriadException &e ) + { + Stream *pStr = new Stream(); + pStr->iId = iId; + //sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" + // << iPreAllocate << sio.nl; + pStr->iSize = 0; + if( aStreams.last()->iId < iId ) + { + aStreams.append( pStr ); + } + else + { + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + if( (*i)->iId > iId ) + { + aStreams.insert( i, pStr ); + break; + } + } + } + + for( int j = 0; j < iPreAllocate; j++ ) + { + int iFreeBlock = findEmptyBlock(); + // sio << "Myriad: Adding block " << iFreeBlock << sio.nl; + pStr->aBlocks.append( iFreeBlock ); + bsBlockUsed.setBit( iFreeBlock ); + iUsed++; + } + + bHeaderChanged = true; + + return pStr->iId; + } +} + int Bu::Myriad::findEmptyBlock() { bHeaderChanged = true; @@ -374,6 +432,12 @@ int Bu::Myriad::findEmptyBlock() void Bu::Myriad::deleteStream( int iId ) { + if( iId < 0 ) + throw MyriadException( MyriadException::invalidStreamId, + "Invalid stream id."); + if( iId == 0 ) + throw MyriadException( MyriadException::protectedStream, + "You cannot delete stream zero, it is protected."); for( StreamArray::iterator i = aStreams.begin(); i; i++ ) { if( (*i)->iId == iId ) @@ -382,6 +446,7 @@ void Bu::Myriad::deleteStream( int iId ) for( BlockArray::iterator j = pStream->aBlocks.begin(); j; j++ ) { bsBlockUsed.setBit( *j, false ); + iUsed--; } aStreams.erase( i ); bHeaderChanged = true; @@ -391,12 +456,33 @@ void Bu::Myriad::deleteStream( int iId ) } } +Bu::Array Bu::Myriad::getStreamIds() +{ + Bu::Array aRet( aStreams.getSize() ); + for( StreamArray::iterator i = aStreams.begin(); i; i++ ) + { + aRet.append( (*i)->iId ); + } + + return aRet; +} + +int Bu::Myriad::getStreamSize( int iId ) +{ + return findStream( iId )->iSize; +} + Bu::MyriadStream Bu::Myriad::openStream( int iId ) { //sio << "Myriad: Request to open stream: " << iId << sio.nl; return MyriadStream( *this, findStream( iId ) ); } +int Bu::Myriad::getNumStreams() +{ + return aStreams.getSize(); +} + int Bu::Myriad::getBlockSize() { return iBlockSize; @@ -469,6 +555,7 @@ int Bu::Myriad::streamAddBlock( Stream *pStream ) int iBlock = findEmptyBlock(); pStream->aBlocks.append( iBlock ); bsBlockUsed.setBit( iBlock ); + iUsed++; return iBlock; } @@ -484,6 +571,8 @@ void Bu::Myriad::setStreamSize( Stream *pStream, long iSize ) for( int iNewSize = pStream->aBlocks.getSize()*iBlockSize; iNewSize-64 > iSize; iNewSize -= iBlockSize ) { + if( bsBlockUsed.getBit( pStream->aBlocks.last() ) ) + iUsed--; bsBlockUsed.setBit( pStream->aBlocks.last(), false ); pStream->aBlocks.eraseLast(); } diff --git a/src/myriad.h b/src/myriad.h index b5cd18c..53a42b8 100644 --- a/src/myriad.h +++ b/src/myriad.h @@ -26,16 +26,22 @@ namespace Bu invalidFormat, badVersion, invalidWordSize, - noSuchStream + noSuchStream, + streamExists, + invalidStreamId, + protectedStream }; subExceptionDeclEnd() /** - * Numerically Indexed Data Streams. This is a working name so I can - * actually get some code written instead of agonizing over the name. - * - * This is a system for creating streams that contain other streams in - * a flexible block-allocated system. + * Myriad block-allocated stream multiplexing system. This is a system for + * creating streams that contain other streams in a flexible and lightweight + * manner. Basically, you can create a file (or any other stream) that can + * store any number of flexible, growing streams. The streams within the + * Myriad stream are automatically numbered, not named. This works more + * or less like a filesystem, but without the extra layer for managing + * file and directory links. This would actually be very easy to add + * on top of Myriad, but is not required. * * Header format is as follows: * @@ -78,22 +84,42 @@ namespace Bu { friend class MyriadStream; public: + /** + * Create a Myriad object that uses the given stream to store data. + * This stream must be random access. The block size and preallocate + * values passed in are values that will be used if the given stream + * is empty. In that case the stream will be "formatted" for myriad + * with the specified block size. If there is already a viable Myriad + * format present in the stream, then the blocksize and preallocate + * values will be ignored and the values from the stream will be used + * instead. If the stream doesn't appear to be Myriad formatted an + * exception will be thrown. + */ Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); virtual ~Myriad(); /** - * Create a new Myriad system in the assosiated stream. This should be - * used carefully, it will destroy all data already within the stream. - * More options will probably be added soon. + * Destroy whatever data may be in the base stream and create a new + * Myriad system there with the given blocksize. Use this with care, + * it will destroy anything that was already in the stream, and + * generally, should not ever have to be used. */ void initialize( int iBlockSize, int iPreAllocate=1 ); /** - * Create a new stream within the Myriad system. The ID of the new stream - * is returned. + * Create a new stream within the Myriad system. The ID of the new + * stream is returned. */ int createStream( int iPreAllocate=1 ); + /** + * Create a new stream within the Myriad system with a given id. The + * id that you provide will be the new id of the stream unless it's + * already used, in which case an error is thrown. This is primarilly + * useful when copying an old Myriad file into a new one. + */ + int createStreamWithId( int iId, int iPreAllocate=1 ); + /** * Delete a stream that's already within the Myriad. */ @@ -104,10 +130,13 @@ namespace Bu */ MyriadStream openStream( int iId ); + Bu::Array getStreamIds(); + int getStreamSize( int iId ); + + int getNumStreams(); int getBlockSize(); int getNumBlocks(); int getNumUsedBlocks(); - int getBlockOverhead(); /** * Syncronize the header data, etc. with the storage stream. It's not @@ -115,6 +144,11 @@ namespace Bu */ void sync(); + /** + * Read the first few bytes from the given stream and return true/false + * depending on weather or not it's a Myriad stream. This will throw + * an exception if the stream is empty, or is not random access. + */ static bool isMyriad( Bu::Stream &sStore ); private: diff --git a/src/tools/myriad.cpp b/src/tools/myriad.cpp index 535d7ac..73ceba1 100644 --- a/src/tools/myriad.cpp +++ b/src/tools/myriad.cpp @@ -106,8 +106,7 @@ int main( int argc, char *argv[] ) else { File fOut( opts.sFile, File::WriteNew|File::Read ); - Myriad m( fOut ); - m.initialize( opts.iBlockSize, opts.iPreallocate ); + Myriad m( fOut, opts.iBlockSize, opts.iPreallocate ); } break; @@ -121,6 +120,20 @@ int main( int argc, char *argv[] ) { File fIn( opts.sFile, File::Read ); Myriad m( fIn ); + sio << "Myriad info:" << sio.nl + << " Block size: " << m.getBlockSize() << sio.nl + << " Block count: " << m.getNumBlocks() << sio.nl + << " Blocks used: " << m.getNumUsedBlocks() << " (" + << m.getNumUsedBlocks()*100/m.getNumBlocks() << "%)" + << sio.nl + << " Stream count: " << m.getNumStreams() << sio.nl; + Bu::Array aStreams = m.getStreamIds(); + sio << " Stream info:" << sio.nl; + for( Bu::Array::iterator i = aStreams.begin(); i; i++ ) + { + sio << " " << Fmt(4) << *i << ") " + << m.getStreamSize( *i ) << "b" << sio.nl; + } } break; diff --git a/src/unit/array.unit b/src/unit/array.unit index 1493033..f3fdeda 100644 --- a/src/unit/array.unit +++ b/src/unit/array.unit @@ -9,6 +9,9 @@ #include "bu/hash.h" #include "bu/array.h" +#include "bu/sio.h" +using Bu::sio; + suite Array { test general @@ -82,4 +85,20 @@ suite Array unitTest( a3[1].get("Test") == "Bloop" ); unitTest( a3[1].get("Foo") == "ooF" ); } + + test insert + { + Bu::Array aInts; + aInts.insert( aInts.end(), 4 ); + aInts.insert( aInts.begin(), 1 ); + aInts.insert( aInts.end(), 5 ); + aInts.insert( aInts.begin()+1, 3 ); + aInts.insert( aInts.begin()+1, 2 ); + aInts.insert( aInts.begin(), 0 ); + + for( int j = 0; j < 6; j++ ) + { + unitTest( aInts[j] == j ); + } + } } -- cgit v1.2.3