ENH: Improved implementation of FilesDiffer to avoid allocating enough memory for the entire file twice. Instead using a block-at-a-time comparison.

This commit is contained in:
Brad King 2006-04-13 22:56:32 -04:00
parent 58d0c5e176
commit b8a589bb1d

View File

@ -1419,7 +1419,8 @@ bool SystemTools::CopyFileIfDifferent(const char* source,
return true; return true;
} }
#define KWSYS_ST_BUFFER 4096
bool SystemTools::FilesDiffer(const char* source, bool SystemTools::FilesDiffer(const char* source,
const char* destination) const char* destination)
{ {
@ -1459,28 +1460,36 @@ bool SystemTools::FilesDiffer(const char* source,
return true; return true;
} }
char* source_buf = new char[statSource.st_size]; // Compare the files a block at a time.
char* dest_buf = new char[statSource.st_size]; char source_buf[KWSYS_ST_BUFFER];
char dest_buf[KWSYS_ST_BUFFER];
finSource.read(source_buf, statSource.st_size); long nleft = statSource.st_size;
finDestination.read(dest_buf, statSource.st_size); while(nleft > 0)
if(statSource.st_size != static_cast<long>(finSource.gcount()) ||
statSource.st_size != static_cast<long>(finDestination.gcount()))
{ {
// Failed to read files. // Read a block from each file.
delete [] source_buf; long nnext = (nleft > KWSYS_ST_BUFFER)? KWSYS_ST_BUFFER : nleft;
delete [] dest_buf; finSource.read(source_buf, nnext);
return true; finDestination.read(dest_buf, nnext);
// If either failed to read assume they are different.
if(static_cast<long>(finSource.gcount()) != nnext ||
static_cast<long>(finDestination.gcount()) != nnext)
{
return true;
}
// If this block differs the file differs.
if(memcmp((const void*)source_buf, (const void*)dest_buf, nnext) != 0)
{
return true;
}
// Update the byte count remaining.
nleft -= nnext;
} }
int ret = memcmp((const void*)source_buf,
(const void*)dest_buf,
statSource.st_size);
delete [] dest_buf; // No differences found.
delete [] source_buf; return false;
return ret != 0;
} }