Skip to content

Commit 0c99e2c

Browse files
committed
Rework lookup procedure
1 parent 60250e6 commit 0c99e2c

File tree

2 files changed

+81
-85
lines changed

2 files changed

+81
-85
lines changed

simplecpp.cpp

Lines changed: 41 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2989,86 +2989,64 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const
29892989
return "";
29902990
}
29912991

2992-
simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader)
2992+
std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::tryload(const FileDataCache::name_map_type::iterator &name_it, const simplecpp::DUI &dui, std::vector<std::string> &filenames, simplecpp::OutputList *outputList)
29932993
{
2994-
if (mData.empty())
2995-
return nullptr;
2996-
2997-
if (isAbsolutePath(header)) {
2998-
const std::string path = simplecpp::simplifyPath(header);
2999-
const auto name_it = mNameMap.find(path);
3000-
3001-
if (name_it != mNameMap.end())
3002-
return name_it->second;
3003-
3004-
return nullptr;
3005-
}
3006-
3007-
if (!systemheader) {
3008-
const std::string path = simplecpp::simplifyPath(dirPath(sourcefile) + header);
3009-
const auto name_it = mNameMap.find(path);
3010-
3011-
if (name_it != mNameMap.end())
3012-
return name_it->second;
3013-
3014-
// If the file exists but hasn't been loaded yet then we need to stop searching here or we could get a false match
3015-
std::ifstream f;
3016-
openHeaderDirect(f, path);
3017-
if (f.is_open())
3018-
return nullptr;
3019-
}
3020-
3021-
for (const auto &includePath : dui.includePaths) {
3022-
const std::string path = simplecpp::simplifyPath(includePath + "/" + header);
3023-
const auto name_it = mNameMap.find(path);
3024-
3025-
if (name_it != mNameMap.end())
3026-
return name_it->second;
3027-
}
3028-
3029-
return nullptr;
3030-
}
3031-
3032-
std::pair<bool, simplecpp::FileData *> simplecpp::FileDataCache::load(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector<std::string> &filenames, simplecpp::OutputList *outputList)
3033-
{
3034-
std::ifstream f;
3035-
std::string path = openHeader(f, dui, sourcefile, header, systemheader);
3036-
3037-
if (path.empty())
3038-
return std::make_pair(false, nullptr);
3039-
2994+
const std::string &path = name_it->first;
30402995
FileID fileId;
30412996

30422997
if (!getFileId(path, fileId))
3043-
return std::make_pair(false, nullptr);
2998+
return std::make_pair(nullptr, false);
30442999

30453000
const auto id_it = mIdMap.find(fileId);
30463001
if (id_it != mIdMap.end()) {
3047-
mNameMap.insert(std::make_pair(std::move(path), id_it->second));
3048-
3049-
return std::make_pair(false, id_it->second);
3002+
name_it->second = id_it->second;
3003+
return std::make_pair(id_it->second, false);
30503004
}
30513005

3006+
std::ifstream f(path);
30523007
FileData *const data = new FileData {path, TokenList(f, filenames, path, outputList)};
30533008

30543009
if (dui.removeComments)
30553010
data->tokens.removeComments();
30563011

3057-
mNameMap.insert(std::make_pair(std::move(path), data));
3012+
name_it->second = data;
30583013
mIdMap.insert(std::make_pair(fileId, data));
30593014
mData.push_back(std::unique_ptr<FileData>(data));
30603015

3061-
return std::make_pair(true, data);
3016+
return std::make_pair(data, true);
30623017
}
30633018

