// SearchReplace.cpp : Defines the entry point for the console application. // #include #include class ReplacementTableEntry; std::vector 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::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::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 ); } }