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 <optional>
#include <string>
#include "util/hex.h"
@@ -24,17 +25,16 @@ uint8_t FindDictionaryEntry(uint8_t value) {
return value - DICTOFF;
}
TextElement FindMatchingCommand(uint8_t b) {
TextElement empty_element;
std::optional<TextElement> FindMatchingCommand(uint8_t b) {
for (const auto &text_element : TextCommands) {
if (text_element.ID == b) {
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(),
[value](const TextElement &text_element) {
return text_element.ID == value;
@@ -42,8 +42,7 @@ TextElement FindMatchingSpecial(uint8_t value) {
if (it != SpecialChars.end()) {
return *it;
}
return TextElement();
return std::nullopt;
}
ParsedElement FindMatchingElement(const std::string &str) {
@@ -80,15 +79,15 @@ std::string ParseTextDataByte(uint8_t value) {
}
// Check for command.
TextElement text_element = FindMatchingCommand(value);
if (!text_element.Empty()) {
return text_element.GenericToken;
auto text_element = FindMatchingCommand(value);
if (text_element != std::nullopt) {
return text_element->GenericToken;
}
// Check for special characters.
text_element = FindMatchingSpecial(value);
if (!text_element.Empty()) {
return text_element.GenericToken;
auto special_element = FindMatchingSpecial(value);
if (special_element != std::nullopt) {
return text_element->GenericToken;
}
// Check for dictionary.
@@ -214,10 +213,10 @@ absl::StatusOr<MessageData> ParseSingleMessage(
temp_bytes_raw.push_back(current_byte);
// Check for command.
TextElement text_element = FindMatchingCommand(current_byte);
if (!text_element.Empty()) {
current_message_raw.append(text_element.GetParamToken());
current_message_parsed.append(text_element.GetParamToken());
auto text_element = FindMatchingCommand(current_byte);
if (text_element != std::nullopt) {
current_message_raw.append(text_element->GetParamToken());
current_message_parsed.append(text_element->GetParamToken());
temp_bytes_parsed.push_back(current_byte);
continue;
}
@@ -283,12 +282,12 @@ std::vector<std::string> ParseMessageData(
}
} else {
auto text_element = FindMatchingCommand(byte);
if (!text_element.Empty()) {
if (text_element.ID == kScrollVertical ||
text_element.ID == kLine2 || text_element.ID == kLine3) {
if (text_element != std::nullopt) {
if (text_element->ID == kScrollVertical ||
text_element->ID == kLine2 || text_element->ID == kLine3) {
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 FindMatchingCommand(uint8_t b);
std::optional<TextElement> FindMatchingCommand(uint8_t b);
static const std::vector<TextElement> SpecialChars = {
TextElement(0x43, "...", false, "Ellipsis …"),
@@ -282,7 +282,7 @@ static const std::vector<TextElement> SpecialChars = {
TextElement(0x4B, "LFR", false, "Link face right"),
};
TextElement FindMatchingSpecial(uint8_t b);
std::optional<TextElement> FindMatchingSpecial(uint8_t b);
struct ParsedElement {
TextElement Parent;

View File

@@ -261,23 +261,25 @@ void MessageEditor::ReadAllTextDataV2() {
current_raw_message.clear();
current_parsed_message.clear();
continue;
} else if (current_byte == 0xFF) {
break;
}
raw_message.push_back(current_byte);
TextElement text_element = FindMatchingCommand(current_byte);
if (!text_element.Empty()) {
auto text_element = FindMatchingCommand(current_byte);
if (text_element != std::nullopt) {
parsed_message.push_back(current_byte);
if (text_element.HasArgument) {
if (text_element->HasArgument) {
current_byte = rom()->data()[pos++];
raw_message.push_back(current_byte);
parsed_message.push_back(current_byte);
}
current_raw_message.append(text_element.GetParamToken(current_byte));
current_parsed_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));
if (text_element.Token == kBankToken) {
if (text_element->Token == kBankToken) {
pos = kTextData2;
}
@@ -285,10 +287,10 @@ void MessageEditor::ReadAllTextDataV2() {
}
// Check for special characters.
text_element = FindMatchingSpecial(current_byte);
if (!text_element.Empty()) {
current_raw_message.append(text_element.GetParamToken());
current_parsed_message.append(text_element.GetParamToken());
auto special_element = FindMatchingSpecial(current_byte);
if (special_element != std::nullopt) {
current_raw_message.append(special_element->GetParamToken());
current_parsed_message.append(special_element->GetParamToken());
parsed_message.push_back(current_byte);
continue;
}
@@ -299,7 +301,7 @@ void MessageEditor::ReadAllTextDataV2() {
current_raw_message.append("[");
current_raw_message.append(DICTIONARYTOKEN);
current_raw_message.append(":");
current_raw_message.append(util::HexWord(dictionary));
current_raw_message.append(util::HexByte(dictionary));
current_raw_message.append("]");
uint32_t address = Get24LocalFromPC(
@@ -336,7 +338,6 @@ void MessageEditor::ReadAllTextData() {
std::string current_message_raw;
std::string current_message_parsed;
TextElement text_element;
while (true) {
current_byte = rom()->data()[pos++];
@@ -361,20 +362,19 @@ void MessageEditor::ReadAllTextData() {
temp_bytes_raw.push_back(current_byte);
// Check for command.
text_element = FindMatchingCommand(current_byte);
if (!text_element.Empty()) {
auto text_element = FindMatchingCommand(current_byte);
if (text_element.has_value()) {
temp_bytes_parsed.push_back(current_byte);
if (text_element.HasArgument) {
if (text_element->HasArgument) {
current_byte = rom()->data()[pos++];
temp_bytes_raw.push_back(current_byte);
temp_bytes_parsed.push_back(current_byte);
}
current_message_raw.append(text_element.GetParamToken(current_byte));
current_message_parsed.append(text_element.GetParamToken(current_byte));
current_message_raw.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;
}
@@ -382,10 +382,10 @@ void MessageEditor::ReadAllTextData() {
}
// Check for special characters.
text_element = FindMatchingSpecial(current_byte);
if (!text_element.Empty()) {
current_message_raw.append(text_element.GetParamToken());
current_message_parsed.append(text_element.GetParamToken());
auto special_element = FindMatchingSpecial(current_byte);
if (special_element.has_value()) {
current_message_raw.append(special_element->GetParamToken());
current_message_parsed.append(special_element->GetParamToken());
temp_bytes_parsed.push_back(current_byte);
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,
int sizex, int sizey) {
const int num_x_tiles = 16;
@@ -532,8 +514,14 @@ void MessageEditor::DrawCharacterToPreview(const std::vector<uint8_t> &text) {
// characters.
DrawStringToPreview("(NAME)");
} else if (value >= DICTOFF && value < (DICTOFF + 97)) {
auto dictionaryEntry = GetDictionaryFromID(value - DICTOFF);
DrawCharacterToPreview(dictionaryEntry.Data);
int pos = value - DICTOFF;
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 kMessageBankChangeId = 0x80;
static TextElement DictionaryElement =
TextElement(0x80, DICTIONARYTOKEN, true, "Dictionary");
class MessageEditor : public Editor, public SharedRom {
public:
MessageEditor() { type_ = EditorType::kMessage; }
@@ -62,7 +59,6 @@ class MessageEditor : public Editor, public SharedRom {
void Delete();
void SelectAll();
DictionaryEntry GetDictionaryFromID(uint8_t value);
void DrawTileToPreview(int x, int y, int srcx, int srcy, int pal,
int sizex = 1, int sizey = 1);
void DrawCharacterToPreview(char c);