llvm.org GIT mirror llvm / a7750c1
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49024 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 11 years ago
1 changed file(s) with 56 addition(s) and 73 deletion(s). Raw diff Collapse all Expand all
1313
1414 #include "llvm/Support/FileUtilities.h"
1515 #include "llvm/System/Path.h"
16 #include "llvm/System/MappedFile.h"
16 #include "llvm/Support/MemoryBuffer.h"
17 #include "llvm/ADT/OwningPtr.h"
18 #include "llvm/ADT/SmallString.h"
1719 #include "llvm/ADT/StringExtras.h"
1820 #include
1921 #include
4345 }
4446 }
4547
46 static char *BackupNumber(char *Pos, char *FirstChar) {
48 static const char *BackupNumber(const char *Pos, const char *FirstChar) {
4749 // If we didn't stop in the middle of a number, don't backup.
4850 if (!isNumberChar(*Pos)) return Pos;
4951
5658 return Pos;
5759 }
5860
61 /// EndOfNumber - Return the first character that is not part of the specified
62 /// number. This assumes that the buffer is null terminated, so it won't fall
63 /// off the end.
64 static const char *EndOfNumber(const char *Pos) {
65 while (isNumberChar(*Pos))
66 ++Pos;
67 return Pos;
68 }
69
5970 /// CompareNumbers - compare two numbers, returning true if they are different.
60 static bool CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End,
71 static bool CompareNumbers(const char *&F1P, const char *&F2P,
72 const char *F1End, const char *F2End,
6173 double AbsTolerance, double RelTolerance,
6274 std::string *ErrorMsg) {
63 char *F1NumEnd, *F2NumEnd;
75 const char *F1NumEnd, *F2NumEnd;
6476 double V1 = 0.0, V2 = 0.0;
6577
6678 // If one of the positions is at a space and the other isn't, chomp up 'til
7082 while (isspace(*F2P) && F2P != F2End)
7183 ++F2P;
7284
73 // If we stop on numbers, compare their difference. Note that some ugliness
74 // is built into this to permit support for numbers that use "D" or "d" as
75 // their exponential marker, e.g. "1.234D45". This occurs in 200.sixtrack in
76 // spec2k.
77 if (isNumberChar(*F1P) && isNumberChar(*F2P)) {
78 bool isDNotation;
79 do {
80 isDNotation = false;
81 V1 = strtod(F1P, &F1NumEnd);
82 V2 = strtod(F2P, &F2NumEnd);
83
84 if (*F1NumEnd == 'D' || *F1NumEnd == 'd') {
85 *F1NumEnd = 'e'; // Strange exponential notation!
86 isDNotation = true;
87 }
88 if (*F2NumEnd == 'D' || *F2NumEnd == 'd') {
89 *F2NumEnd = 'e'; // Strange exponential notation!
90 isDNotation = true;
91 }
92 } while (isDNotation);
93 } else {
94 // Otherwise, the diff failed.
85 // If we stop on numbers, compare their difference.
86 if (!isNumberChar(*F1P) || !isNumberChar(*F2P)) {
87 // The diff failed.
9588 F1NumEnd = F1P;
9689 F2NumEnd = F2P;
90 } else {
91 // Note that some ugliness is built into this to permit support for numbers
92 // that use "D" or "d" as their exponential marker, e.g. "1.234D45". This
93 // occurs in 200.sixtrack in spec2k.
94 V1 = strtod(F1P, const_cast(&F1NumEnd));
95 V2 = strtod(F2P, const_cast(&F2NumEnd));
96
97 if (*F1NumEnd == 'D' || *F1NumEnd == 'd') {
98 // Copy string into tmp buffer to replace the 'D' with an 'e'.
99 SmallString<200> StrTmp(F1P, EndOfNumber(F1NumEnd)+1);
100 StrTmp[F1NumEnd-F1P] = 'e'; // Strange exponential notation!
101
102 V1 = strtod(&StrTmp[0], const_cast(&F1NumEnd));
103 F1NumEnd = F1P + (F1NumEnd-&StrTmp[0]);
104 }
105
106 if (*F2NumEnd == 'D' || *F2NumEnd == 'd') {
107 // Copy string into tmp buffer to replace the 'D' with an 'e'.
108 SmallString<200> StrTmp(F2P, EndOfNumber(F2NumEnd)+1);
109 StrTmp[F2NumEnd-F2P] = 'e'; // Strange exponential notation!
110
111 V2 = strtod(&StrTmp[0], const_cast(&F2NumEnd));
112 F2NumEnd = F2P + (F2NumEnd-&StrTmp[0]);
113 }
97114 }
98115
99116 if (F1NumEnd == F1P || F2NumEnd == F2P) {
134151 return false;
135152 }
136153
137 // PadFileIfNeeded - If the files are not identical, we will have to be doing
138 // numeric comparisons in here. There are bad cases involved where we (i.e.,
139 // strtod) might run off the beginning or end of the file if it starts or ends
140 // with a number. Because of this, if needed, we pad the file so that it starts
141 // and ends with a null character.
142 static void PadFileIfNeeded(char *&FileStart, char *&FileEnd, char *&FP) {
143 if (FileStart-FileEnd < 2 ||
144 isNumberChar(FileStart[0]) || isNumberChar(FileEnd[-1])) {
145 unsigned FileLen = FileEnd-FileStart;
146 char *NewFile = new char[FileLen+2];
147 NewFile[0] = 0; // Add null padding
148 NewFile[FileLen+1] = 0; // Add null padding
149 memcpy(NewFile+1, FileStart, FileLen);
150 FP = NewFile+(FP-FileStart)+1;
151 FileStart = NewFile+1;
152 FileEnd = FileStart+FileLen;
153 }
154 }
155
156154 /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the
157155 /// files match, 1 if they are different, and 2 if there is a file error. This
158156 /// function differs from DiffFiles in that you can specify an absolete and
190188
191189 // Now its safe to mmap the files into memory becasue both files
192190 // have a non-zero size.
193 sys::MappedFile F1;
194 if (F1.open(FileA, Error))
191 OwningPtr F1(MemoryBuffer::getFile(FileA.c_str(), FileA.size(),
192 Error));
193 OwningPtr F2(MemoryBuffer::getFile(FileB.c_str(), FileB.size(),
194 Error));
195 if (F1 == 0 || F2 == 0)
195196 return 2;
196 sys::MappedFile F2;
197 if (F2.open(FileB, Error))
198 return 2;
199 if (!F1.map(Error))
200 return 2;
201 if (!F2.map(Error))
202 return 2;
203
197
204198 // Okay, now that we opened the files, scan them for the first difference.
205 char *File1Start = F1.charBase();
206 char *File2Start = F2.charBase();
207 char *File1End = File1Start+A_size;
208 char *File2End = File2Start+B_size;
209 char *F1P = File1Start;
210 char *F2P = File2Start;
199 const char *File1Start = F1->getBufferStart();
200 const char *File2Start = F2->getBufferStart();
201 const char *File1End = F1->getBufferEnd();
202 const char *File2End = F2->getBufferEnd();
203 const char *F1P = File1Start;
204 const char *F2P = File2Start;
211205
212206 if (A_size == B_size) {
213 // Are the buffers identical?
207 // Are the buffers identical? Common case: Handle this efficiently.
214208 if (std::memcmp(File1Start, File2Start, A_size) == 0)
215209 return 0;
216210
220214 return 1; // Files different!
221215 }
222216 }
223
224 char *OrigFile1Start = File1Start;
225 char *OrigFile2Start = File2Start;
226
227 // If the files need padding, do so now.
228 PadFileIfNeeded(File1Start, File1End, F1P);
229 PadFileIfNeeded(File2Start, File2End, F2P);
230217
231218 bool CompareFailed = false;
232219 while (1) {
271258 CompareFailed = true;
272259 }
273260
274 if (OrigFile1Start != File1Start)
275 delete[] (File1Start-1); // Back up past null byte
276 if (OrigFile2Start != File2Start)
277 delete[] (File2Start-1); // Back up past null byte
278261 return CompareFailed;
279262 }