Fix some more memory leaks related to parseAsm()

This commit is contained in:
BigBahss 2021-02-16 06:15:54 -05:00 committed by huderlem
parent f65b6a047e
commit fa8b387120
3 changed files with 55 additions and 58 deletions

View file

@ -44,15 +44,15 @@ public:
static QString readTextFile(QString); static QString readTextFile(QString);
static int textFileLineCount(const QString &path); static int textFileLineCount(const QString &path);
void strip_comment(QString*); void strip_comment(QString*);
QList<QStringList>* parseAsm(QString); QList<QStringList> parseAsm(const QString &filename);
int evaluateDefine(QString, QMap<QString, int>*); int evaluateDefine(QString, QMap<QString, int>*);
QStringList readCArray(QString text, QString label); QStringList readCArray(QString text, QString label);
QMap<QString, QString> readNamedIndexCArray(QString text, QString label); QMap<QString, QString> readNamedIndexCArray(QString text, QString label);
QString readCIncbin(QString text, QString label); QString readCIncbin(QString text, QString label);
QMap<QString, int> readCDefines(QString filename, QStringList prefixes, QMap<QString, int> = QMap<QString, int>()); QMap<QString, int> readCDefines(QString filename, QStringList prefixes, QMap<QString, int> = QMap<QString, int>());
void readCDefinesSorted(QString, QStringList, QStringList*, QMap<QString, int> = QMap<QString, int>()); void readCDefinesSorted(QString, QStringList, QStringList*, QMap<QString, int> = QMap<QString, int>());
QList<QStringList>* getLabelMacros(QList<QStringList>*, QString); QList<QStringList> getLabelMacros(const QList<QStringList> &, const QString &);
QStringList* getLabelValues(QList<QStringList>*, QString); QStringList getLabelValues(const QList<QStringList> &, const QString &);
bool tryParseJsonFile(QJsonDocument *out, QString filepath); bool tryParseJsonFile(QJsonDocument *out, QString filepath);
bool ensureFieldsExist(QJsonObject obj, QList<QString> fields); bool ensureFieldsExist(QJsonObject obj, QList<QString> fields);

View file