3064-
std::pair<bool, simplecpp::FileData *> simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector<std::string> &filenames, simplecpp::OutputList *outputList)
3019+
std::pair<simplecpp::FileData *, bool> simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector<std::string> &filenames, simplecpp::OutputList *outputList)
30653020
{
3066-
FileData *const data = lookup(sourcefile, header, dui, systemheader);
3021+
#define TRYLOAD(path) \
3022+
{ \
3023+
const auto ins = mNameMap.insert(std::make_pair(path, nullptr)); \
3024+
if (ins.second) { \
3025+
const auto load = tryload(ins.first, dui, filenames, outputList); \
3026+
if (load.first != nullptr) \
3027+
return load; \
3028+
} \
3029+
else { \
3030+
return std::make_pair(ins.first->second, false); \
3031+
} \
3032+
}
3033+
3034+
if (isAbsolutePath(header)) {
3035+
TRYLOAD(simplecpp::simplifyPath(header))
3036+
return std::make_pair(nullptr, false);
3037+
}
30673038

3068-
if (data != nullptr)
3069-
return std::make_pair(false, data);
3039+
if (!systemheader) {
3040+
TRYLOAD(simplecpp::simplifyPath(dirPath(sourcefile) + header))
3041+
}
30703042

3071-
return load(sourcefile, header, dui, systemheader, filenames, outputList);
3043+
for (const auto &includePath : dui.includePaths) {
3044+
TRYLOAD(simplecpp::simplifyPath(includePath + "/" + header))
3045+
}
3046+
3047+
#undef TRYLOAD
3048+
3049+
return std::make_pair(nullptr, false);
30723050
}
30733051

30743052
bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id)
@@ -3097,15 +3075,6 @@ bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id)
30973075
#endif
30983076
}
30993077

