Refactor message handling: replace TextElement return type with std::optional for better nullability handling

This commit is contained in:
scawful
2025-04-05 17:24:11 -04:00
parent 9705745c14
commit 3d3a88a9c6
4 changed files with 52 additions and 69 deletions

View File

@@ -1,5 +1,6 @@
#include "message_data.h" #include "message_data.h"
#include <optional>
#include <string> #include <string>
#include "util/hex.h" #include "util/hex.h"
@@ -24,17 +25,16 @@ uint8_t FindDictionaryEntry(uint8_t value) {
return value - DICTOFF; return value - DICTOFF;
} }
TextElement FindMatchingCommand(uint8_t b) { std::optional<TextElement> FindMatchingCommand(uint8_t b) {
TextElement empty_element;
for (const auto &text_element : TextCommands) { for (const auto &text_element : TextCommands) {
if (text_element.ID == b) { if (text_element.ID == b) {
return text_element; return text_element;
} }
} }
return empty_element; return std::nullopt;
} }
TextElement FindMatchingSpecial(uint8_t value) { std::optional<TextElement> FindMatchingSpecial(uint8_t value) {
auto it = std::find_if(SpecialChars.begin(), SpecialChars.end(), auto it = std::find_if(SpecialChars.begin(), SpecialChars.end(),
[value](const TextElement &text_element) { [value](const TextElement &text_element) {
return text_element.ID == value; return text_element.ID == value;
@@ -42,8 +42,7 @@ TextElement FindMatchingSpecial(uint8_t value) {
if (it != SpecialChars.end()) { if (it != SpecialChars.end()) {
return *it; return *it;
} }
return std::nullopt;
return TextElement();
} }
ParsedElement FindMatchingElement(const std::string &str) { ParsedElement FindMatchingElement(const std::string &str) {
@@ -80,15 +79,15 @@ std::string ParseTextDataByte(uint8_t value) {
} }
// Check for command. // Check for command.
TextElement text_element = FindMatchingCommand(value); auto text_element = FindMatchingCommand(value);
if (!text_element.Empty()) { if (text_element != std::nullopt) {
return text_element.GenericToken; return text_element->GenericToken;
} }
// Check for special characters. // Check for special characters.
text_element = FindMatchingSpecial(value); auto special_element = FindMatchingSpecial(value);
if (!text_element.Empty()) { if (special_element != std::nullopt) {
return text_element.GenericToken; return text_element->GenericToken;
} }
// Check for dictionary. // Check for dictionary.
@@ -214,10 +213,10 @@ absl::StatusOr<MessageData> ParseSingleMessage(
temp_bytes_raw.push_back(current_byte); temp_bytes_raw.push_back(current_byte);
// Check for command. // Check for command.
TextElement text_element = FindMatchingCommand(current_byte); auto text_element = FindMatchingCommand(current_byte);
if (!text_element.Empty()) { if (text_element != std::nullopt) {
current_message_raw.append(text_element.GetParamToken()); current_message_raw.append(text_element->GetParamToken());
current_message_parsed.append(text_element.GetParamToken()); current_message_parsed.append(text_element->GetParamToken());
temp_bytes_parsed.push_back(current_byte); temp_bytes_parsed.push_back(current_byte);
continue; continue;
} }
@@ -283,12 +282,12 @@ std::vector<std::string> ParseMessageData(
} }
} else { } else {
auto text_element = FindMatchingCommand(byte); auto text_element = FindMatchingCommand(byte);
if (!text_element.Empty()) { if (text_element != std::nullopt) {
if (text_element.ID == kScrollVertical || if (text_element->ID == kScrollVertical ||
text_element.ID == kLine2 || text_element.ID == kLine3) { text_element->ID == kLine2 || text_element->ID == kLine3) {
parsed_message.append("\n"); parsed_message.append("\n");
} }
parsed_message.append(text_element.GenericToken); parsed_message.append(text_element->GenericToken);
} }
} }
} }

View File

@@ -256,7 +256,7 @@ static const std::vector<TextElement> TextCommands = {
TextElement(0x70, "NONO", false, kCrash), TextElement(0x70, "NONO", false, kCrash),
}; };
TextElement FindMatchingCommand(uint8_t b); std::optional<TextElement> FindMatchingCommand(uint8_t b);
static const std::vector<TextElement> SpecialChars = { static const std::vector<TextElement> SpecialChars = {
TextElement(0x43, "...", false, "Ellipsis …"), TextElement(0x43, "...", false, "Ellipsis …"),
@@ -282,7 +282,7 @@ static const std::vector<TextElement> SpecialChars = {
TextElement(0x4B, "LFR", false, "Link face right"), TextElement(0x4B, "LFR", false, "Link face right"),
}; };
TextElement FindMatchingSpecial(uint8_t b); std::optional<TextElement> FindMatchingSpecial(uint8_t b);
struct ParsedElement { struct ParsedElement {
TextElement Parent; TextElement Parent;

View File

@@ -261,23 +261,25 @@ void MessageEditor::ReadAllTextDataV2() {
current_raw_message.clear(); current_raw_message.clear();
current_parsed_message.clear(); current_parsed_message.clear();
continue; continue;
} else if (current_byte == 0xFF) {
break;
} }
raw_message.push_back(current_byte); raw_message.push_back(current_byte);
TextElement text_element = FindMatchingCommand(current_byte); auto text_element = FindMatchingCommand(current_byte);
if (!text_element.Empty()) { if (text_element != std::nullopt) {
parsed_message.push_back(current_byte); parsed_message.push_back(current_byte);
if (text_element.HasArgument) { if (text_element->HasArgument) {
current_byte = rom()->data()[pos++]; current_byte = rom()->data()[pos++];
raw_message.push_back(current_byte); raw_message.push_back(current_byte);
parsed_message.push_back(current_byte); parsed_message.push_back(current_byte);
} }
current_raw_message.append(text_element.GetParamToken(current_byte)); current_raw_message.append(text_element->GetParamToken(current_byte));
current_parsed_message.append(text_element.GetParamToken(current_byte)); current_parsed_message.append(text_element->GetParamToken(current_byte));
if (text_element.Token == kBankToken) { if (text_element->Token == kBankToken) {
pos = kTextData2; pos = kTextData2;
} }
@@ -285,10 +287,10 @@ void MessageEditor::ReadAllTextDataV2() {
} }
// Check for special characters. // Check for special characters.
text_element = FindMatchingSpecial(current_byte); auto special_element = FindMatchingSpecial(current_byte);
if (!text_element.Empty()) { if (special_element != std::nullopt) {
current_raw_message.append(text_element.GetParamToken()); current_raw_message.append(special_element->GetParamToken());
current_parsed_message.append(text_element.GetParamToken()); current_parsed_message.append(special_element->GetParamToken());
parsed_message.push_back(current_byte); parsed_message.push_back(current_byte);
continue; continue;
} }
@@ -299,7 +301,7 @@ void MessageEditor::ReadAllTextDataV2() {
current_raw_message.append("["); current_raw_message.append("[");
current_raw_message.append(DICTIONARYTOKEN); current_raw_message.append(DICTIONARYTOKEN);
current_raw_message.append(":"); current_raw_message.append(":");
current_raw_message.append(util::HexWord(dictionary)); current_raw_message.append(util::HexByte(dictionary));
current_raw_message.append("]"); current_raw_message.append("]");
uint32_t address = Get24LocalFromPC( uint32_t address = Get24LocalFromPC(
@@ -336,7 +338,6 @@ void MessageEditor::ReadAllTextData() {
std::string current_message_raw; std::string current_message_raw;
std::string current_message_parsed; std::string current_message_parsed;
TextElement text_element;
while (true) { while (true) {
current_byte = rom()->data()[pos++]; current_byte = rom()->data()[pos++];
@@ -361,20 +362,19 @@ void MessageEditor::ReadAllTextData() {
temp_bytes_raw.push_back(current_byte); temp_bytes_raw.push_back(current_byte);
// Check for command. // Check for command.
text_element = FindMatchingCommand(current_byte); auto text_element = FindMatchingCommand(current_byte);
if (text_element.has_value()) {
if (!text_element.Empty()) {
temp_bytes_parsed.push_back(current_byte); temp_bytes_parsed.push_back(current_byte);
if (text_element.HasArgument) { if (text_element->HasArgument) {
current_byte = rom()->data()[pos++]; current_byte = rom()->data()[pos++];
temp_bytes_raw.push_back(current_byte); temp_bytes_raw.push_back(current_byte);
temp_bytes_parsed.push_back(current_byte); temp_bytes_parsed.push_back(current_byte);
} }
current_message_raw.append(text_element.GetParamToken(current_byte)); current_message_raw.append(text_element->GetParamToken(current_byte));
current_message_parsed.append(text_element.GetParamToken(current_byte)); current_message_parsed.append(text_element->GetParamToken(current_byte));
if (text_element.Token == kBankToken) { if (text_element->Token == kBankToken) {
pos = kTextData2; pos = kTextData2;
} }
@@ -382,10 +382,10 @@ void MessageEditor::ReadAllTextData() {
} }
// Check for special characters. // Check for special characters.
text_element = FindMatchingSpecial(current_byte); auto special_element = FindMatchingSpecial(current_byte);
if (!text_element.Empty()) { if (special_element.has_value()) {
current_message_raw.append(text_element.GetParamToken()); current_message_raw.append(special_element->GetParamToken());
current_message_parsed.append(text_element.GetParamToken()); current_message_parsed.append(special_element->GetParamToken());
temp_bytes_parsed.push_back(current_byte); temp_bytes_parsed.push_back(current_byte);
continue; continue;
} }
@@ -425,24 +425,6 @@ void MessageEditor::ReadAllTextData() {
} }
} }
std::string ReplaceAllDictionaryWords(std::string str,
std::vector<DictionaryEntry> dictionary) {
std::string temp = str;
for (const auto &entry : dictionary) {
if (absl::StrContains(temp, entry.Contents)) {
temp = absl::StrReplaceAll(temp, {{entry.Contents, entry.Contents}});
}
}
return temp;
}
DictionaryEntry MessageEditor::GetDictionaryFromID(uint8_t value) {
if (value < 0 || value >= all_dictionaries_.size()) {
return DictionaryEntry();
}
return all_dictionaries_[value];
}
void MessageEditor::DrawTileToPreview(int x, int y, int srcx, int srcy, int pal, void MessageEditor::DrawTileToPreview(int x, int y, int srcx, int srcy, int pal,
int sizex, int sizey) { int sizex, int sizey) {
const int num_x_tiles = 16; const int num_x_tiles = 16;
@@ -532,8 +514,14 @@ void MessageEditor::DrawCharacterToPreview(const std::vector<uint8_t> &text) {
// characters. // characters.
DrawStringToPreview("(NAME)"); DrawStringToPreview("(NAME)");
} else if (value >= DICTOFF && value < (DICTOFF + 97)) { } else if (value >= DICTOFF && value < (DICTOFF + 97)) {
auto dictionaryEntry = GetDictionaryFromID(value - DICTOFF); int pos = value - DICTOFF;
DrawCharacterToPreview(dictionaryEntry.Data); if (pos < 0 || pos >= all_dictionaries_.size()) {
// Invalid dictionary entry.
std::cerr << "Invalid dictionary entry: " << pos << std::endl;
continue;
}
auto dictionary_entry = all_dictionaries_[pos];
DrawCharacterToPreview(dictionary_entry.Data);
} }
} }
} }

View File

@@ -30,9 +30,6 @@ constexpr uint8_t kWidthArraySize = 100;
constexpr uint8_t kBlockTerminator = 0x80; constexpr uint8_t kBlockTerminator = 0x80;
constexpr uint8_t kMessageBankChangeId = 0x80; constexpr uint8_t kMessageBankChangeId = 0x80;
static TextElement DictionaryElement =
TextElement(0x80, DICTIONARYTOKEN, true, "Dictionary");
class MessageEditor : public Editor, public SharedRom { class MessageEditor : public Editor, public SharedRom {
public: public:
MessageEditor() { type_ = EditorType::kMessage; } MessageEditor() { type_ = EditorType::kMessage; }
@@ -62,7 +59,6 @@ class MessageEditor : public Editor, public SharedRom {
void Delete(); void Delete();
void SelectAll(); void SelectAll();
DictionaryEntry GetDictionaryFromID(uint8_t value);
void DrawTileToPreview(int x, int y, int srcx, int srcy, int pal, void DrawTileToPreview(int x, int y, int srcx, int srcy, int pal,
int sizex = 1, int sizey = 1); int sizex = 1, int sizey = 1);
void DrawCharacterToPreview(char c); void DrawCharacterToPreview(char c);