Refactor message handling: replace TextElement return type with std::optional for better nullability handling
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user