Code:
/*
demo.cpp
*/
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <vector>
#include <string>
#include <iterator>
#include <cstring>
#include <algorithm>
using namespace std;
typedef vector< unsigned char >
buffer_type;
inline void error( string const& message = string( ) )
{
throw runtime_error( message );
}
void read_contents( string const& file, buffer_type& buffer )
{
ifstream
in( file.data( ), ios::binary );
if( !in )
error( string( "cannot open input file '" ) + file + "'" );
buffer.clear( );
for( ;; )
{
int
ch = in.get( );
if( in.bad( ) )
error( "file system read failure" );
if( in.eof( ) )
break;
buffer.push_back( ch );
}
}
int main( int argc, char** argv )
{
char const*
program = argv[ 0 ];
cerr << "File Patch Utility / File to Array Declaration Translator" << endl;
try
{
/*
Find and patch a pattern in a file
*/
if( argc == 4 )
{
char const
* pattern_file = argv[ 1 ],
* patch_file = argv[ 2 ],
* target_file = argv[ 3 ];
buffer_type
pattern_buffer,
patch_buffer,
target_buffer;
read_contents( pattern_file, pattern_buffer );
read_contents( patch_file, patch_buffer );
read_contents( target_file, target_buffer );
/*
For some reason, the ios::in flag is needed to prevent file truncation
*/
ofstream
out( target_file, ios::binary | ios::in );
if( !out )
error( string( "cannot open target file '" ) + target_file + "'" );
buffer_type::iterator
found = search
(
target_buffer.begin( ),
target_buffer.end( ),
pattern_buffer.begin( ),
pattern_buffer.end( )
);
if( found == target_buffer.end( ) )
error
(
string( "pattern in '" ) + pattern_file +
"' not found in target '" + target_file + "'"
);
size_t
position = distance( target_buffer.begin( ), found );
out.seekp( position, ios::beg );
copy
(
patch_buffer.begin( ),
patch_buffer.end( ),
ostream_iterator< buffer_type::value_type >( out )
);
if( out.bad( ) )
error( "file system write failure" );
}
/*
Translate a file to array declaration source-code
*/
else if( argc == 3 )
{
char const
* source_file = argv[ 1 ],
* target_file = argv[ 2 ];
buffer_type
source_buffer;
read_contents( source_file, source_buffer );
ofstream
out( target_file, ios::trunc );
if( !out )
error( string( "cannot open output file '" ) + target_file + "'" );
out << "{";
for( size_t index = 0, size = source_buffer.size( ), width = 15; index < size; ++index )
{
if( index != 0 )
out << ", ";
if( index % width == 0 )
out << endl << "\t";
out << ( void* )source_buffer[ index ];
}
out << endl << "};" << endl;
if( out.bad( ) )
error( "file system write failure" );
}
else
error( );
}
catch( exception const& error )
{
if( strlen( error.what( ) ) != 0 )
cerr << "Error: " << error.what( ) << endl;
cerr << "Usage: " << program << " <pattern_file> <patch_file> <target_file>" << endl;
cerr << " ...OR..." << endl;
cerr << "Usage: " << program << " <source_file> <target_file>" << endl;
return 1;
}
return 0;
}
So let's say we have the file 'pattern.txt' that contains the search pattern:
Code:
/*
test.cpp
*/
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#define LARGEST_BUFFER_SIZE_NEEDED 8192
char buffer[ LARGEST_BUFFER_SIZE_NEEDED ] =
{
0x2d, 0x3e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x61, 0x72,
0x63, 0x68, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x2e, 0x20, 0x49, 0x64, 0x65, 0x61, 0x6c,
0x6c, 0x79, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65,
0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x76, 0x65, 0x73, 0x2e, 0x20, 0x3c, 0x2d
};
int main( void )
{
std::copy( buffer, buffer + strlen( buffer ), std::ostream_iterator< char >( std::cout ) );
return 0;
}
Now let's say we have the file 'patch.txt' that contains the text: