336 lines
8.0 KiB
C++
336 lines
8.0 KiB
C++
// SearchReplace.cpp : Defines the entry point for the console application.
|
|
//
|
|
|
|
#include <assert.h>
|
|
#include <vector>
|
|
|
|
class ReplacementTableEntry;
|
|
|
|
std::vector<ReplacementTableEntry*> gReplacementTable;
|
|
|
|
bool BuildReplacementTable( FILE* rulesFile );
|
|
void RemoveNewLine( char* string );
|
|
bool IsWhiteSpace( char* string );
|
|
void ProcessSourceFile( FILE* sourceFile, FILE* targetFile );
|
|
|
|
|
|
|
|
class ReplacementTableEntry
|
|
{
|
|
public:
|
|
|
|
ReplacementTableEntry( const char* findString, const char* replaceString );
|
|
~ReplacementTableEntry();
|
|
|
|
char* mFindString;
|
|
char* mReplaceString;
|
|
};
|
|
|
|
|
|
ReplacementTableEntry::ReplacementTableEntry
|
|
(
|
|
const char* findString,
|
|
const char* replaceString
|
|
)
|
|
:
|
|
mFindString( 0 ),
|
|
mReplaceString( 0 )
|
|
{
|
|
assert( findString );
|
|
assert( replaceString );
|
|
|
|
mFindString = new char[strlen(findString)+1];
|
|
strcpy( mFindString, findString );
|
|
|
|
mReplaceString = new char[strlen(replaceString)+1];
|
|
strcpy( mReplaceString, replaceString );
|
|
}
|
|
|
|
ReplacementTableEntry::~ReplacementTableEntry()
|
|
{
|
|
delete [] mFindString;
|
|
delete [] mReplaceString;
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
// int main
|
|
//==============================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
//==============================================================================
|
|
int main(int argc, char* argv[])
|
|
{
|
|
// Validate command line arguments
|
|
assert( argc == 4 );
|
|
|
|
const char* rulesName = argv[1];
|
|
const char* sourceName = argv[2];
|
|
const char* targetName = argv[3];
|
|
|
|
// Open rules file
|
|
FILE* rulesFile = fopen( rulesName, "rt" );
|
|
|
|
if( rulesFile == NULL )
|
|
{
|
|
printf( "Failed to open rules file: %s\n", rulesName );
|
|
return( 0 );
|
|
}
|
|
|
|
// Build search and replace table
|
|
bool result = BuildReplacementTable( rulesFile );
|
|
|
|
// Close rules file
|
|
fclose( rulesFile );
|
|
|
|
|
|
// Open source file
|
|
FILE* sourceFile = fopen( sourceName, "rt" );
|
|
|
|
if( sourceFile == NULL )
|
|
{
|
|
fclose( rulesFile );
|
|
printf( "Failed to open source file: %s\n", sourceName );
|
|
return( 0 );
|
|
}
|
|
|
|
// Open target file
|
|
FILE* targetFile = fopen( targetName, "wt" );
|
|
|
|
if( targetFile == NULL )
|
|
{
|
|
fclose( rulesFile );
|
|
fclose( sourceFile );
|
|
printf( "Failed to open target file: %s\n", targetName );
|
|
return( 0 );
|
|
}
|
|
|
|
// Process source file
|
|
|
|
ProcessSourceFile( sourceFile, targetFile );
|
|
|
|
fclose( sourceFile );
|
|
fclose( targetFile );
|
|
|
|
|
|
// Clean up
|
|
std::vector<ReplacementTableEntry*>::const_iterator iter = gReplacementTable.begin();
|
|
|
|
for( ; iter != gReplacementTable.end(); ++iter )
|
|
{
|
|
ReplacementTableEntry* entry = (*iter);
|
|
|
|
delete entry;
|
|
}
|
|
|
|
gReplacementTable.clear();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
// bool BuildReplacementTable
|
|
//==============================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
//==============================================================================
|
|
bool BuildReplacementTable( FILE* rulesFile )
|
|
{
|
|
// Get the next line from the file
|
|
|
|
int lineCount = 0;
|
|
|
|
while( 1 )
|
|
{
|
|
const int BUFFER_SIZE = 512;
|
|
char* fgetsResult;
|
|
char lineBuffer[BUFFER_SIZE];
|
|
|
|
do
|
|
{ if( feof( rulesFile ) )
|
|
{
|
|
return( true );
|
|
}
|
|
|
|
fgetsResult = fgets( lineBuffer, BUFFER_SIZE, rulesFile );
|
|
++lineCount;
|
|
}
|
|
while( IsWhiteSpace( lineBuffer ) == true );
|
|
|
|
char findString[BUFFER_SIZE];
|
|
strcpy( findString, lineBuffer );
|
|
RemoveNewLine( findString );
|
|
|
|
|
|
do
|
|
{
|
|
if( feof( rulesFile ) )
|
|
{
|
|
printf( "Error in rules file, missing replace string (line: %d)\n", lineCount );
|
|
return( false );
|
|
}
|
|
|
|
fgetsResult = fgets( lineBuffer, BUFFER_SIZE, rulesFile );
|
|
++lineCount;
|
|
}
|
|
while( IsWhiteSpace( lineBuffer ) == true );
|
|
|
|
char replaceString[BUFFER_SIZE];
|
|
strcpy( replaceString, lineBuffer );
|
|
RemoveNewLine( replaceString );
|
|
|
|
// Create Entry
|
|
//
|
|
ReplacementTableEntry* entry = new ReplacementTableEntry( findString, replaceString );
|
|
gReplacementTable.push_back( entry );
|
|
}
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
// void RemoveNewLine
|
|
//==============================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
//==============================================================================
|
|
void RemoveNewLine( char* string )
|
|
{
|
|
assert( string );
|
|
|
|
int length = strlen( string );
|
|
|
|
int i;
|
|
for( i = 0; i < length; ++i )
|
|
{
|
|
if( '\n' == string[i] )
|
|
{
|
|
string[i] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
// bool IsWhiteSpace
|
|
//==============================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
//==============================================================================
|
|
bool IsWhiteSpace( char* string )
|
|
{
|
|
assert( string );
|
|
|
|
int length = strlen( string );
|
|
|
|
int i;
|
|
for( i = 0; i < length; ++i )
|
|
{
|
|
if( (string[i] != '\n') && (string[i] != ' ') )
|
|
{
|
|
return( false );
|
|
}
|
|
}
|
|
|
|
return( true );
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
// void ProcessSourceFile
|
|
//==============================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return:
|
|
//
|
|
//==============================================================================
|
|
void ProcessSourceFile( FILE* sourceFile, FILE* targetFile )
|
|
{
|
|
int lineNumber = 0;
|
|
while( !feof( sourceFile ) )
|
|
{
|
|
// Read in a line from the source
|
|
const int BUFFER_SIZE = 1024;
|
|
char* fgetsResult;
|
|
char sourceBuffer[BUFFER_SIZE];
|
|
char targetBuffer[BUFFER_SIZE];
|
|
|
|
fgetsResult = fgets( sourceBuffer, BUFFER_SIZE, sourceFile );
|
|
strcpy( targetBuffer, sourceBuffer );
|
|
++lineNumber;
|
|
|
|
// Iterate through the find strings for a match
|
|
std::vector<ReplacementTableEntry*>::const_iterator iter = gReplacementTable.begin();
|
|
|
|
for( ; iter != gReplacementTable.end(); ++iter )
|
|
{
|
|
ReplacementTableEntry* entry = (*iter);
|
|
|
|
char* start = sourceBuffer;
|
|
char* targetPos = targetBuffer;
|
|
char* found = NULL;
|
|
|
|
do
|
|
{
|
|
found = strstr( start, entry->mFindString );
|
|
|
|
// Replace if found
|
|
if( found != NULL )
|
|
{
|
|
// Copy over the prefix
|
|
memcpy(targetPos, start, found - start );
|
|
targetPos += found - start;
|
|
|
|
// Copy over the replacement string
|
|
memcpy(targetPos, entry->mReplaceString, strlen( entry->mReplaceString ) );
|
|
targetPos += strlen( entry->mReplaceString );
|
|
start = found + strlen( entry->mFindString );
|
|
|
|
// Copy over the postfix
|
|
memcpy( targetPos, start, strlen(start) );
|
|
|
|
// NULL terminate
|
|
char* term = targetPos + strlen(start);
|
|
*term = '\0';
|
|
}
|
|
}
|
|
while( found != NULL );
|
|
|
|
// The target now becomes the source to preserve any replacements.
|
|
strcpy( sourceBuffer, targetBuffer );
|
|
}
|
|
|
|
// Write out line to target
|
|
fputs( targetBuffer, targetFile );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |