diff options
author | Chris Lattner <sabre@nondot.org> | 2007-12-17 21:38:04 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-12-17 21:38:04 +0000 |
commit | 5fb125c2556cb9d914493b1ef1bd5eee2d2843af (patch) | |
tree | baf74a344af93b9f3995598e45b3745478d7d594 /Lex/HeaderMap.cpp | |
parent | 1adbf6349d4701771a814542008386ad39e3d614 (diff) |
implement HeaderMap::LookupFile. I think headermaps are done now. All that is
left is this crazy thing called "testing".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45124 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Lex/HeaderMap.cpp')
-rw-r--r-- | Lex/HeaderMap.cpp | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/Lex/HeaderMap.cpp b/Lex/HeaderMap.cpp index 177821e0cf..64a2c8e71b 100644 --- a/Lex/HeaderMap.cpp +++ b/Lex/HeaderMap.cpp @@ -14,6 +14,7 @@ #include "clang/Lex/HeaderMap.h" #include "clang/Basic/FileManager.h" #include "llvm/ADT/scoped_ptr.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -51,6 +52,19 @@ struct HMapHeader { }; } // end namespace clang. +/// HashHMapKey - This is the 'well known' hash function required by the file +/// format, used to look up keys in the hash table. The hash table uses simple +/// linear probing based on this function. +static inline unsigned HashHMapKey(const char *S, const char *End) { + unsigned Result = 0; + + for (; S != End; S++) + Result += tolower(*S) * 13; + return Result; +} + + + //===----------------------------------------------------------------------===// // Verification and Construction //===----------------------------------------------------------------------===// @@ -155,6 +169,17 @@ const char *HeaderMap::getString(unsigned StrTabIdx) const { return FileBuffer->getBufferStart()+StrTabIdx; } +/// StringsEqualWithoutCase - Compare the specified two strings for case- +/// insensitive equality, returning true if they are equal. Both strings are +/// known to have the same length. +static bool StringsEqualWithoutCase(const char *S1, const char *S2, + unsigned Len) { + for (; Len; ++S1, ++S2, --Len) + if (tolower(*S1) != tolower(*S2)) + return false; + return true; +} + //===----------------------------------------------------------------------===// // The Main Drivers //===----------------------------------------------------------------------===// @@ -184,6 +209,34 @@ void HeaderMap::dump() const { const FileEntry *HeaderMap::LookupFile(const char *FilenameStart, const char *FilenameEnd, FileManager &FM) const { - // FIXME: this needs work. - return 0; + const HMapHeader &Hdr = getHeader(); + unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets); + + // If the number of buckets is not a power of two, the headermap is corrupt. + // Don't probe infinitely. + if (NumBuckets & (NumBuckets-1)) + return 0; + + // Linearly probe the hash table. + for (unsigned Bucket = HashHMapKey(FilenameStart, FilenameEnd);; ++Bucket) { + HMapBucket B = getBucket(Bucket & (NumBuckets-1)); + if (B.Key == HMAP_EmptyBucketKey) return 0; // Hash miss. + + // See if the key matches. If not, probe on. + const char *Key = getString(B.Key); + unsigned BucketKeyLen = strlen(Key); + if (BucketKeyLen != unsigned(FilenameEnd-FilenameStart)) + continue; + + // See if the actual strings equal. + if (!StringsEqualWithoutCase(FilenameStart, Key, BucketKeyLen)) + continue; + + // If so, we have a match in the hash table. Construct the destination + // path. + llvm::SmallString<1024> DestPath; + DestPath += getString(B.Prefix); + DestPath += getString(B.Suffix); + return FM.getFile(DestPath.begin(), DestPath.end()); + } } |