#include "ffilter.hpp"
int FileFilter::count = 0;
FileFilter::FileFilter( const char *file2read,
const char *file2write,
data_block* (*filter_func)
( data_block *inblock ) )
{
long file_size;
filter = filter_func;
if( !file2read | | !file2write | | !filter )
filter_valid = 0;
else {
rfile = fopen( file2read, "rb" );
wfile = fopen( file2write, "wb" );
if( rfile && wfile && create_sem() && create_queue() ) {
fseek( rfile, 0L, SEEK_END );
file_size = ftell( rfile );
fseek( rfile, 0L, SEEK_SET );
blocks2read = file_size/INBUF_SIZE;
if( file_size % INBUF_SIZE )
++blocks2read;
blocks2write = blocks2read;
filter_valid = 1;
_beginthread( read_thread, 4096, (void *)this );
_beginthread( write_thread, 4096, (void *)this );
}
else
filter_valid = 0;
}
}
FileFilter::~FileFilter()
{
if( rfile )
fclose( rfile );
if( wfile )
fclose( wfile );
rfile = wfile = 0;
filter_valid = 0;
}
void read_thread( void *filterptr )
{
data_block *db, *db2;
FileFilter *ff = (FileFilter *)filterptr;
while( ff->blocks2read---- ) {
db = new data_block;
db->block = new char[ INBUF_SIZE ];
db->data_size = fread( db->block, 1, INBUF_SIZE, ff->rfile );
if( db->data_size ) {
db2 = ff->filter( db );
delete db->block;
delete db;
db = db2;
if( !ff->put_queue( db )) {
printf("\nCould not Put to Data Queue!\n");
exit( 1 );
}
}
}
}
void write_thread( void *filterptr )
{
data_block *db;
FileFilter *ff = (FileFilter *)filterptr;
int n, s;
APIRET rc;
while( ff->blocks2write-- ) {
if( !( db = ff->get_queue()) ) {
printf("\n\tBIG Error! : Queue is EMPTY!\N");
exit( 1 );
}
s = db->data_size;
n = fwrite( db->block, 1, s, ff->wfile );
delete db->block;
delete db;
if( n != s ) {
printf("\n\tWrite Block Write Error : Terminating!\n");
exit( 1 );
}
}
rc = DosPostEventSem( ff->done_sem );
ff->filter_error = (ULONG)rc;
}
int FileFilter::create_queue()
{
APIRET rc;
char n[ 16 ];
strcpy( qname, "\\QUEUES\\Q");
sprintf( n, "%ld", count );
strcat( qname, n );
rc = DosCreateQueue( &qhandle, QUE_FIFO |
QUE_CONVERT_ADDRESS, qname );
if( !rc ) ++count;
return !rc;
}
int FileFilter::put_queue( data_block *data )
{
ULONG Request = 0;
ULONG DataLength;
PVOID DataBuffer;
ULONG ElemPriority = 0;
APIRET rc; // OS/2 QUEUE API stuff
data_block *d; // data structure from ffilter.hpp
if( !data )
return 0;
DataLength = data->data_size;
DataBuffer = data->block;
rc = DosWriteQueue(qhandle, Request, DataLength,
DataBuffer, ElemPriority);
delete data;
return ( rc ) ? 0 : 1;
}
data_block* FileFilter::get_queue()
{
REQUESTDATA Request; // OS/2 QUEUE API stuff
ULONG DataLength;
PVOID DataAddress;
ULONG ElementCode = 0;
BOOL32 NoWait = 0;
BYTE ElemPriority = 0;
HEV SemHandle = 0;
APIRET rc;
data_block *data = 0; // data structure from ffilter.hpp
rc = DosReadQueue(qhandle, &Request, &DataLength, &DataAddress,
ElementCode, NoWait, &ElemPriority, SemHandle);
if( rc )
return 0;
data = new data_block;
if( data ) {
data->data_size = DataLength;
data->block = (char *)DataAddress;
}
return data;
}
int FileFilter::create_sem()
{
ULONG attr = 0;
BOOL32 state = 0;
APIRET rc;
max_sem_wait = 60000UL;
rc = DosCreateEventSem( 0, &done_sem, attr, state );
return ( rc ) ? 0 : 1;
}
APIRET FileFilter::wait4completion( ULONG max_wait )
{
return DosWaitEventSem( done_sem, max_wait );
}
// End of File