From ef6eb69c72b2ff90cd343b87daed12d25b7cd52f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 19 Mar 2025 14:27:56 -0400 Subject: [PATCH] Add file cache to ParserUtil --- include/core/parseutil.h | 6 +++- include/project.h | 1 + src/core/parseutil.cpp | 57 +++++++++++++++++++++++++++-------- src/project.cpp | 64 ++++++++++++++++++++++++---------------- 4 files changed, 90 insertions(+), 38 deletions(-) diff --git a/include/core/parseutil.h b/include/core/parseutil.h index b5fc5dd2..4c19a27c 100644 --- a/include/core/parseutil.h +++ b/include/core/parseutil.h @@ -45,7 +45,8 @@ public: ParseUtil(); void set_root(const QString &dir); static QString readTextFile(const QString &path, QString *error = nullptr); - void invalidateTextFile(const QString &path); + bool cacheFile(const QString &path, QString *error = nullptr); + void clearFileCache() { this->fileCache.clear(); } static int textFileLineCount(const QString &path); QList parseAsm(const QString &filename); QStringList readCArray(const QString &filename, const QString &label); @@ -87,6 +88,7 @@ private: QString text; QString file; QString curDefine; + QHash fileCache; QHash errorMap; int evaluateDefine(const QString&, const QString &, QMap*, QMap*); QList tokenizeExpression(QString, QMap*, QMap*); @@ -105,6 +107,8 @@ private: QMap evaluateCDefines(const QString &filename, const QSet &filterList, bool useRegex, QString *error); bool defineNameMatchesFilter(const QString &name, const QSet &filterList) const; bool defineNameMatchesFilter(const QString &name, const QSet &filterList) const; + QString loadTextFile(const QString &path, QString *error = nullptr); + QString pathWithRoot(const QString &path); static const QRegularExpression re_incScriptLabel; static const QRegularExpression re_globalIncScriptLabel; diff --git a/include/project.h b/include/project.h index f7a4b5cc..5fcb579c 100644 --- a/include/project.h +++ b/include/project.h @@ -279,6 +279,7 @@ private: void ignoreWatchedFileTemporarily(QString filepath); void recordFileChange(const QString &filepath); + void resetFileCache(); QString findSpeciesIconPath(const QStringList &names) const; diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp index 22880562..62735db3 100644 --- a/src/core/parseutil.cpp +++ b/src/core/parseutil.cpp @@ -37,6 +37,12 @@ void ParseUtil::set_root(const QString &dir) { this->root = dir; } +QString ParseUtil::pathWithRoot(const QString &path) { + if (this->root.isEmpty()) return path; + if (path.startsWith(this->root)) return path; + return QString("%1/%2").arg(this->root).arg(path); +} + void ParseUtil::recordError(const QString &message) { this->errorMap[this->curDefine].append(message); } @@ -85,6 +91,34 @@ QString ParseUtil::readTextFile(const QString &path, QString *error) { return text; } +// Load the specified text file, either from the cache or by reading the file. +// Note that this doesn't insert any parsed files into the file cache, and we don't +// want it to (we read a lot of files only once, storing them all is a waste of memory). +QString ParseUtil::loadTextFile(const QString &path, QString *error) { + auto it = this->fileCache.constFind(path); + if (it != this->fileCache.constEnd()) { + // Load text file from cache + //logWarn(QString("CACHE HIT ON %1").arg(path)); + return it.value(); + } + +/* TODO: Remove + static QSet parsedFiles; + if (parsedFiles.contains(path)) { + logWarn(QString("CACHE MISS ON %1").arg(path)); + } else { + parsedFiles.insert(path); + } +*/ + + return readTextFile(pathWithRoot(path), error); +} + +bool ParseUtil::cacheFile(const QString &path, QString *error) { + this->fileCache.insert(path, readTextFile(pathWithRoot(path), error)); + return !error || error->isEmpty(); +} + int ParseUtil::textFileLineCount(const QString &path) { const QString text = readTextFile(path); return text.split('\n').count() + 1; @@ -93,7 +127,7 @@ int ParseUtil::textFileLineCount(const QString &path) { QList ParseUtil::parseAsm(const QString &filename) { QList parsed; - this->text = readTextFile(this->root + '/' + filename); + this->text = loadTextFile(filename); const QStringList lines = removeLineComments(this->text, "@").split('\n'); for (const auto &line : lines) { const QString trimmedLine = line.trimmed(); @@ -295,7 +329,7 @@ QString ParseUtil::readCIncbin(const QString &filename, const QString &label) { return path; } - this->text = readTextFile(this->root + "/" + filename); + this->text = loadTextFile(filename); QRegularExpression re(QString( "\\b%1\\b" @@ -316,7 +350,7 @@ QMap ParseUtil::readCIncbinMulti(const QString &filepath) { QMap incbinMap; this->file = filepath; - this->text = readTextFile(this->root + "/" + filepath); + this->text = loadTextFile(filepath); static const QRegularExpression regex("(?