Move CheatFileParser out to the header, remove the line_ mmember variable

This commit is contained in:
Henrik Rydgård committed 2025-10-07 10:07:04 -06:00
1 parent 9c5b1c1b8b
commit f21876b0b7
2 files changed
+70 -70

No files matched your search

+35 -69
View File
@@ -43,75 +43,37 @@ using namespace SceCtrl;
void hleCheat(u64 userdata, int cyclesLate);
static inline std::string TrimString(const std::string &s) {
static inline std::string TrimString(std::string_view s) {
auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c) {
// isspace() expects 0 - 255, so convert any sign-extended value.
return std::isspace(c & 0xFF);
return std::isspace((u8)c);
});
auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c){
return std::isspace(c & 0xFF);
return std::isspace((u8)c);
}).base();
return wsback > wsfront ? std::string(wsfront, wsback) : std::string();
}
class CheatFileParser {
public:
CheatFileParser(const Path &filename, const std::string &gameID = "") {
fp_ = File::OpenCFile(filename, "rt");
validGameID_ = ReplaceAll(gameID, "-", "");
}
~CheatFileParser() {
if (fp_)
fclose(fp_);
}
CheatFileParser::CheatFileParser(const Path &filename, std::string_view gameID) {
fp_ = File::OpenCFile(filename, "rt");
validGameID_ = ReplaceAll(gameID, "-", "");
}
bool Parse();
std::vector<std::string> GetErrors() const {
return errors_;
}
std::vector<CheatCode> GetCheats() const {
return cheats_;
}
std::vector<CheatFileInfo> GetFileInfo() const {
return cheatInfo_;
}
protected:
void Flush();
void FlushCheatInfo();
void AddError(const std::string &msg);
void ParseLine(const std::string &line);
void ParseDataLine(const std::string &line);
bool ValidateGameID(const std::string &gameID);
FILE *fp_ = nullptr;
std::string validGameID_;
int line_ = 0;
int games_ = 0;
std::vector<std::string> errors_;
std::vector<CheatFileInfo> cheatInfo_;
std::vector<CheatCode> cheats_;
std::vector<CheatLine> pendingLines_;
CheatFileInfo lastCheatInfo_;
bool gameEnabled_ = true;
bool gameRiskyEnabled_ = false;
bool cheatEnabled_ = false;
};
CheatFileParser::~CheatFileParser() {
if (fp_)
fclose(fp_);
}
bool CheatFileParser::Parse() {
// Ugh, using a member variable as loop counter is bad.
for (line_ = 1; fp_ && !feof(fp_); ++line_) {
for (int lineNumber = 1; fp_ && !feof(fp_); ++lineNumber) {
char temp[2048];
char *tempLine = fgets(temp, sizeof(temp), fp_);
if (!tempLine)
continue;
// Detect UTF-8 BOM sequence, and ignore it.
if (line_ == 1 && memcmp(tempLine, "\xEF\xBB\xBF", 3) == 0)
if (lineNumber == 1 && memcmp(tempLine, "\xEF\xBB\xBF", 3) == 0)
tempLine += 3;
std::string line = TrimString(tempLine);
@@ -119,13 +81,13 @@ bool CheatFileParser::Parse() {
// and a minimum of 1 displayable character in cheat name string "_C0 1"
// which both equal to 5 characters.
if (line.length() >= 5 && line[0] == '_') {
ParseLine(line);
ParseLine(line, lineNumber);
} else if (line.length() >= 2 && line[0] == '/' && line[1] == '/') {
// Comment, ignore.
} else if (line.length() >= 1 && line[0] == '#') {
// Comment, ignore.
} else if (line.length() > 0) {
errors_.push_back(StringFromFormat("Unrecognized content on line %d: expecting _", line_));
errors_.push_back(StringFromFormat("Unrecognized content on line %d: expecting _", lineNumber));
}
}
@@ -149,11 +111,11 @@ void CheatFileParser::FlushCheatInfo() {
}
}
void CheatFileParser::AddError(const std::string &err) {
errors_.push_back(StringFromFormat("Error on line %d: %s", line_, err.c_str()));
void CheatFileParser::AddError(const std::string &err, int lineNumber) {
errors_.push_back(StringFromFormat("Error on line %d: %s", lineNumber, err.c_str()));
}
void CheatFileParser::ParseLine(const std::string &line) {
void CheatFileParser::ParseLine(const std::string &line, int lineNumber) {
switch (line[1]) {
case 'S':
// Disc ID, validate (for multi-disc cheat files)?
@@ -193,13 +155,13 @@ void CheatFileParser::ParseLine(const std::string &line) {
// Cheat name and activation status.
if (line.length() >= 3 && line[2] >= '1' && line[2] <= '9') {
lastCheatInfo_ = { line_, line.length() >= 5 ? line.substr(4) : "", true };
lastCheatInfo_ = { lineNumber, line.length() >= 5 ? line.substr(4) : "", true };
cheatEnabled_ = true;
} else if (line.length() >= 3 && line[2] == '0') {
lastCheatInfo_ = { line_, line.length() >= 5 ? line.substr(4) : "", false };
lastCheatInfo_ = { lineNumber, line.length() >= 5 ? line.substr(4) : "", false };
cheatEnabled_ = false;
} else {
AddError("could not parse cheat name line");
AddError("could not parse cheat name line", lineNumber);
cheatEnabled_ = false;
return;
}
@@ -207,24 +169,25 @@ void CheatFileParser::ParseLine(const std::string &line) {
case 'L':
// CwCheat data line.
ParseDataLine(line.substr(2));
ParseDataLine(line.substr(2), lineNumber);
return;
case 'M':
// TempAR data line.
AddError("TempAR codes not supported");
AddError("TempAR codes not supported", lineNumber);
return;
default:
AddError("unknown line type");
AddError("unknown line type", lineNumber);
return;
}
}
void CheatFileParser::ParseDataLine(const std::string &line) {
void CheatFileParser::ParseDataLine(const std::string &line, int lineNumber) {
if (!gameEnabled_) {
return;
}
if (!cheatEnabled_) {
FlushCheatInfo();
return;
@@ -234,15 +197,15 @@ void CheatFileParser::ParseDataLine(const std::string &line) {
int len = 0;
if (sscanf(line.c_str(), "%x %x %n", &cheatLine.part1, &cheatLine.part2, &len) == 2) {
if ((size_t)len < line.length()) {
AddError("junk after line data");
AddError("junk after line data", lineNumber);
}
pendingLines_.push_back(cheatLine);
} else {
AddError("expecting two values");
AddError("expecting two values", lineNumber);
}
}
bool CheatFileParser::ValidateGameID(const std::string &gameID) {
bool CheatFileParser::ValidateGameID(std::string_view gameID) {
return validGameID_.empty() || ReplaceAll(TrimString(gameID), "-", "") == validGameID_;
}
@@ -359,14 +322,14 @@ void hleCheat(u64 userdata, int cyclesLate) {
if (!cheatEngine || !cheatsEnabled)
return;
if (g_Config.bReloadCheats) { //Checks if the "reload cheats" button has been pressed.
if (g_Config.bReloadCheats) { // Checks if the "reload cheats" button has been pressed.
cheatEngine->ParseCheats();
g_Config.bReloadCheats = false;
}
cheatEngine->Run();
}
CWCheatEngine::CWCheatEngine(const std::string &gameID) : gameID_(gameID) {
CWCheatEngine::CWCheatEngine(std::string_view gameID) : gameID_(gameID) {
filename_ = GetSysDirectory(DIRECTORY_CHEATS) / (gameID_ + ".ini");
}
@@ -390,7 +353,10 @@ void CWCheatEngine::ParseCheats() {
CheatFileParser parser(filename_, gameID_);
parser.Parse();
// TODO: Report errors.
// TODO: Report errors in a user-visible way.
for (auto &error : parser.GetErrors()) {
ERROR_LOG(Log::System, "CwCheat error: %s", error.c_str());
}
cheats_ = parser.GetCheats();
}
+35 -1
View File
@@ -3,6 +3,7 @@
#pragma once
#include <string>
#include <string_view>
#include <vector>
#include <iostream>
#include <sstream>
@@ -39,7 +40,7 @@ struct CheatOperation;
class CWCheatEngine {
public:
CWCheatEngine(const std::string &gameID);
CWCheatEngine(std::string_view gameID);
std::vector<CheatFileInfo> FileInfo() const;
void ParseCheats();
void CreateCheatFile();
@@ -69,3 +70,36 @@ private:
std::string gameID_;
Path filename_;
};
class CheatFileParser {
public:
CheatFileParser(const Path &filename, std::string_view gameID = "");
~CheatFileParser();
bool Parse();
const std::vector<std::string> &GetErrors() const { return errors_; }
const std::vector<CheatCode> &GetCheats() const { return cheats_; }
const std::vector<CheatFileInfo> &GetFileInfo() const { return cheatInfo_; }
protected:
void Flush();
void FlushCheatInfo();
void AddError(const std::string &msg, int lineNumber);
void ParseLine(const std::string &line, int lineNumber);
void ParseDataLine(const std::string &line, int lineNumber);
bool ValidateGameID(std::string_view gameID);
FILE *fp_ = nullptr;
std::string validGameID_;
int games_ = 0;
std::vector<std::string> errors_;
std::vector<CheatFileInfo> cheatInfo_;
std::vector<CheatCode> cheats_;
std::vector<CheatLine> pendingLines_;
CheatFileInfo lastCheatInfo_;
bool gameEnabled_ = true;
bool gameRiskyEnabled_ = false;
bool cheatEnabled_ = false;
};