[llvm-commits] [llvm] r49024 - /llvm/trunk/lib/Support/FileUtilities.cpp

Chris Lattner sabre at nondot.org
Mon Mar 31 20:39:50 PDT 2008


Author: lattner
Date: Mon Mar 31 22:39:49 2008
New Revision: 49024

URL: http://llvm.org/viewvc/llvm-project?rev=49024&view=rev
Log:
Change DiffFilesWithTolerance to be written in terms of MemoryBuffer,
not an mmapped file.  This more closely matches its requirements and
provides an implicitly null terminated buffer, something this
routine had to emulate itself before.

Modified:
    llvm/trunk/lib/Support/FileUtilities.cpp

Modified: llvm/trunk/lib/Support/FileUtilities.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/FileUtilities.cpp?rev=49024&r1=49023&r2=49024&view=diff

==============================================================================
--- llvm/trunk/lib/Support/FileUtilities.cpp (original)
+++ llvm/trunk/lib/Support/FileUtilities.cpp Mon Mar 31 22:39:49 2008
@@ -14,7 +14,9 @@
 
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/System/Path.h"
-#include "llvm/System/MappedFile.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include <cstdlib>
 #include <cstring>
@@ -44,7 +46,7 @@
   }
 }
 
-static char *BackupNumber(char *Pos, char *FirstChar) {
+static const char *BackupNumber(const char *Pos, const char *FirstChar) {
   // If we didn't stop in the middle of a number, don't backup.
   if (!isNumberChar(*Pos)) return Pos;
 
@@ -57,11 +59,21 @@
   return Pos;
 }
 
+/// EndOfNumber - Return the first character that is not part of the specified
+/// number.  This assumes that the buffer is null terminated, so it won't fall
+/// off the end.
+static const char *EndOfNumber(const char *Pos) {
+  while (isNumberChar(*Pos))
+    ++Pos;
+  return Pos;
+}
+
 /// CompareNumbers - compare two numbers, returning true if they are different.
-static bool CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End,
+static bool CompareNumbers(const char *&F1P, const char *&F2P,
+                           const char *F1End, const char *F2End,
                            double AbsTolerance, double RelTolerance,
                            std::string *ErrorMsg) {
-  char *F1NumEnd, *F2NumEnd;
+  const char *F1NumEnd, *F2NumEnd;
   double V1 = 0.0, V2 = 0.0;
 
   // If one of the positions is at a space and the other isn't, chomp up 'til
@@ -71,30 +83,35 @@
   while (isspace(*F2P) && F2P != F2End)
     ++F2P;
 
-  // If we stop on numbers, compare their difference.  Note that some ugliness
-  // is built into this to permit support for numbers that use "D" or "d" as
-  // their exponential marker, e.g. "1.234D45".  This occurs in 200.sixtrack in
-  // spec2k.
-  if (isNumberChar(*F1P) && isNumberChar(*F2P)) {
-    bool isDNotation;
-    do {
-      isDNotation = false;
-      V1 = strtod(F1P, &F1NumEnd);
-      V2 = strtod(F2P, &F2NumEnd);
-
-      if (*F1NumEnd == 'D' || *F1NumEnd == 'd') {
-        *F1NumEnd = 'e';  // Strange exponential notation!
-        isDNotation = true;
-      }
-      if (*F2NumEnd == 'D' || *F2NumEnd == 'd') {
-        *F2NumEnd = 'e';  // Strange exponential notation!
-        isDNotation = true;
-      }
-    } while (isDNotation);
-  } else {
-    // Otherwise, the diff failed.
+  // If we stop on numbers, compare their difference.
+  if (!isNumberChar(*F1P) || !isNumberChar(*F2P)) {
+    // The diff failed.
     F1NumEnd = F1P;
     F2NumEnd = F2P;
+  } else {
+    // Note that some ugliness is built into this to permit support for numbers
+    // that use "D" or "d" as their exponential marker, e.g. "1.234D45".  This
+    // occurs in 200.sixtrack in spec2k.
+    V1 = strtod(F1P, const_cast<char**>(&F1NumEnd));
+    V2 = strtod(F2P, const_cast<char**>(&F2NumEnd));
+
+    if (*F1NumEnd == 'D' || *F1NumEnd == 'd') {
+      // Copy string into tmp buffer to replace the 'D' with an 'e'.
+      SmallString<200> StrTmp(F1P, EndOfNumber(F1NumEnd)+1);
+      StrTmp[F1NumEnd-F1P] = 'e';  // Strange exponential notation!
+      
+      V1 = strtod(&StrTmp[0], const_cast<char**>(&F1NumEnd));
+      F1NumEnd = F1P + (F1NumEnd-&StrTmp[0]);
+    }
+    
+    if (*F2NumEnd == 'D' || *F2NumEnd == 'd') {
+      // Copy string into tmp buffer to replace the 'D' with an 'e'.
+      SmallString<200> StrTmp(F2P, EndOfNumber(F2NumEnd)+1);
+      StrTmp[F2NumEnd-F2P] = 'e';  // Strange exponential notation!
+      
+      V2 = strtod(&StrTmp[0], const_cast<char**>(&F2NumEnd));
+      F2NumEnd = F2P + (F2NumEnd-&StrTmp[0]);
+    }
   }
 
   if (F1NumEnd == F1P || F2NumEnd == F2P) {
@@ -135,25 +152,6 @@
   return false;
 }
 
-// PadFileIfNeeded - If the files are not identical, we will have to be doing
-// numeric comparisons in here.  There are bad cases involved where we (i.e.,
-// strtod) might run off the beginning or end of the file if it starts or ends
-// with a number.  Because of this, if needed, we pad the file so that it starts
-// and ends with a null character.
-static void PadFileIfNeeded(char *&FileStart, char *&FileEnd, char *&FP) {
-  if (FileStart-FileEnd < 2 ||
-      isNumberChar(FileStart[0]) || isNumberChar(FileEnd[-1])) {
-    unsigned FileLen = FileEnd-FileStart;
-    char *NewFile = new char[FileLen+2];
-    NewFile[0] = 0;              // Add null padding
-    NewFile[FileLen+1] = 0;      // Add null padding
-    memcpy(NewFile+1, FileStart, FileLen);
-    FP = NewFile+(FP-FileStart)+1;
-    FileStart = NewFile+1;
-    FileEnd = FileStart+FileLen;
-  }
-}
-
 /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the
 /// files match, 1 if they are different, and 2 if there is a file error.  This
 /// function differs from DiffFiles in that you can specify an absolete and
@@ -191,27 +189,23 @@
 
   // Now its safe to mmap the files into memory becasue both files
   // have a non-zero size.
-  sys::MappedFile F1;
-  if (F1.open(FileA, Error))
-    return 2;
-  sys::MappedFile F2;
-  if (F2.open(FileB, Error))
-    return 2;
-  if (!F1.map(Error))
+  OwningPtr<MemoryBuffer> F1(MemoryBuffer::getFile(FileA.c_str(), FileA.size(),
+                                                   Error));
+  OwningPtr<MemoryBuffer> F2(MemoryBuffer::getFile(FileB.c_str(), FileB.size(),
+                                                   Error));
+  if (F1 == 0 || F2 == 0)
     return 2;
-  if (!F2.map(Error))
-    return 2;
-
+  
   // Okay, now that we opened the files, scan them for the first difference.
-  char *File1Start = F1.charBase();
-  char *File2Start = F2.charBase();
-  char *File1End = File1Start+A_size;
-  char *File2End = File2Start+B_size;
-  char *F1P = File1Start;
-  char *F2P = File2Start;
+  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?
+    // Are the buffers identical?  Common case: Handle this efficiently.
     if (std::memcmp(File1Start, File2Start, A_size) == 0)
       return 0;
 
@@ -222,13 +216,6 @@
     }
   }
 
-  char *OrigFile1Start = File1Start;
-  char *OrigFile2Start = File2Start;
-
-  // If the files need padding, do so now.
-  PadFileIfNeeded(File1Start, File1End, F1P);
-  PadFileIfNeeded(File2Start, File2End, F2P);
-
   bool CompareFailed = false;
   while (1) {
     // Scan for the end of file or next difference.
@@ -272,9 +259,5 @@
       CompareFailed = true;
   }
 
-  if (OrigFile1Start != File1Start)
-    delete[] (File1Start-1);   // Back up past null byte
-  if (OrigFile2Start != File2Start)
-    delete[] (File2Start-1);   // Back up past null byte
   return CompareFailed;
 }





More information about the llvm-commits mailing list