summaryrefslogtreecommitdiff
path: root/src/tools/nidstool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/nidstool.cpp')
-rw-r--r--src/tools/nidstool.cpp241
1 files changed, 241 insertions, 0 deletions
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 @@
1#include "bu/file.h"
2#include "bu/nids.h"
3#include "bu/nidsstream.h"
4#include "bu/paramproc.h"
5
6#include <stdlib.h>
7
8typedef struct Block
9{
10 uint32_t uFirstBlock;
11 uint32_t uNextBlock;
12 uint32_t uBytesUsed;
13} Block;
14
15class Param : public Bu::ParamProc
16{
17public:
18 Param( int argc, char *argv[] )
19 {
20 addHelpBanner("nidstool - Do stuff with nids files.\n\n");
21 addParam("info", 'i', mkproc(Param::procInfo),
22 "Print some info about the file.");
23 addParam("dump", 'd', mkproc(Param::procDump),
24 "Dump a stream to a file.");
25 addParam("analyze", 'a', mkproc(Param::procAnalyze),
26 "Analyze a nids file.");
27 addParam("copy", 'c', mkproc(Param::procCopy),
28 "Copy a nids file, changing settings.");
29 addParam("help", 'h', mkproc(Bu::ParamProc::help), "This help.");
30 process( argc, argv );
31 }
32
33 virtual ~Param()
34 {
35 }
36
37 void printInfo( Bu::Nids &n )
38 {
39 printf("File info:\n");
40 printf(" Header overhead: %db\n", n.getBlockStart() );
41 printf(" Block size: %db\n", n.getBlockSize() );
42 printf(" Block count: %d\n", n.getNumBlocks() );
43 printf(" Blocks used: %d (%d%%)\n", n.getNumUsedBlocks(),
44 n.getNumUsedBlocks()*100/n.getNumBlocks() );
45 printf(" Block overhead: %db\n", n.getBlockOverhead() );
46 printf(" Block storage: %db (%d%%)\n",
47 n.getBlockSize()-n.getBlockOverhead(),
48 (n.getBlockSize()-n.getBlockOverhead())*100/n.getBlockSize() );
49 }
50
51 int procInfo( int argc, char *argv[] )
52 {
53 if( argc < 1 )
54 {
55 printf("You must provide a file name.\n");
56 exit( 1 );
57 }
58
59 Bu::File fIn( argv[0], Bu::File::Read );
60 Bu::Nids n( fIn );
61 n.initialize();
62
63 printInfo( n );
64
65 if( argc >= 2 )
66 {
67 uint32_t uStream = strtoul( argv[1], NULL, 0 );
68 uint32_t uBlock = uStream;
69
70 Block b;
71
72 for(;;)
73 {
74 fIn.setPos( n.getBlockStart()+n.getBlockSize()*uBlock );
75 fIn.read( &b, sizeof(Block) );
76 printf("Stream %u: block %u, next %u, %ub used.\n",
77 uStream, uBlock, b.uNextBlock, b.uBytesUsed
78 );
79 if( b.uNextBlock == 0xFFFFFFFFUL )
80 break;
81 uBlock = b.uNextBlock;
82 }
83 printf("Stream End.\n");
84
85 return 2;
86 }
87
88 return 1;
89 }
90
91 int procDump( int argc, char *argv[] )
92 {
93 if( argc < 3 )
94 {
95 printf("You must provide a nids file, a stream id, and an output "
96 "file.\n");
97 exit( 1 );
98 }
99
100 Bu::File fIn( argv[0], Bu::File::Read );
101 Bu::Nids n( fIn );
102 n.initialize();
103
104 int iStream = strtol( argv[1], NULL, 0 );
105 Bu::NidsStream sIn = n.openStream( iStream );
106
107 Bu::File fOut( argv[2], Bu::File::Write|Bu::File::Create );
108 int iTotal = 0;
109 char buf[100];
110 for(;;)
111 {
112 int iRead = sIn.read( buf, 100 );
113 iTotal += fOut.write( buf, iRead );
114 if( iRead < 100 )
115 break;
116 }
117
118 printf("Wrote %db from stream %d in %s to %s.\n",
119 iTotal, iStream, argv[0], argv[2] );
120 return 3;
121 }
122
123 int procAnalyze( int argc, char *argv[] )
124 {
125 if( argc < 1 )
126 {
127 printf("You must provide a file name.\n");
128 exit( 1 );
129 }
130
131 Bu::File fIn( argv[0], Bu::File::Read );
132 Bu::Nids n( fIn );
133 n.initialize();
134
135 printInfo( n );
136
137 int iStreamCnt = 0;
138 int iStreamTotal = 0;
139 int iOneBlock = 0;
140 uint32_t iLargest = 0;
141 uint32_t iSmallest = 0;
142 int iWaste = 0;
143 int iUsable = n.getBlockSize()-n.getBlockOverhead();
144 Block b;
145 for( int j = 0; j < n.getNumBlocks(); j++ )
146 {
147 fIn.setPos( n.getBlockStart()+n.getBlockSize()*j );
148 fIn.read( &b, sizeof(Block) );
149 if( b.uFirstBlock != (uint32_t)j )
150 continue;
151
152 iStreamCnt++;
153 iStreamTotal += b.uBytesUsed;
154
155 if( b.uNextBlock == 0xFFFFFFFFUL )
156 {
157 iOneBlock++;
158 iWaste += iUsable - b.uBytesUsed;
159 }
160 else
161 {
162 iWaste += iUsable - (b.uBytesUsed%iUsable);
163 }
164
165 if( j == 0 )
166 {
167 iSmallest = iLargest = b.uBytesUsed;
168 }
169 else
170 {
171 if( iLargest < b.uBytesUsed )
172 iLargest = b.uBytesUsed;
173 if( iSmallest > b.uBytesUsed )
174 iSmallest = b.uBytesUsed;
175 }
176 }
177 printf("Steam analysis:\n");
178 printf(" Stream count: %d\n", iStreamCnt );
179 printf(" Stream size: %db/%db/%db (min/avr/max)\n",
180 iSmallest, iStreamTotal/iStreamCnt, iLargest );
181 printf(" One-block streams: %d (%d%%)\n",
182 iOneBlock, iOneBlock*100/iStreamCnt );
183 printf(" Total wasted space: %db (%d%%)\n",
184 iWaste, iWaste*100/iStreamTotal );
185 printf(" Avr blocks-per-stream: %f%%\n",
186 (float)n.getNumBlocks()/(float)iStreamCnt );
187
188 return 1;
189 }
190
191 int procCopy( int argc, char *argv[] )
192 {
193 if( argc < 3 )
194 {
195 printf("You must provide source stream, blocksize, destination.\n");
196 exit( 1 );
197 }
198
199 Bu::File fIn( argv[0], Bu::File::Read );
200 Bu::Nids nIn( fIn );
201 nIn.initialize();
202
203 Bu::File fOut( argv[2], Bu::File::Read|Bu::File::Write|Bu::File::Create|
204 Bu::File::Truncate );
205 Bu::Nids nOut( fOut );
206 nOut.initialize( strtol( argv[1], 0, NULL ) );
207
208 Block b;
209 for( int j = 0; j < nIn.getNumBlocks(); j++ )
210 {
211 fIn.setPos( nIn.getBlockStart()+nIn.getBlockSize()*j );
212 fIn.read( &b, sizeof(Block) );
213 if( b.uFirstBlock != (uint32_t)j )
214 continue;
215
216 Bu::NidsStream sIn = nIn.openStream( j );
217 int iNew = nOut.createStream();
218 Bu::NidsStream sOut = nOut.openStream( iNew );
219
220 char buf[1024];
221 for(;;)
222 {
223 int iRead = sIn.read( buf, 1024 );
224 sOut.write( buf, iRead );
225 if( iRead < 1024 )
226 break;
227 }
228 }
229
230 return 3;
231 }
232};
233
234
235int main( int argc, char *argv[] )
236{
237 Param p( argc, argv );
238
239 return 0;
240}
241