home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Programming Contest / Test Code Folder / Shared Test Code / ProblemUtils.cp < prev    next >
Encoding:
Text File  |  1998-06-08  |  9.1 KB  |  435 lines  |  [TEXT/CWIE]

  1. #include "ProblemUtils.h"
  2.  
  3. #include <stdio.h>
  4. #include <string.h>
  5.  
  6. const int buffer_size = 2000;
  7. static char buffer[buffer_size];
  8. static char buffer2[buffer_size];
  9.  
  10. pascal OSErr ProblemFSRead( short rn, long reqsize, long *resultsize, char *data )
  11. {
  12.     OSErr err;
  13.     *resultsize = reqsize;
  14.     
  15.     err = FSRead( rn, resultsize, data );
  16.     if ( err == eofErr && *resultsize > 0 ) {
  17.         err = noErr;
  18.     }
  19.     return err;
  20. }
  21.  
  22. pascal OSErr ProblemFSMustRead( short rn, long reqsize, char *data )
  23. {
  24.     OSErr err;
  25.     long resultsize = reqsize;
  26.     
  27.     err = FSRead( rn, &resultsize, data );
  28.     if ( err == noErr && resultsize < reqsize ) {
  29.         err = eofErr;
  30.     }
  31.     return err;
  32. }
  33.  
  34. pascal OSErr ProblemFSWrite( short rn, long reqsize, char *data )
  35. {
  36.     OSErr err;
  37.     long savedsize;
  38.     
  39.     savedsize = reqsize;
  40.     err = FSWrite( rn, &reqsize, data );
  41.     if ( err == noErr && reqsize != savedsize ) {    
  42.         err = -1;
  43.     }
  44.     return err;
  45. }
  46.  
  47. pascal OSErr ProblemCopyData( short frn, short trn )
  48. {
  49.     OSErr err;
  50.     long len;
  51.     
  52.     err = noErr;
  53.     while ( err == noErr ) {
  54.         err = ProblemFSRead( frn, buffer_size, &len, buffer );
  55.         if ( err == eofErr ) {
  56.             err = noErr;
  57.             break;
  58.         }
  59.         if ( err == noErr ) {
  60.             err = ProblemFSWrite( trn, len, buffer );
  61.         }
  62.     }
  63.     return err;
  64. }
  65.  
  66. pascal OSErr ProblemDuplicateFile( const FSSpec *from, const FSSpec *to )
  67. {
  68.     OSErr err, err2;
  69.     short frn, trn;
  70.     
  71.     (void) FSpDelete( to );
  72.     err = FSpCreate( to, 'CWIE', 'TEXT', 0 );
  73.     if ( err == noErr ) {
  74.         err = FSpOpenDF( from, fsRdPerm, &frn );
  75.         if ( err == noErr ) {
  76.             err = FSpOpenDF( to, fsWrPerm, &trn );
  77.             if ( err == noErr ) {
  78.                 err = ProblemCopyData( frn, trn );
  79.                 err2 = FSClose( trn );
  80.                 if ( err == noErr ) {
  81.                     err = err2;
  82.                 }
  83.             }
  84.             (void) FSClose( frn );
  85.         }
  86.     }
  87.     if ( err != noErr ) {
  88.         (void) FSpDelete( to );
  89.     }
  90.     return err;
  91. }
  92.  
  93. pascal OSErr ProblemDiffData( short rn1, short rn2 )
  94. {
  95.     OSErr err, err1, err2;
  96.     long len1, len2, i;
  97.     
  98.     err = noErr;
  99.     while ( err == noErr ) {
  100.     
  101.         err1 = ProblemFSRead( rn1, buffer_size, &len1, buffer );
  102.         err2 = ProblemFSRead( rn2, buffer_size, &len2, buffer2 );
  103.         
  104.         if ( err1 == eofErr && err2 == eofErr ) {
  105.             break;
  106.         }
  107.         if ( err1 != noErr ) {
  108.             err = err1;
  109.             break;
  110.         }
  111.         if ( err2 != noErr ) {
  112.             err = err2;
  113.             break;
  114.         }
  115.         if ( len1 != len2 ) {
  116.             err = eofErr;
  117.             break;
  118.         }
  119.         
  120.         for( i = 0; i < len1; i++ ) {
  121.             if ( buffer[i] != buffer2[i] ) {
  122.                 break;
  123.             }
  124.         }
  125.         if ( i != len1 ) {
  126.             err = badFileFormat;
  127.             break;
  128.         }
  129.     }
  130.     return err;
  131. }
  132.  
  133. pascal Boolean ProblemDiffFiles( const FSSpec *file1, const FSSpec *file2 )
  134. {
  135.     OSErr err;
  136.     short rn1, rn2;
  137.     
  138.     err = FSpOpenDF( file1, fsRdPerm, &rn1 );
  139.     if ( err == noErr ) {
  140.         err = FSpOpenDF( file2, fsRdPerm, &rn2 );
  141.         if ( err == noErr ) {
  142.             err = ProblemDiffData( rn1, rn2 );
  143.             (void) FSClose( rn2 );
  144.         }
  145.         (void) FSClose( rn1 );
  146.     }
  147.     return err != noErr;
  148. }
  149.  
  150. pascal OSErr ProblemGetTestDirectoryFSSpec( FSSpec *spec )
  151. {
  152.     OSErr err;
  153.     FCBPBRec fpb;
  154.     CInfoPBRec pb;
  155.     Str255 name;
  156.     Str15 number;
  157.     
  158.     fpb.ioNamePtr = name;
  159.     fpb.ioVRefNum = 0;
  160.     fpb.ioRefNum = CurResFile();
  161.     fpb.ioFCBIndx = 0;
  162.     err = PBGetFCBInfoSync( &fpb );
  163.     if ( err == noErr ) {
  164.         pb.hFileInfo.ioNamePtr = name;
  165.         pb.hFileInfo.ioVRefNum = fpb.ioFCBVRefNum;
  166.         pb.hFileInfo.ioDirID = fpb.ioFCBParID;
  167.         pb.hFileInfo.ioFDirIndex = -1;
  168.         err = PBGetCatInfoSync( &pb );
  169.     }
  170.     
  171.     if ( err == noErr ) {
  172.         number[0] = 2;
  173.         number[1] = name[9];
  174.         number[2] = name[10];
  175.         PLstrcpy( name, "\p:::Test Data Folder:Problem " );
  176.         PLstrcat( name, number );
  177.         PLstrcat( name, "\p Test Data:XXX" );
  178.         err = FSMakeFSSpec( fpb.ioFCBVRefNum, fpb.ioFCBParID, name, spec );
  179.         if ( err == fnfErr ) {
  180.             err = noErr;
  181.         }
  182.         spec->name[0] = 0;
  183.     }
  184.     return err;
  185. }
  186.  
  187. pascal OSErr ProblemGetTestSpecs( const FSSpec *testspec, long test, 
  188.     FSSpec *inputspec, FSSpec *correctspec, FSSpec *savedspec, FSSpec *outputspec )
  189. {
  190.     OSErr err;
  191.     Str15 number;
  192.     FSSpec irrelevent;
  193.     
  194.     number[0] = 2;
  195.     number[1] = '0' + test / 10;
  196.     number[2] = '0' + test % 10;
  197.     
  198.     *inputspec = *testspec;
  199.     PLstrcpy( inputspec->name, "\pTest" );
  200.     PLstrcat( inputspec->name, number );
  201.     *correctspec = *inputspec;
  202.     *savedspec = *inputspec;
  203.     *outputspec = *inputspec;
  204.  
  205.     PLstrcat( inputspec->name, "\p.input" );
  206.     PLstrcat( correctspec->name, "\p.correct" );
  207.     PLstrcat(savedspec->name, "\p.saved" );
  208.     PLstrcat( outputspec->name, "\p.output" );
  209.     
  210.     (void) FSpDelete( outputspec );
  211.     (void) FSpDelete( savedspec );
  212.     err = FSMakeFSSpec( inputspec->vRefNum, inputspec->parID, inputspec->name, &irrelevent );
  213.     if ( err == noErr ) {
  214.         err = ProblemDuplicateFile( inputspec, savedspec );
  215.     }
  216.     return err;
  217. }
  218.  
  219. pascal void ProblemLogError( OSErr err, const char *function )
  220. {
  221.     if ( err != noErr ) {
  222.         printf( "%s got error %d\n", function, err );
  223.     }
  224. }
  225.  
  226. pascal void ProblemRunEitherFileTests( RunFileTestProc runtest, RunSingleFileTestProc singleruntest )
  227. {
  228.     OSErr err;
  229.     FSSpec testspec, inputspec, correctspec, savedspec, outputspec;
  230.     long test;
  231.     Boolean correct;
  232.     
  233.     err = ProblemGetTestDirectoryFSSpec( &testspec );
  234.     ProblemLogError( err, "GetTestDirectoryFSSpec" );
  235.     
  236.     if ( err == noErr ) {
  237.         test = 1;
  238.         while ( 1 ) {
  239.             err = ProblemGetTestSpecs( &testspec, test, &inputspec, &correctspec, &savedspec, &outputspec );
  240.             if ( err != noErr ) {
  241.                 if ( err != fnfErr ) {
  242.                     ProblemLogError( err, "GetTestSpecs" );
  243.                 }
  244.                 break;
  245.             }
  246.             
  247.             printf( "Test %d\n", test );
  248.             // Test
  249.  
  250.             if ( runtest != NULL ) {
  251.                 err = runtest( &savedspec, &outputspec );
  252.                 if ( err == noErr ) {
  253.                     correct = !ProblemDiffFiles( &correctspec, &outputspec );
  254.                 }
  255.             } else {
  256.                 err = singleruntest( &savedspec, &outputspec, &correct );
  257.             }
  258.             if ( err != noErr ) {
  259.                 printf( "FAILED: Result returned %d!\n", err );
  260.             } else if ( ProblemDiffFiles( &inputspec, &savedspec ) ) {
  261.                 printf( "FAILED: Modified Input Files!\n" );
  262.             } else if ( !correct ) {
  263.                 printf( "FAILED: Incorrect result!\n" );
  264.             } else {
  265.                 printf( "SUCCESS!\n" );
  266.             }
  267.             if ( ProblemDiffFiles( &inputspec, &savedspec ) ) {
  268.                 err = ProblemDuplicateFile( &savedspec, &inputspec );
  269.             }
  270.             (void) FSpDelete( &savedspec );
  271.             
  272.             test++;
  273.         }
  274.     }
  275. }
  276.  
  277. pascal void ProblemRunFileTests( RunFileTestProc runtest )
  278. {
  279.     ProblemRunEitherFileTests( runtest, NULL );
  280. }
  281.  
  282. pascal void ProblemRunSingleFileTests( RunSingleFileTestProc runtest )
  283. {
  284.     ProblemRunEitherFileTests( NULL, runtest );
  285. }
  286.  
  287. pascal OSErr ProblemFileRead( const FSSpec* infile, Handle *data )
  288. {
  289.     OSErr err;
  290.     short rn;
  291.     long filelen;
  292.     
  293.     *data = nil;
  294.     err = FSpOpenDF( infile, fsRdPerm, &rn );
  295.     if ( err == noErr ) {
  296.         err = GetEOF( rn,  &filelen );
  297.         if ( err == noErr ) {
  298.             *data = NewHandle( filelen );
  299.             err = MemError();
  300.             if ( err == noErr ) {
  301.                 HLock( *data );
  302.                 err = ProblemFSMustRead( rn, filelen, **data );
  303.                 HUnlock( *data );
  304.             }
  305.         }
  306.         (void )FSClose( rn );
  307.     }
  308.     if ( err != noErr ) {
  309.         DisposeHandle( *data );
  310.     }
  311.     return err;
  312. }
  313.  
  314. pascal OSErr ProblemFileWrite( const FSSpec* outfile, Handle data )
  315. {
  316.     OSErr err, err2;
  317.     short rn;
  318.     
  319.     (void) FSpDelete( outfile );
  320.     (void) FSpCreate( outfile, 'CWIE', 'TEXT', 0 );
  321.     err = FSpOpenDF( outfile, fsWrPerm, &rn );
  322.     if ( err == noErr ) {
  323.         HLock( data );
  324.         err = ProblemFSWrite( rn, GetHandleSize( data ), *data );
  325.         HUnlock( data );
  326.         err2 = FSClose( rn );
  327.         if ( err == noErr ) {
  328.             err = err2;
  329.         }
  330.     }
  331.     return err;
  332. }
  333.  
  334. pascal Boolean ProblemReadLineFromHandle( Handle data, char *line, long linelen )
  335. {
  336.     long datalen = GetHandleSize( data );
  337.     char *p = *data;
  338.     char *datafin = p + datalen;
  339.     long actlinelen;
  340.     
  341.     if ( datalen == 0 ) return false;
  342.     
  343.     while ( *p != '\r' && p < datafin ) p++;
  344.     actlinelen = p - *data;
  345.     actlinelen = actlinelen < linelen ? actlinelen : linelen - 1;
  346.     BlockMoveData( *data, line, actlinelen );
  347.     line[actlinelen] = 0;
  348.     if ( p < datafin ) p++;
  349.     (void) Munger( data, 0, nil, p - *data, &data, 0); // Delete line from start of handle
  350.     return true;
  351. }
  352.  
  353. pascal OSErr ProblemWriteLineToHandle( Handle data, char *line )
  354. {
  355.     OSErr err;
  356.     
  357.     err = ProblemWriteStringToHandle( data, line );
  358.     if ( err == noErr ) {
  359.         err = ProblemWriteStringToHandle( data, "\r" );
  360.     }
  361.     return err;
  362. }
  363.  
  364. pascal OSErr ProblemWriteStringToHandle( Handle data, char *line )
  365. {
  366.     OSErr err;
  367.     
  368.     err = PtrAndHand( line, data, strlen(line) );
  369.     return err;
  370. }
  371.  
  372. pascal void ProblemP2CString( void *line )
  373. {
  374.     unsigned char *p = (unsigned char *)line;
  375.     long len = *p;
  376.     
  377.     BlockMoveData( p + 1, p, len );
  378.     p[len] = 0;
  379. }
  380.  
  381. pascal void ProblemC2PString( void *line )
  382. {
  383.     char *p = (char *)line;
  384.     long len = strlen(p);
  385.     
  386.     len = len <= 255 ? len : 255;
  387.     
  388.     BlockMoveData( p, p + 1, len );
  389.     p[0] = len;
  390. }
  391.  
  392. pascal Boolean ProblemGetUInt32( char **line, UInt32 *number )
  393. {
  394.     char numbers[20];
  395.     
  396.     ProblemGetCString( line, numbers, 20 );
  397.     return sscanf( numbers, "%ld", number ) == 1;
  398. }
  399.  
  400. pascal Boolean ProblemGetSInt32( char **line, SInt32 *number )
  401. {
  402.     char numbers[20];
  403.     
  404.     ProblemGetCString( line, numbers, 20 );
  405.     return sscanf( numbers, "%ld", number ) == 1;
  406. }
  407.  
  408. pascal void ProblemGetString( char **line, StringPtr field )
  409. {
  410.     char *p;
  411.     
  412.     p = *line;
  413.     while ( *p != 0 && *p != ',' ) p++;
  414.     field[0] = p - *line;
  415.     BlockMoveData( *line, &field[1], field[0] );
  416.     if ( *p ) p++;
  417.     *line = p;
  418. }
  419.  
  420. pascal void ProblemGetCString( char **line, char *field, long fieldlen )
  421. {
  422.     char *p;
  423.     long len;
  424.     
  425.     p = *line;
  426.     while ( *p != 0 && *p != ',' ) p++;
  427.     len = p - *line;
  428.     len = len < fieldlen ? len : fieldlen - 1;
  429.     BlockMoveData( *line, field, len );
  430.     field[len] = 0;
  431.     if ( *p ) p++;
  432.     *line = p;
  433. }
  434.  
  435.