aboutsummaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/mkunit.cpp547
-rw-r--r--src/tools/nidstool.cpp248
2 files changed, 547 insertions, 248 deletions
diff --git a/src/tools/mkunit.cpp b/src/tools/mkunit.cpp
new file mode 100644
index 0000000..43fab38
--- /dev/null
+++ b/src/tools/mkunit.cpp
@@ -0,0 +1,547 @@
1#include <bu/file.h>
2#include <bu/optparser.h>
3#include <bu/buffer.h>
4#include <bu/list.h>
5#include <bu/sio.h>
6#include <bu/variant.h>
7
8using namespace Bu;
9
10class Test
11{
12public:
13 Test() :
14 bExpectPass( true )
15 {
16 }
17
18 Bu::FString sName;
19 bool bExpectPass;
20};
21typedef Bu::List<Test> TestList;
22
23class Suite
24{
25public:
26 Bu::FString sName;
27 TestList lTest;
28};
29//typedef Bu::List<Suite> SuiteList;
30
31enum TokType
32{
33 tokFluff,
34 tokSuite,
35 tokTest,
36 tokChar,
37 tokBlock,
38 tokEof
39};
40
41Bu::Formatter &operator<<( Bu::Formatter &f, TokType t )
42{
43 switch( t )
44 {
45 case tokFluff: return f << "tokFluff";
46 case tokSuite: return f << "tokSuite";
47 case tokTest: return f << "tokTest";
48 case tokChar: return f << "tokChar";
49 case tokBlock: return f << "tokBlock";
50 case tokEof: return f << "tokEof";
51 }
52
53 return f;
54}
55
56Bu::Formatter &operator<<( Bu::Formatter &f, const Test &t )
57{
58 return f << "{" << t.sName << ", bExpectPass=" << t.bExpectPass << "}";
59}
60
61Bu::Formatter &operator<<( Bu::Formatter &f, const Suite &s )
62{
63 return f << "Suite[" << s.sName << "] = " << s.lTest << f.nl;
64}
65
66class Parser
67{
68public:
69 Parser( const Bu::FString &sFile ) :
70 fIn( sFile, File::Read ),
71 bIn( fIn ),
72 cBuf( 0 ),
73 bAvail( false ),
74 eMode( mRoot ),
75 iLine( 1 ),
76 iChar( 0 ),
77 iDepth( 0 )
78 {
79 }
80
81 char nextChar()
82 {
83 if( bAvail )
84 return cBuf;
85
86 if( bIn.read( &cBuf, 1 ) < 1 )
87 throw Bu::ExceptionBase("End of stream");
88 bAvail = true;
89
90 if( cBuf == '\n' )
91 {
92 iLine++;
93 iChar = 0;
94 }
95 else
96 iChar++;
97
98 return cBuf;
99 }
100
101 TokType nextToken( Variant &v, Bu::FString &sWsOut, int &iLineStart,
102 int &iCharStart )
103 {
104 Bu::FString sTok, sWs;
105
106 char buf;
107 try
108 {
109 buf = nextChar();
110 }
111 catch(...)
112 {
113 return tokEof;
114 }
115
116 for(;;)
117 {
118 if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' )
119 {
120 sWs += buf;
121 bAvail = false;
122 }
123 else
124 break;
125
126 try
127 {
128 buf = nextChar();
129 }
130 catch(...)
131 {
132 sWsOut = sWs;
133 return tokEof;
134 }
135 }
136
137 sWsOut = sWs;
138
139 iLineStart = iLine;
140 iCharStart = iChar;
141 bool bInStr = false;
142 bool bDblStr;
143
144 for(;;)
145 {
146 switch( eMode )
147 {
148 case mRoot:
149 if( buf == ' ' || buf == '\t' || buf == '\n'
150 || buf == '\r' )
151 {
152 if( sTok == "suite" )
153 return tokSuite;
154 else
155 {
156 v = sTok;
157 return tokFluff;
158 }
159 }
160 else if( buf == '(' || buf == ')' || buf == '{'
161 || buf == '}' || buf == ';' )
162 {
163 if( sTok.getSize() == 0 )
164 {
165 bAvail = false;
166 v = buf;
167 return tokChar;
168 }
169 else
170 {
171 v = sTok;
172 return tokFluff;
173 }
174 }
175 else
176 {
177 sTok += buf;
178 bAvail = false;
179 }
180 break;
181
182 case mSuite:
183 if( buf == ' ' || buf == '\t' || buf == '\n'
184 || buf == '\r' )
185 {
186 if( sTok == "test" )
187 return tokTest;
188 else
189 {
190 v = sTok;
191 return tokFluff;
192 }
193 }
194 else if( buf == '(' || buf == ')'
195 || buf == '}' || buf == ';' )
196 {
197 if( sTok.getSize() == 0 )
198 {
199 bAvail = false;
200 v = buf;
201 return tokChar;
202 }
203 else
204 {
205 v = sTok;
206 return tokFluff;
207 }
208 }
209 else if( buf == '{' )
210 {
211 if( sTok.getSize() > 0 )
212 {
213 v = sTok;
214 return tokFluff;
215 }
216 else
217 {
218 sTok += buf;
219 bAvail = false;
220 eMode = mBlock;
221 iDepth = 1;
222 }
223 }
224 else
225 {
226 sTok += buf;
227 bAvail = false;
228 }
229 break;
230
231 case mBlock:
232 if( bInStr )
233 {
234 if( buf == '\\' )
235 {
236 sTok += buf;
237 bAvail = false;
238 sTok += nextChar();
239 bAvail = false;
240 }
241 else if( bDblStr == true && buf == '\"' )
242 {
243 sTok += buf;
244 bAvail = false;
245 bInStr = false;
246 }
247 else if( bDblStr == false && buf == '\'' )
248 {
249 sTok += buf;
250 bAvail = false;
251 bInStr = false;
252 }
253 else
254 {
255 sTok += buf;
256 bAvail = false;
257 }
258 }
259 else
260 {
261 if( buf == '\"' )
262 {
263 bInStr = true;
264 bDblStr = true;
265 sTok += buf;
266 bAvail = false;
267 }
268 else if( buf == '\'' )
269 {
270 bInStr = true;
271 bDblStr = false;
272 sTok += buf;
273 bAvail = false;
274 }
275 else if( buf == '}' )
276 {
277 sTok += buf;
278 bAvail = false;
279 iDepth--;
280 if( iDepth == 0 )
281 {
282 v = sTok;
283 eMode = mSuite;
284 return tokBlock;
285 }
286 }
287 else if( buf == '{' )
288 {
289 sTok += buf;
290 bAvail = false;
291 iDepth++;
292 }
293 else
294 {
295 sTok += buf;
296 bAvail = false;
297 }
298 }
299 break;
300 }
301
302 buf = nextChar();
303 }
304 }
305
306 void firstPass()
307 {
308 Variant v;
309 Bu::FString sWs;
310 int iL, iC;
311 for(;;)
312 {
313 TokType t = nextToken( v, sWs, iL, iC );
314 if( t == tokEof )
315 return;
316 switch( eMode )
317 {
318 case mRoot:
319 if( t == tokSuite )
320 {
321 if( nextToken( v, sWs, iL, iC ) != tokFluff )
322 throw Bu::ExceptionBase("%d:%d: Expected string "
323 "following suite.", iL, iC );
324 s.sName = v.get<Bu::FString>();
325 if( nextToken( v, sWs, iL, iC ) != tokChar ||
326 v.get<char>() != '{' )
327 throw Bu::ExceptionBase("%d:%d: Expected {, got "
328 "'%s'", iL, iC, v.toString().getStr() );
329 eMode = mSuite;
330 }
331 break;
332
333 case mSuite:
334 switch( t )
335 {
336 case tokFluff:
337 break;
338
339 case tokBlock:
340 break;
341
342 case tokTest:
343 {
344 if( nextToken( v, sWs, iL, iC ) != tokFluff )
345 throw Bu::ExceptionBase("%d:%d: Expected "
346 "string following test.", iL, iC );
347 Test t;
348 t.sName = v.get<Bu::FString>();
349 if( nextToken( v, sWs, iL, iC ) != tokBlock )
350 throw Bu::ExceptionBase("%d:%d: Expected "
351 "{...} block.",
352 iL, iC );
353 s.lTest.append( t );
354 }
355 break;
356
357 case tokChar:
358 if( v.get<char>() == '}' )
359 {
360 eMode = mRoot;
361 }
362 else
363 {
364 }
365 break;
366
367 default:
368 sio << iL << ":" << iC << ": Unexpected "
369 << t << " found." << sio.nl;
370 return;
371 break;
372 }
373 break;
374
375 default:
376 sio << "???" << sio.nl;
377 break;
378 }
379 }
380 }
381
382 void secondPass( const Bu::FString &sOut )
383 {
384 File fOut( sOut, File::WriteNew );
385 Formatter f( fOut );
386 fIn.setPos( 0 );
387 bIn.stop();
388 bIn.start();
389 bAvail = false;
390 eMode = mRoot;
391 iLine = 1;
392 iChar = 0;
393 bool bHasIncluded = false;
394
395 Bu::FString sWs;
396 Variant v;
397 int iL, iC;
398 for(;;)
399 {
400 TokType t = nextToken( v, sWs, iL, iC );
401 switch( eMode )
402 {
403 case mRoot:
404 if( t == tokSuite )
405 {
406 fOut.write( sWs );
407 if( nextToken( v, sWs, iL, iC ) != tokFluff )
408 throw Bu::ExceptionBase("%d:%d: Expected string "
409 "following suite.", iL, iC );
410 s.sName = v.get<Bu::FString>();
411 if( nextToken( v, sWs, iL, iC ) != tokChar ||
412 v.get<char>() != '{' )
413 throw Bu::ExceptionBase("%d:%d: Expected {",
414 iL, iC );
415 eMode = mSuite;
416
417 if( bHasIncluded == false )
418 {
419 fOut.write("#include <bu/unitsuite.h>\n");
420 bHasIncluded = true;
421 }
422
423 Bu::FString sClass = "_UnitSuite_" + s.sName;
424 f << "class " << sClass
425 << " : public Bu::UnitSuite" << f.nl
426 << "{" << f.nl << "public:" << f.nl
427 << "\t" << sClass << "()" << f.nl
428 << "\t{" << f.nl
429 << "\t\tsetName(\"" << s.sName << "\");" << f.nl;
430 for( TestList::iterator i = s.lTest.begin(); i; i++ )
431 {
432 f << "\t\tadd( static_cast<Bu::UnitSuite::Test>("
433 "&" << sClass << "::" << (*i).sName << "), \""
434 << (*i).sName << "\", Bu::UnitSuite::"
435 "expectPass );" << f.nl;
436 }
437 f << "\t}" << f.nl << f.nl
438 << "\tvirtual ~" << sClass << "() { }" << f.nl
439 << f.nl;
440 }
441 else if( t == tokEof )
442 {
443 Bu::FString sClass = "_UnitSuite_" + s.sName;
444 f << sWs << f.nl << "int main( int argc, char *argv[] )"
445 << f.nl << "{" << f.nl << "\treturn " << sClass
446 << "().run( argc, argv );" << f.nl << "}" << f.nl;
447 }
448 else
449 {
450 fOut.write( sWs );
451 f << v;
452 }
453 break;
454
455 case mSuite:
456 switch( t )
457 {
458 case tokFluff:
459 fOut.write( sWs );
460 fOut.write( v.get<Bu::FString>() );
461 break;
462
463 case tokTest:
464 {
465 fOut.write( sWs );
466 if( nextToken( v, sWs, iL, iC ) != tokFluff )
467 throw Bu::ExceptionBase("%d:%d: Expected "
468 "string following test.", iL, iC );
469 Test t;
470 t.sName = v.get<Bu::FString>();
471 if( nextToken( v, sWs, iL, iC ) != tokBlock )
472 throw Bu::ExceptionBase("%d:%d: Expected "
473 "{...} block.",
474 iL, iC );
475
476 f << "\tvoid " << t.sName << "()"
477 << f.nl << "#line " << iL
478 << " \"" << sOut << "\"" << f.nl
479 << v << f.nl;
480 }
481 break;
482
483 case tokChar:
484 if( v.get<char>() == '}' )
485 {
486 f << "};" << f.nl << f.nl;
487 eMode = mRoot;
488 }
489 else
490 {
491 char buf = v.get<char>();
492 fOut.write( sWs );
493 fOut.write( &buf, 1 );
494 }
495 break;
496
497 case tokBlock:
498 fOut.write( sWs );
499 f << f.nl << "#line " << iL << " \"" << sOut
500 << "\"" << f.nl;
501 fOut.write( v.get<Bu::FString>() );
502
503 break;
504
505 default:
506 sio << iL << ":" << iC << ": Unexpected "
507 << t << " found." << sio.nl;
508 return;
509 break;
510 }
511 break;
512
513 default:
514 sio << "???" << sio.nl;
515 break;
516 }
517 if( t == tokEof )
518 return;
519 }
520 }
521
522private:
523 File fIn;
524 Buffer bIn;
525 char cBuf;
526 bool bAvail;
527 enum Mode
528 {
529 mRoot,
530 mSuite,
531 mBlock
532 };
533 Mode eMode;
534 int iLine, iChar;
535 int iDepth;
536 Suite s;
537};
538
539int main( int argc, char *argv[] )
540{
541 Parser p( argv[1] );
542
543 p.firstPass();
544
545 p.secondPass( argv[2] );
546}
547
diff --git a/src/tools/nidstool.cpp b/src/tools/nidstool.cpp
deleted file mode 100644
index 41179f9..0000000
--- a/src/tools/nidstool.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/file.h"
9#include "bu/nids.h"
10#include "bu/nidsstream.h"
11#include "bu/paramproc.h"
12
13#include <stdlib.h>
14
15typedef struct Block
16{
17 uint32_t uFirstBlock;
18 uint32_t uNextBlock;
19 uint32_t uBytesUsed;
20} Block;
21
22class Param : public Bu::ParamProc
23{
24public:
25 Param( int argc, char *argv[] )
26 {
27 addHelpBanner("nidstool - Do stuff with nids files.\n\n");
28 addParam("info", 'i', mkproc(Param::procInfo),
29 "Print some info about the file.");
30 addParam("dump", 'd', mkproc(Param::procDump),
31 "Dump a stream to a file.");
32 addParam("analyze", 'a', mkproc(Param::procAnalyze),
33 "Analyze a nids file.");
34 addParam("copy", 'c', mkproc(Param::procCopy),
35 "Copy a nids file, changing settings.");
36 addParam("help", 'h', mkproc(Bu::ParamProc::help), "This help.");
37 process( argc, argv );
38 }
39
40 virtual ~Param()
41 {
42 }
43
44 void printInfo( Bu::Nids &n )
45 {
46 printf("File info:\n");
47 printf(" Header overhead: %db\n", n.getBlockStart() );
48 printf(" Block size: %db\n", n.getBlockSize() );
49 printf(" Block count: %d\n", n.getNumBlocks() );
50 printf(" Blocks used: %d (%d%%)\n", n.getNumUsedBlocks(),
51 n.getNumUsedBlocks()*100/n.getNumBlocks() );
52 printf(" Block overhead: %db\n", n.getBlockOverhead() );
53 printf(" Block storage: %db (%d%%)\n",
54 n.getBlockSize()-n.getBlockOverhead(),
55 (n.getBlockSize()-n.getBlockOverhead())*100/n.getBlockSize() );
56 }
57
58 int procInfo( int argc, char *argv[] )
59 {
60 if( argc < 1 )
61 {
62 printf("You must provide a file name.\n");
63 exit( 1 );
64 }
65
66 Bu::File fIn( argv[0], Bu::File::Read );
67 Bu::Nids n( fIn );
68 n.initialize();
69
70 printInfo( n );
71
72 if( argc >= 2 )
73 {
74 uint32_t uStream = strtoul( argv[1], NULL, 0 );
75 uint32_t uBlock = uStream;
76
77 Block b;
78
79 for(;;)
80 {
81 fIn.setPos( n.getBlockStart()+n.getBlockSize()*uBlock );
82 fIn.read( &b, sizeof(Block) );
83 printf("Stream %u: block %u, next %u, %ub used.\n",
84 uStream, uBlock, b.uNextBlock, b.uBytesUsed
85 );
86 if( b.uNextBlock == 0xFFFFFFFFUL )
87 break;
88 uBlock = b.uNextBlock;
89 }
90 printf("Stream End.\n");
91
92 return 2;
93 }
94
95 return 1;
96 }
97
98 int procDump( int argc, char *argv[] )
99 {
100 if( argc < 3 )
101 {
102 printf("You must provide a nids file, a stream id, and an output "
103 "file.\n");
104 exit( 1 );
105 }
106
107 Bu::File fIn( argv[0], Bu::File::Read );
108 Bu::Nids n( fIn );
109 n.initialize();
110
111 int iStream = strtol( argv[1], NULL, 0 );
112 Bu::NidsStream sIn = n.openStream( iStream );
113
114 Bu::File fOut( argv[2], Bu::File::Write|Bu::File::Create );
115 int iTotal = 0;
116 char buf[100];
117 for(;;)
118 {
119 int iRead = sIn.read( buf, 100 );
120 iTotal += fOut.write( buf, iRead );
121 if( iRead < 100 )
122 break;
123 }
124
125 printf("Wrote %db from stream %d in %s to %s.\n",
126 iTotal, iStream, argv[0], argv[2] );
127 return 3;
128 }
129
130 int procAnalyze( int argc, char *argv[] )
131 {
132 if( argc < 1 )
133 {
134 printf("You must provide a file name.\n");
135 exit( 1 );
136 }
137
138 Bu::File fIn( argv[0], Bu::File::Read );
139 Bu::Nids n( fIn );
140 n.initialize();
141
142 printInfo( n );
143
144 int iStreamCnt = 0;
145 int iStreamTotal = 0;
146 int iOneBlock = 0;
147 uint32_t iLargest = 0;
148 uint32_t iSmallest = 0;
149 int iWaste = 0;
150 int iUsable = n.getBlockSize()-n.getBlockOverhead();
151 Block b;
152 for( int j = 0; j < n.getNumBlocks(); j++ )
153 {
154 fIn.setPos( n.getBlockStart()+n.getBlockSize()*j );
155 fIn.read( &b, sizeof(Block) );
156 if( b.uFirstBlock != (uint32_t)j )
157 continue;
158
159 iStreamCnt++;
160 iStreamTotal += b.uBytesUsed;
161
162 if( b.uNextBlock == 0xFFFFFFFFUL )
163 {
164 iOneBlock++;
165 iWaste += iUsable - b.uBytesUsed;
166 }
167 else
168 {
169 iWaste += iUsable - (b.uBytesUsed%iUsable);
170 }
171
172 if( j == 0 )
173 {
174 iSmallest = iLargest = b.uBytesUsed;
175 }
176 else
177 {
178 if( iLargest < b.uBytesUsed )
179 iLargest = b.uBytesUsed;
180 if( iSmallest > b.uBytesUsed )
181 iSmallest = b.uBytesUsed;
182 }
183 }
184 printf("Steam analysis:\n");
185 printf(" Stream count: %d\n", iStreamCnt );
186 printf(" Stream size: %db/%db/%db (min/avr/max)\n",
187 iSmallest, iStreamTotal/iStreamCnt, iLargest );
188 printf(" One-block streams: %d (%d%%)\n",
189 iOneBlock, iOneBlock*100/iStreamCnt );
190 printf(" Total wasted space: %db (%d%%)\n",
191 iWaste, iWaste*100/iStreamTotal );
192 printf(" Avr blocks-per-stream: %f%%\n",
193 (float)n.getNumBlocks()/(float)iStreamCnt );
194
195 return 1;
196 }
197
198 int procCopy( int argc, char *argv[] )
199 {
200 if( argc < 3 )
201 {
202 printf("You must provide source stream, blocksize, destination.\n");
203 exit( 1 );
204 }
205
206 Bu::File fIn( argv[0], Bu::File::Read );
207 Bu::Nids nIn( fIn );
208 nIn.initialize();
209
210 Bu::File fOut( argv[2], Bu::File::Read|Bu::File::Write|Bu::File::Create|
211 Bu::File::Truncate );
212 Bu::Nids nOut( fOut );
213 nOut.initialize( strtol( argv[1], 0, NULL ) );
214
215 Block b;
216 for( int j = 0; j < nIn.getNumBlocks(); j++ )
217 {
218 fIn.setPos( nIn.getBlockStart()+nIn.getBlockSize()*j );
219 fIn.read( &b, sizeof(Block) );
220 if( b.uFirstBlock != (uint32_t)j )
221 continue;
222
223 Bu::NidsStream sIn = nIn.openStream( j );
224 int iNew = nOut.createStream();
225 Bu::NidsStream sOut = nOut.openStream( iNew );
226
227 char buf[1024];
228 for(;;)
229 {
230 int iRead = sIn.read( buf, 1024 );
231 sOut.write( buf, iRead );
232 if( iRead < 1024 )
233 break;
234 }
235 }
236
237 return 3;
238 }
239};
240
241
242int main( int argc, char *argv[] )
243{
244 Param p( argc, argv );
245
246 return 0;
247}
248