3100-
bool simplecpp::FileDataCache::FileID::operator< (const FileID &that) const
3101-
{
3102-
#ifdef SIMPLECPP_WINDOWS
3103-
return std::memcmp(&fileIdInfo, &that.fileIdInfo, sizeof(fileIdInfo)) < 0;
3104-
#else
3105-
return dev < that.dev || (dev == that.dev && ino < that.ino);
3106-
#endif
3107-
}
3108-
31093078
simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector<std::string> &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
31103079
{
31113080
#ifdef SIMPLECPP_WINDOWS
@@ -3122,8 +3091,8 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens,
31223091
const std::string &filename = *it;
31233092

31243093
const auto loadResult = cache.get("", filename, dui, false, filenames, outputList);
3125-
const bool loaded = loadResult.first;
3126-
FileData *const filedata = loadResult.second;
3094+
const bool loaded = loadResult.second;
3095+
FileData *const filedata = loadResult.first;
31273096

31283097
if (filedata == nullptr) {
31293098
if (outputList) {
@@ -3170,7 +3139,7 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens,
31703139
const bool systemheader = (htok->str()[0] == '<');
31713140
const std::string header(htok->str().substr(1U, htok->str().size() - 2U));
31723141

3173-
FileData *const filedata = cache.get(sourcefile, header, dui, systemheader, filenames, outputList).second;
3142+
FileData *const filedata = cache.get(sourcefile, header, dui, systemheader, filenames, outputList).first;
31743143
if (!filedata)
31753144
continue;
31763145

@@ -3329,7 +3298,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
33293298

33303299
includetokenstack.push(rawtokens.cfront());
33313300
for (std::list<std::string>::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) {
3332-
const FileData *const filedata = cache.get("", *it, dui, false, files, outputList).second;
3301+
const FileData *const filedata = cache.get("", *it, dui, false, files, outputList).first;
33333302
if (filedata != nullptr && filedata->tokens.cfront() != nullptr)
33343303
includetokenstack.push(filedata->tokens.cfront());
33353304
}
@@ -3463,7 +3432,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
34633432

34643433
const bool systemheader = (inctok->str()[0] == '<');
34653434
const std::string header(inctok->str().substr(1U, inctok->str().size() - 2U));
3466-
const FileData *const filedata = cache.get(rawtok->location.file(), header, dui, systemheader, files, outputList).second;
3435+
const FileData *const filedata = cache.get(rawtok->location.file(), header, dui, systemheader, files, outputList).first;
34673436
if (filedata == nullptr) {
34683437
if (outputList) {
34693438
simplecpp::Output out(files);

simplecpp.h

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <memory>
1919
#include <set>
2020
#include <string>
21+
#include <unordered_map>
2122
#include <vector>
2223

2324
#ifdef _WIN32
@@ -411,14 +412,9 @@ namespace simplecpp {
411412
FileDataCache &operator=(const FileDataCache &) = delete;
412413
FileDataCache &operator=(FileDataCache &&) = default;
413414

414-
/** Fetch the data for a file if it exists in the cache */
415-
FileData *lookup(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader);
416-
417-
/** Load a file into the cache and return the loaded data, or return the cached data if the file id is cached */
418-
std::pair<bool, FileData *> load(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector<std::string> &filenames, OutputList *outputList);
419-
420-
/** Get the cached data for a file, or load and then return it if it isn't cached */
421-
std::pair<bool, FileData *> get(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector<std::string> &filenames, OutputList *outputList);
415+
/** Get the cached data for a file, or load and then return it if it isn't cached.
416+
* returns the file data and true if the file was loaded, false if it was cached. */
417+
std::pair<FileData *, bool> get(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector<std::string> &filenames, OutputList *outputList);
422418

423419
void insert(FileData data) {
424420
FileData *const newdata = new FileData(std::move(data));
@@ -462,26 +458,57 @@ namespace simplecpp {
462458

463459
private:
464460
struct FileID {
465-
bool operator< (const FileID &that) const;
461+
struct Hasher;
462+
friend class FileDataCache;
466463

467464
#ifdef SIMPLECPP_WINDOWS
468465
struct {
469466
std::uint64_t VolumeSerialNumber;
470467
struct {
471-
std::uint8_t Identifier[16];
468+
std::uint64_t IdentifierHi;
469+
std::uint64_t IdentifierLo;
472470
} FileId;
473471
} fileIdInfo;
472+
473+
bool operator==(const FileID &that) const noexcept
474+
{
475+
return fileIdInfo.VolumeSerialNumber == that.fileIdInfo.VolumeSerialNumber &&
476+
fileIdInfo.FileId.IdentifierHi == that.fileIdInfo.FileId.IdentifierHi &&
477+
fileIdInfo.FileId.IdentifierLo == that.fileIdInfo.FileId.IdentifierLo;
478+
}
474479
#else
475480
dev_t dev;
476481
ino_t ino;
482+
483+
bool operator==(const FileID& that) const noexcept
484+
{
485+
return dev == that.dev && ino == that.ino;
486+
}
477487
#endif
478-
};
488+
struct Hasher {
489+
std::size_t operator()(const FileID &id) const
490+
{
491+
#ifdef SIMPLECPP_WINDOWS
492+
return static_cast<std::size_t>(id.fileIdInfo.FileId.IdentifierHi ^ id.fileIdInfo.FileId.IdentifierLo ^
493+
id.fileIdInfo.VolumeSerialNumber);
494+
#else
495+
return static_cast<std::size_t>(id.dev << 32) | static_cast<std::size_t>(id.ino);
496+
#endif
497+
}
498+
};
499+
};
500+
501+
using name_map_type = std::unordered_map<std::string, FileData *>;
502+
using id_map_type = std::unordered_map<FileID, FileData *, FileID::Hasher>;
479503

480504
static bool getFileId(const std::string &path, FileID &id);
481505

506+
std::pair<FileData *, bool> tryload(const name_map_type::iterator &name_it, const DUI &dui, std::vector<std::string> &filenames, OutputList *outputList);
507+
482508
container_type mData;
483-
std::map<std::string, FileData *> mNameMap;
484-
std::map<FileID, FileData *> mIdMap;
509+
name_map_type mNameMap;
510+
id_map_type mIdMap;
511+
485512
};
486513
}
487514

0 commit comments

Comments
 (0)