- try {
- // Map in the files into memory.
- sys::MappedFile F1((sys::Path(FileA)));
- sys::MappedFile F2((sys::Path(FileB)));
- F1.map();
- F2.map();
-
- // Okay, now that we opened the files, scan them for the first difference.
- char *File1Start = F1.charBase();
- char *File2Start = F2.charBase();
- char *File1End = File1Start+F1.size();
- char *File2End = File2Start+F2.size();
- char *F1P = File1Start;
- char *F2P = File2Start;
-
- // Scan for the end of file or first difference.
+ const sys::FileStatus *FileAStat = FileA.getFileStatus(false, Error);
+ if (!FileAStat)
+ return 2;
+ const sys::FileStatus *FileBStat = FileB.getFileStatus(false, Error);
+ if (!FileBStat)
+ return 2;
+
+ // Check for zero length files because some systems croak when you try to
+ // mmap an empty file.
+ size_t A_size = FileAStat->getSize();
+ size_t B_size = FileBStat->getSize();
+
+ // If they are both zero sized then they're the same
+ if (A_size == 0 && B_size == 0)
+ return 0;
+
+ // If only one of them is zero sized then they can't be the same
+ if ((A_size == 0 || B_size == 0)) {
+ if (Error)
+ *Error = "Files differ: one is zero-sized, the other isn't";
+ return 1;
+ }
+
+ // Now its safe to mmap the files into memory becasue both files
+ // have a non-zero size.
+ OwningPtr<MemoryBuffer> F1(MemoryBuffer::getFile(FileA.c_str(), Error));
+ OwningPtr<MemoryBuffer> F2(MemoryBuffer::getFile(FileB.c_str(), Error));
+ if (F1 == 0 || F2 == 0)
+ return 2;
+
+ // Okay, now that we opened the files, scan them for the first difference.
+ const char *File1Start = F1->getBufferStart();
+ const char *File2Start = F2->getBufferStart();
+ const char *File1End = F1->getBufferEnd();
+ const char *File2End = F2->getBufferEnd();
+ const char *F1P = File1Start;
+ const char *F2P = File2Start;
+
+ if (A_size == B_size) {
+ // Are the buffers identical? Common case: Handle this efficiently.
+ if (std::memcmp(File1Start, File2Start, A_size) == 0)
+ return 0;
+
+ if (AbsTol == 0 && RelTol == 0) {
+ if (Error)
+ *Error = "Files differ without tolerance allowance";
+ return 1; // Files different!
+ }
+ }
+
+ bool CompareFailed = false;
+ while (1) {
+ // Scan for the end of file or next difference.