@ -59,27 +59,27 @@ int ParseUtil::textFileLineCount(const QString &path) {
return text.split('\n').count() + 1; return text.split('\n').count() + 1;
} }
QList<QStringList>* ParseUtil::parseAsm(QString filename) { QList<QStringList> ParseUtil::parseAsm(const QString &filename) {
QList<QStringList> *parsed = new QList<QStringList>; QList<QStringList> parsed;
text = readTextFile(root + "/" + filename); text = readTextFile(root + '/' + filename);
QStringList lines = text.split('\n'); const QStringList lines = text.split('\n');
for (QString line : lines) { for (QString line : lines) {
strip_comment(&line); strip_comment(&line);
if (line.trimmed().isEmpty()) { if (line.trimmed().isEmpty()) {
} else if (line.contains(':')) { } else if (line.contains(':')) {
QString label = line.left(line.indexOf(':')); const QString label = line.left(line.indexOf(':'));
QStringList list{ ".label", label }; // .label is not a real keyword. It's used only to make the output more regular. const QStringList list{ ".label", label }; // .label is not a real keyword. It's used only to make the output more regular.
parsed->append(list); parsed.append(list);
// There should not be anything else on the line. // There should not be anything else on the line.
// gas will raise a syntax error if there is. // gas will raise a syntax error if there is.
} else { } else {
line = line.trimmed(); line = line.trimmed();
int index = line.indexOf(QRegExp("\\s+")); int index = line.indexOf(QRegExp("\\s+"));
QString macro = line.left(index); const QString macro = line.left(index);
QStringList params(line.right(line.length() - index).trimmed().split(QRegExp("\\s*,\\s*"))); QStringList params(line.right(line.length() - index).trimmed().split(QRegExp("\\s*,\\s*")));
params.prepend(macro); params.prepend(macro);
parsed->append(params); parsed.append(params);
} }
} }
return parsed; return parsed;
@ -335,7 +335,7 @@ QMap<QString, QString> ParseUtil::readNamedIndexCArray(QString filename, QString
QRegularExpression re_text(QString(R"(\b%1\b\s*(\[?[^\]]*\])?\s*=\s*\{([^\}]*)\})").arg(label)); QRegularExpression re_text(QString(R"(\b%1\b\s*(\[?[^\]]*\])?\s*=\s*\{([^\}]*)\})").arg(label));
QString body = re_text.match(text).captured(2).replace(QRegularExpression("\\s*"), ""); QString body = re_text.match(text).captured(2).replace(QRegularExpression("\\s*"), "");
QRegularExpression re("\\[(?<index>[A-Za-z0-9_]*)\\]=(?<value>&?[A-Za-z0-9_]*)"); QRegularExpression re("\\[(?<index>[A-Za-z0-9_]*)\\]=(?<value>&?[A-Za-z0-9_]*)");
QRegularExpressionMatchIterator iter = re.globalMatch(body); QRegularExpressionMatchIterator iter = re.globalMatch(body);
@ -349,24 +349,23 @@ QMap<QString, QString> ParseUtil::readNamedIndexCArray(QString filename, QString
return map; return map;
} }
QList<QStringList>* ParseUtil::getLabelMacros(QList<QStringList> *list, QString label) { QList<QStringList> ParseUtil::getLabelMacros(const QList<QStringList> &list, const QString &label) {
bool in_label = false; bool in_label = false;
QList<QStringList> *new_list = new QList<QStringList>; QList<QStringList> new_list;
for (int i = 0; i < list->length(); i++) { for (const auto &params : list) {
QStringList params = list->value(i); const QString macro = params.value(0);
QString macro = params.value(0);
if (macro == ".label") { if (macro == ".label") {
if (params.value(1) == label) { if (params.value(1) == label) {
in_label = true; in_label = true;
} else if (in_label) { } else if (in_label) {
// If nothing has been read yet, assume the label // If nothing has been read yet, assume the label
// we're looking for is in a stack of labels. // we're looking for is in a stack of labels.
if (new_list->length() > 0) { if (new_list.length() > 0) {
break; break;
} }
} }
} else if (in_label) { } else if (in_label) {
new_list->append(params); new_list.append(params);
} }
} }
return new_list; return new_list;
@ -374,17 +373,16 @@ QList<QStringList>* ParseUtil::getLabelMacros(QList<QStringList> *list, QString
// For if you don't care about filtering by macro, // For if you don't care about filtering by macro,
// and just want all values associated with some label. // and just want all values associated with some label.
QStringList* ParseUtil::getLabelValues(QList<QStringList> *list, QString label) { QStringList ParseUtil::getLabelValues(const QList<QStringList> &list, const QString &label) {
list = getLabelMacros(list, label); const QList<QStringList> labelMacros = getLabelMacros(list, label);
QStringList *values = new QStringList; QStringList values;
for (int i = 0; i < list->length(); i++) { for (const auto &params : labelMacros) {
QStringList params = list->value(i); const QString macro = params.value(0);
QString macro = params.value(0);
if (macro == ".align" || macro == ".ifdef" || macro == ".ifndef") { if (macro == ".align" || macro == ".ifdef" || macro == ".ifndef") {
continue; continue;
} }
for (int j = 1; j < params.length(); j++) { for (int i = 1; i < params.length(); i++) {
values->append(params.value(j)); values.append(params.value(i));
} }
} }
return values; return values;

View file

@ -1108,26 +1108,26 @@ bool Project::loadMapTilesets(Map* map) {
} }
Tileset* Project::loadTileset(QString label, Tileset *tileset) { Tileset* Project::loadTileset(QString label, Tileset *tileset) {
QStringList *values = parser.getLabelValues(parser.parseAsm("data/tilesets/headers.inc"), label); const QStringList values = parser.getLabelValues(parser.parseAsm("data/tilesets/headers.inc"), label);
if (values->isEmpty()) { if (values.isEmpty()) {
return nullptr; return nullptr;
} }
if (tileset == nullptr) { if (tileset == nullptr) {
tileset = new Tileset; tileset = new Tileset;
} }
tileset->name = label; tileset->name = label;
tileset->is_compressed = values->value(0); tileset->is_compressed = values.value(0);
tileset->is_secondary = values->value(1); tileset->is_secondary = values.value(1);
tileset->padding = values->value(2); tileset->padding = values.value(2);
tileset->tiles_label = values->value(3); tileset->tiles_label = values.value(3);
tileset->palettes_label = values->value(4); tileset->palettes_label = values.value(4);
tileset->metatiles_label = values->value(5); tileset->metatiles_label = values.value(5);
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) { if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
tileset->callback_label = values->value(6); tileset->callback_label = values.value(6);
tileset->metatile_attrs_label = values->value(7); tileset->metatile_attrs_label = values.value(7);
} else { } else {
tileset->metatile_attrs_label = values->value(6); tileset->metatile_attrs_label = values.value(6);
tileset->callback_label = values->value(7); tileset->callback_label = values.value(7);
} }
loadTilesetAssets(tileset); loadTilesetAssets(tileset);
@ -1450,15 +1450,15 @@ void Project::loadTilesetAssets(Tileset* tileset) {
} }
QRegularExpression re("([a-z])([A-Z0-9])"); QRegularExpression re("([a-z])([A-Z0-9])");
QString tilesetName = tileset->name; QString tilesetName = tileset->name;
QString dir_path = root + "/data/tilesets/" + category + "/" + tilesetName.replace("gTileset_", "").replace(re, "\\1_\\2").toLower(); QString dir_path = root + "/data/tilesets/" + category + '/' + tilesetName.replace("gTileset_", "").replace(re, "\\1_\\2").toLower();
QList<QStringList> *graphics = parser.parseAsm("data/tilesets/graphics.inc"); const QList<QStringList> graphics = parser.parseAsm("data/tilesets/graphics.inc");
QStringList *tiles_values = parser.getLabelValues(graphics, tileset->tiles_label); const QStringList tiles_values = parser.getLabelValues(graphics, tileset->tiles_label);
QStringList *palettes_values = parser.getLabelValues(graphics, tileset->palettes_label); const QStringList palettes_values = parser.getLabelValues(graphics, tileset->palettes_label);
QString tiles_path; QString tiles_path;
if (!tiles_values->isEmpty()) { if (!tiles_values.isEmpty()) {
tiles_path = root + "/" + tiles_values->value(0).section('"', 1, 1); tiles_path = root + '/' + tiles_values.value(0).section('"', 1, 1);
} else { } else {
tiles_path = dir_path + "/tiles.4bpp"; tiles_path = dir_path + "/tiles.4bpp";
if (tileset->is_compressed == "TRUE") { if (tileset->is_compressed == "TRUE") {
@ -1466,28 +1466,27 @@ void Project::loadTilesetAssets(Tileset* tileset) {
} }
} }
if (!palettes_values->isEmpty()) { if (!palettes_values.isEmpty()) {
for (int i = 0; i < palettes_values->length(); i++) { for (const auto &value : palettes_values) {
QString value = palettes_values->value(i); tileset->palettePaths.append(this->fixPalettePath(root + '/' + value.section('"', 1, 1)));
tileset->palettePaths.append(this->fixPalettePath(root + "/" + value.section('"', 1, 1)));
} }
} else { } else {
QString palettes_dir_path = dir_path + "/palettes"; QString palettes_dir_path = dir_path + "/palettes";
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
tileset->palettePaths.append(palettes_dir_path + "/" + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".pal"); tileset->palettePaths.append(palettes_dir_path + '/' + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".pal");
} }
} }
QList<QStringList> *metatiles_macros = parser.parseAsm("data/tilesets/metatiles.inc"); const QList<QStringList> metatiles_macros = parser.parseAsm("data/tilesets/metatiles.inc");
QStringList *metatiles_values = parser.getLabelValues(metatiles_macros, tileset->metatiles_label); const QStringList metatiles_values = parser.getLabelValues(metatiles_macros, tileset->metatiles_label);
if (!metatiles_values->isEmpty()) { if (!metatiles_values.isEmpty()) {
tileset->metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1); tileset->metatiles_path = root + '/' + metatiles_values.value(0).section('"', 1, 1);
} else { } else {
tileset->metatiles_path = dir_path + "/metatiles.bin"; tileset->metatiles_path = dir_path + "/metatiles.bin";
} }
QStringList *metatile_attrs_values = parser.getLabelValues(metatiles_macros, tileset->metatile_attrs_label); const QStringList metatile_attrs_values = parser.getLabelValues(metatiles_macros, tileset->metatile_attrs_label);
if (!metatile_attrs_values->isEmpty()) { if (!metatile_attrs_values.isEmpty()) {
tileset->metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1); tileset->metatile_attrs_path = root + '/' + metatile_attrs_values.value(0).section('"', 1, 1);
} else { } else {
tileset->metatile_attrs_path = dir_path + "/metatile_attributes.bin"; tileset->metatile_attrs_path = dir_path + "/metatile_attributes.bin";
} }