From 514721c24c7212c084ad2530e8239ff121097818 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 6 Apr 2009 19:13:51 +0000 Subject: Ok, I rearranged some things, we have a tools dir now, those build by default. Also I added a bunch of classes that I've been tinkering with that are almost ready for use, so I figured I may as well throw them in here. --- src/tools/nidstool.cpp | 241 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 src/tools/nidstool.cpp (limited to 'src/tools') diff --git a/src/tools/nidstool.cpp b/src/tools/nidstool.cpp new file mode 100644 index 0000000..d1465ce --- /dev/null +++ b/src/tools/nidstool.cpp @@ -0,0 +1,241 @@ +#include "bu/file.h" +#include "bu/nids.h" +#include "bu/nidsstream.h" +#include "bu/paramproc.h" + +#include + +typedef struct Block +{ + uint32_t uFirstBlock; + uint32_t uNextBlock; + uint32_t uBytesUsed; +} Block; + +class Param : public Bu::ParamProc +{ +public: + Param( int argc, char *argv[] ) + { + addHelpBanner("nidstool - Do stuff with nids files.\n\n"); + addParam("info", 'i', mkproc(Param::procInfo), + "Print some info about the file."); + addParam("dump", 'd', mkproc(Param::procDump), + "Dump a stream to a file."); + addParam("analyze", 'a', mkproc(Param::procAnalyze), + "Analyze a nids file."); + addParam("copy", 'c', mkproc(Param::procCopy), + "Copy a nids file, changing settings."); + addParam("help", 'h', mkproc(Bu::ParamProc::help), "This help."); + process( argc, argv ); + } + + virtual ~Param() + { + } + + void printInfo( Bu::Nids &n ) + { + printf("File info:\n"); + printf(" Header overhead: %db\n", n.getBlockStart() ); + printf(" Block size: %db\n", n.getBlockSize() ); + printf(" Block count: %d\n", n.getNumBlocks() ); + printf(" Blocks used: %d (%d%%)\n", n.getNumUsedBlocks(), + n.getNumUsedBlocks()*100/n.getNumBlocks() ); + printf(" Block overhead: %db\n", n.getBlockOverhead() ); + printf(" Block storage: %db (%d%%)\n", + n.getBlockSize()-n.getBlockOverhead(), + (n.getBlockSize()-n.getBlockOverhead())*100/n.getBlockSize() ); + } + + int procInfo( int argc, char *argv[] ) + { + if( argc < 1 ) + { + printf("You must provide a file name.\n"); + exit( 1 ); + } + + Bu::File fIn( argv[0], Bu::File::Read ); + Bu::Nids n( fIn ); + n.initialize(); + + printInfo( n ); + + if( argc >= 2 ) + { + uint32_t uStream = strtoul( argv[1], NULL, 0 ); + uint32_t uBlock = uStream; + + Block b; + + for(;;) + { + fIn.setPos( n.getBlockStart()+n.getBlockSize()*uBlock ); + fIn.read( &b, sizeof(Block) ); + printf("Stream %u: block %u, next %u, %ub used.\n", + uStream, uBlock, b.uNextBlock, b.uBytesUsed + ); + if( b.uNextBlock == 0xFFFFFFFFUL ) + break; + uBlock = b.uNextBlock; + } + printf("Stream End.\n"); + + return 2; + } + + return 1; + } + + int procDump( int argc, char *argv[] ) + { + if( argc < 3 ) + { + printf("You must provide a nids file, a stream id, and an output " + "file.\n"); + exit( 1 ); + } + + Bu::File fIn( argv[0], Bu::File::Read ); + Bu::Nids n( fIn ); + n.initialize(); + + int iStream = strtol( argv[1], NULL, 0 ); + Bu::NidsStream sIn = n.openStream( iStream ); + + Bu::File fOut( argv[2], Bu::File::Write|Bu::File::Create ); + int iTotal = 0; + char buf[100]; + for(;;) + { + int iRead = sIn.read( buf, 100 ); + iTotal += fOut.write( buf, iRead ); + if( iRead < 100 ) + break; + } + + printf("Wrote %db from stream %d in %s to %s.\n", + iTotal, iStream, argv[0], argv[2] ); + return 3; + } + + int procAnalyze( int argc, char *argv[] ) + { + if( argc < 1 ) + { + printf("You must provide a file name.\n"); + exit( 1 ); + } + + Bu::File fIn( argv[0], Bu::File::Read ); + Bu::Nids n( fIn ); + n.initialize(); + + printInfo( n ); + + int iStreamCnt = 0; + int iStreamTotal = 0; + int iOneBlock = 0; + uint32_t iLargest = 0; + uint32_t iSmallest = 0; + int iWaste = 0; + int iUsable = n.getBlockSize()-n.getBlockOverhead(); + Block b; + for( int j = 0; j < n.getNumBlocks(); j++ ) + { + fIn.setPos( n.getBlockStart()+n.getBlockSize()*j ); + fIn.read( &b, sizeof(Block) ); + if( b.uFirstBlock != (uint32_t)j ) + continue; + + iStreamCnt++; + iStreamTotal += b.uBytesUsed; + + if( b.uNextBlock == 0xFFFFFFFFUL ) + { + iOneBlock++; + iWaste += iUsable - b.uBytesUsed; + } + else + { + iWaste += iUsable - (b.uBytesUsed%iUsable); + } + + if( j == 0 ) + { + iSmallest = iLargest = b.uBytesUsed; + } + else + { + if( iLargest < b.uBytesUsed ) + iLargest = b.uBytesUsed; + if( iSmallest > b.uBytesUsed ) + iSmallest = b.uBytesUsed; + } + } + printf("Steam analysis:\n"); + printf(" Stream count: %d\n", iStreamCnt ); + printf(" Stream size: %db/%db/%db (min/avr/max)\n", + iSmallest, iStreamTotal/iStreamCnt, iLargest ); + printf(" One-block streams: %d (%d%%)\n", + iOneBlock, iOneBlock*100/iStreamCnt ); + printf(" Total wasted space: %db (%d%%)\n", + iWaste, iWaste*100/iStreamTotal ); + printf(" Avr blocks-per-stream: %f%%\n", + (float)n.getNumBlocks()/(float)iStreamCnt ); + + return 1; + } + + int procCopy( int argc, char *argv[] ) + { + if( argc < 3 ) + { + printf("You must provide source stream, blocksize, destination.\n"); + exit( 1 ); + } + + Bu::File fIn( argv[0], Bu::File::Read ); + Bu::Nids nIn( fIn ); + nIn.initialize(); + + Bu::File fOut( argv[2], Bu::File::Read|Bu::File::Write|Bu::File::Create| + Bu::File::Truncate ); + Bu::Nids nOut( fOut ); + nOut.initialize( strtol( argv[1], 0, NULL ) ); + + Block b; + for( int j = 0; j < nIn.getNumBlocks(); j++ ) + { + fIn.setPos( nIn.getBlockStart()+nIn.getBlockSize()*j ); + fIn.read( &b, sizeof(Block) ); + if( b.uFirstBlock != (uint32_t)j ) + continue; + + Bu::NidsStream sIn = nIn.openStream( j ); + int iNew = nOut.createStream(); + Bu::NidsStream sOut = nOut.openStream( iNew ); + + char buf[1024]; + for(;;) + { + int iRead = sIn.read( buf, 1024 ); + sOut.write( buf, iRead ); + if( iRead < 1024 ) + break; + } + } + + return 3; + } +}; + + +int main( int argc, char *argv[] ) +{ + Param p( argc, argv ); + + return 0; +} + -- cgit v1.2.3