From 715f53731d0cb43a4d0aa1bf8e1190de5ed5e3b0 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 23 Apr 2025 17:08:47 -0400 Subject: [PATCH] Parser define maps to hashes --- include/core/parseutil.h | 17 ++++++------ src/core/parseutil.cpp | 17 ++++++++---- src/project.cpp | 59 ++++++++++++++++++++-------------------- 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/include/core/parseutil.h b/include/core/parseutil.h index a8a7939d..aae86a88 100644 --- a/include/core/parseutil.h +++ b/include/core/parseutil.h @@ -55,11 +55,12 @@ public: QString readCIncbin(const QString &text, const QString &label); QMap readCIncbinMulti(const QString &filepath); QStringList readCIncbinArray(const QString &filename, const QString &label); - QMap readCDefinesByRegex(const QString &filename, const QSet ®exList, QString *error = nullptr); - QMap readCDefinesByName(const QString &filename, const QSet &names, QString *error = nullptr); + QHash readCDefinesByRegex(const QString &filename, const QSet ®exList, QString *error = nullptr); + QHash readCDefinesByName(const QString &filename, const QSet &names, QString *error = nullptr); QStringList readCDefineNames(const QString &filename, const QSet ®exList, QString *error = nullptr); void loadGlobalCDefinesFromFile(const QString &filename, QString *error = nullptr); void loadGlobalCDefines(const QMap &defines); + void loadGlobalCDefines(const QHash &defines); void resetCDefines(); OrderedMap> readCStructs(const QString &, const QString & = "", const QHash& = {}); QList getLabelMacros(const QList&, const QString&); @@ -96,13 +97,13 @@ private: // The maps of define names to values/expressions that are available while parsing C defines. // As the parser reads and evaluates more defines it will update these maps accordingly. - QMap knownDefineValues; - QMap knownDefineExpressions; + QHash knownDefineValues; + QHash knownDefineExpressions; // Maps of special define names to values/expressions that take precedence over defines encountered while parsing. // Some (like 'TRUE'/'FALSE') are always present in these maps, others may be specified by the user with 'loadGlobalCDefines' / 'loadGlobalCDefinesFromFile'. - QMap globalDefineValues; - QMap globalDefineExpressions; + QHash globalDefineValues; + QHash globalDefineExpressions; int evaluateDefine(const QString &identifier, bool *ok = nullptr); int evaluateExpression(const QString &expression); @@ -115,11 +116,11 @@ private: QString createErrorMessage(const QString &message, const QString &expression); struct ParsedDefines { - QMap expressions; // Map of all define names encountered to their expressions + QHash expressions; // Map of all define names encountered to their expressions QStringList filteredNames; // List of define names that matched the search text, in the order that they were encountered }; ParsedDefines readCDefines(const QString &filename, const QSet &filterList, bool useRegex, QString *error); - QMap evaluateCDefines(const QString &filename, const QSet &filterList, bool useRegex, QString *error); + QHash 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); diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp index e9c6f1c0..9130aea0 100644 --- a/src/core/parseutil.cpp +++ b/src/core/parseutil.cpp @@ -488,11 +488,11 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const } // Read all the define names and their expressions in the specified file, then evaluate the ones matching the search text (and any they depend on). -QMap ParseUtil::evaluateCDefines(const QString &filename, const QSet &filterList, bool useRegex, QString *error) { +QHash ParseUtil::evaluateCDefines(const QString &filename, const QSet &filterList, bool useRegex, QString *error) { ParsedDefines defines = readCDefines(filename, filterList, useRegex, error); // Evaluate defines - QMap filteredValues; + QHash filteredValues; this->errorMap.clear(); while (!defines.filteredNames.isEmpty()) { this->curDefine = defines.filteredNames.takeFirst(); @@ -504,12 +504,12 @@ QMap ParseUtil::evaluateCDefines(const QString &filename, const QS } // Find and evaluate a specific set of defines with known names. -QMap ParseUtil::readCDefinesByName(const QString &filename, const QSet &names, QString *error) { +QHash ParseUtil::readCDefinesByName(const QString &filename, const QSet &names, QString *error) { return evaluateCDefines(filename, names, false, error); } // Find and evaluate an unknown list of defines with a known name pattern. -QMap ParseUtil::readCDefinesByRegex(const QString &filename, const QSet ®exList, QString *error) { +QHash ParseUtil::readCDefinesByRegex(const QString &filename, const QSet ®exList, QString *error) { return evaluateCDefines(filename, regexList, true, error); } @@ -526,12 +526,17 @@ void ParseUtil::loadGlobalCDefinesFromFile(const QString &filename, QString *err loadGlobalCDefines(readCDefines(filename, {}, false, error).expressions); } -void ParseUtil::loadGlobalCDefines(const QMap &defines) { +void ParseUtil::loadGlobalCDefines(const QHash &defines) { this->globalDefineExpressions.insert(defines); } +void ParseUtil::loadGlobalCDefines(const QMap &defines) { + for (auto it = defines.constBegin(); it != defines.constEnd(); it++) + this->globalDefineExpressions.insert(it.key(), it.value()); +} + void ParseUtil::resetCDefines() { - static const QMap defaultDefineValues = { + static const QHash defaultDefineValues = { {"FALSE", 0}, {"TRUE", 1}, {"SCHAR_MIN", SCHAR_MIN}, diff --git a/src/project.cpp b/src/project.cpp index b798a203..4b038618 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1481,7 +1481,7 @@ bool Project::readTilesetMetatileLabels() { fileWatcher.addPath(root + "/" + metatileLabelsFilename); const QSet regexList = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix))}; - const QMap defines = parser.readCDefinesByRegex(metatileLabelsFilename, regexList); + const auto defines = parser.readCDefinesByRegex(metatileLabelsFilename, regexList); for (auto i = defines.constBegin(); i != defines.constEnd(); i++) { QString label = i.key(); uint32_t metatileId = i.value(); @@ -2116,16 +2116,15 @@ bool Project::readFieldmapProperties() { const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_fieldmap); fileWatcher.addPath(root + "/" + filename); - const QMap defines = parser.readCDefinesByName(filename, { - numTilesPrimaryName, - numTilesTotalName, - numMetatilesPrimaryName, - numPalsPrimaryName, - numPalsTotalName, - maxMapSizeName, - numTilesPerMetatileName, - mapOffsetWidthName, - mapOffsetHeightName, + const auto defines = parser.readCDefinesByName(filename, { numTilesPrimaryName, + numTilesTotalName, + numMetatilesPrimaryName, + numPalsPrimaryName, + numPalsTotalName, + maxMapSizeName, + numTilesPerMetatileName, + mapOffsetWidthName, + mapOffsetHeightName, }); auto loadDefine = [defines](const QString name, int * dest, int min, int max) { @@ -2219,16 +2218,15 @@ bool Project::readFieldmapMasks() { const QString elevationMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_elevation); const QString behaviorMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_behavior); const QString layerTypeMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_layer); - const QSet searchNames = { - metatileIdMaskName, - collisionMaskName, - elevationMaskName, - behaviorMaskName, - layerTypeMaskName, - }; + const QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap); fileWatcher.addPath(root + "/" + globalFieldmap); - QMap defines = parser.readCDefinesByName(globalFieldmap, searchNames); + const auto defines = parser.readCDefinesByName(globalFieldmap, { metatileIdMaskName, + collisionMaskName, + elevationMaskName, + behaviorMaskName, + layerTypeMaskName, + }); // These mask values are accessible via the settings editor for users who don't have these defines. // If users do have the defines we disable them in the settings editor and direct them to their project files. @@ -2239,8 +2237,8 @@ bool Project::readFieldmapMasks() { // Read Block masks auto readBlockMask = [defines](const QString name, uint16_t *value) { - auto it = defines.find(name); - if (it == defines.end()) + auto it = defines.constFind(name); + if (it == defines.constEnd()) return false; *value = static_cast(it.value()); if (*value != it.value()){ @@ -2314,7 +2312,7 @@ bool Project::readFieldmapMasks() { // Read #defines for encounter and terrain types to populate in the Tileset Editor dropdowns (if necessary) QString error; if (projectConfig.metatileEncounterTypeMask) { - QMap defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_encounter_types)}, &error); + const auto defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_encounter_types)}, &error); if (!error.isEmpty()) { logWarn(QString("Failed to read encounter type constants from '%1': %2").arg(globalFieldmap).arg(error)); error = QString(); @@ -2325,7 +2323,7 @@ bool Project::readFieldmapMasks() { } } if (projectConfig.metatileTerrainTypeMask) { - QMap defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_terrain_types)}, &error); + const auto defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_terrain_types)}, &error); if (!error.isEmpty()) { logWarn(QString("Failed to read terrain type constants from '%1': %2").arg(globalFieldmap).arg(error)); error = QString(); @@ -2673,7 +2671,7 @@ bool Project::readMetatileBehaviors() { QString filename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_behaviors); fileWatcher.addPath(root + "/" + filename); QString error; - QMap defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)}, &error); + const auto defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)}, &error); if (defines.isEmpty() && projectConfig.metatileBehaviorMask) { // Not having any metatile behavior names is ok (their values will be displayed instead) // but if the user's metatiles can have nonzero values then warn them, as they likely want names. @@ -2710,9 +2708,14 @@ bool Project::readObjEventGfxConstants() { QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_events); fileWatcher.addPath(root + "/" + filename); QString error; - this->gfxDefines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)}, &error); + const auto defines = parser.readCDefinesByRegex(filename, {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)}, &error); if (!error.isEmpty()) logWarn(QString("Failed to read object event graphics constants from '%1': %2").arg(filename).arg(error)); + + this->gfxDefines.clear(); + for (auto it = defines.constBegin(); it != defines.constEnd(); it++) + this->gfxDefines.insert(it.key(), it.value()); + return true; } @@ -2720,7 +2723,7 @@ bool Project::readMiscellaneousConstants() { const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_global); const QString maxObjectEventsName = projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count); fileWatcher.addPath(root + "/" + filename); - QMap defines = parser.readCDefinesByName(filename, {maxObjectEventsName}); + const auto defines = parser.readCDefinesByName(filename, {maxObjectEventsName}); this->maxObjectEvents = 64; // Default value auto it = defines.find(maxObjectEventsName); @@ -2953,9 +2956,7 @@ QPixmap Project::getEventPixmap(const QString &gfxName, int frame, bool hFlip) { // Invalid gfx constant. If this is a number, try to use that instead. bool ok; int gfxNum = ParseUtil::gameStringToInt(gfxName, &ok); - if (ok && gfxNum < this->gfxDefines.count()) { - gfx = this->eventGraphicsMap.value(this->gfxDefines.key(gfxNum, "NULL"), nullptr); - } + if (ok) gfx = this->eventGraphicsMap.value(this->gfxDefines.key(gfxNum, "NULL"), nullptr); } if (gfx && !gfx->loaded) { // This is the first request for this event's sprite. We'll attempt to load it now.