diff --git a/Source/utils/language.cpp b/Source/utils/language.cpp index 28076ee60..fc5e972e0 100644 --- a/Source/utils/language.cpp +++ b/Source/utils/language.cpp @@ -1,7 +1,12 @@ +#include "utils/language.h" + +#include +#include +#include + #include "options.h" #include "utils/paths.h" #include "utils/utf8.h" -#include using namespace devilution; #define MO_MAGIC 0x950412de @@ -15,7 +20,7 @@ struct cstring_cmp { } }; -std::map map; +std::map> map; std::map meta; struct mo_head { @@ -89,41 +94,23 @@ bool parse_metadata(char *data) return utf8; } -char *read_entry(FILE *fp, mo_entry *e) +bool read_entry(FILE *fp, mo_entry *e, std::vector &result) { - void *data; - - if (fseek(fp, e->offset, SEEK_SET)) { - return nullptr; - } - - if (!(data = calloc(e->length + 1, sizeof(char)))) { - return nullptr; - } - - if (fread(data, sizeof(char), e->length, fp) != e->length) { - free(data); - return nullptr; - } - - return static_cast(data); + if (fseek(fp, e->offset, SEEK_SET) != 0) + return false; + result.resize(e->length + 1); + result.back() = '\0'; + return (fread(result.data(), sizeof(char), e->length, fp) == e->length); } + } // namespace -const char *LanguageTranslate(const char *key) +const std::string &LanguageTranslate(const char *key) { auto it = map.find(key); if (it == map.end()) { - char *val; - if (!(val = (char *)calloc(strlen(key) + 1, sizeof(char)))) { - return key; - } - std::string latin1 = utf8_to_latin1(key); - strcpy(val, latin1.c_str()); - map[key] = val; - return val; + return map.insert({key, utf8_to_latin1(key)}).first->second; } - return it->second; } @@ -139,7 +126,6 @@ const char *LanguageMetadata(const char *key) void LanguageInitialize() { - mo_entry *src, *dst; mo_head head; FILE *fp; bool utf8; @@ -153,6 +139,7 @@ void LanguageInitialize() } } // Read header and do sanity checks + // FIXME: Endianness. if (fread(&head, sizeof(mo_head), 1, fp) != 1) { return; } @@ -166,52 +153,35 @@ void LanguageInitialize() } // Read entries of source strings - src = new mo_entry[head.nb_mappings]; - if (fseek(fp, head.src_offset, SEEK_SET)) { - delete[] src; + auto src = std::make_unique(head.nb_mappings); + if (fseek(fp, head.src_offset, SEEK_SET) != 0) return; - } - if (fread(src, sizeof(mo_entry), head.nb_mappings, fp) != head.nb_mappings) { - delete[] src; + // FIXME: Endianness. + if (fread(src.get(), sizeof(mo_entry), head.nb_mappings, fp) != head.nb_mappings) return; - } // Read entries of target strings - dst = new mo_entry[head.nb_mappings]; - if (fseek(fp, head.dst_offset, SEEK_SET)) { - delete[] dst; - delete[] src; + auto dst = std::make_unique(head.nb_mappings); + if (fseek(fp, head.dst_offset, SEEK_SET) != 0) return; - } - - if (fread(dst, sizeof(mo_entry), head.nb_mappings, fp) != head.nb_mappings) { - delete[] dst; - delete[] src; + // FIXME: Endianness. + if (fread(dst.get(), sizeof(mo_entry), head.nb_mappings, fp) != head.nb_mappings) return; - } // Read strings described by entries for (uint32_t i = 0; i < head.nb_mappings; i++) { - char *key, *val; - if ((key = read_entry(fp, src + i))) { - if ((val = read_entry(fp, dst + i))) { - if (!*key) { - utf8 = parse_metadata(val); + std::vector key; + std::vector value; + if (read_entry(fp, &src[i], key) && read_entry(fp, &dst[i], value)) { + if (key.empty()) { + utf8 = parse_metadata(value.data()); + } else { + if (utf8) { + map.emplace(key.data(), utf8_to_latin1(value.data())); } else { - if (utf8) { - std::string latin1 = utf8_to_latin1(key); - strcpy(key, latin1.c_str()); - - latin1 = utf8_to_latin1(val); - strcpy(val, latin1.c_str()); - } - map[key] = val; + map.emplace(key.data(), value.data()); } - } else { - free(key); } } } - delete[] dst; - delete[] src; } diff --git a/Source/utils/language.h b/Source/utils/language.h index 23c0a72a6..8f1a87ac2 100644 --- a/Source/utils/language.h +++ b/Source/utils/language.h @@ -1,8 +1,10 @@ #pragma once -#define _(x) LanguageTranslate(x) +#include + +#define _(x) LanguageTranslate(x).c_str() #define N_(x) (x) void LanguageInitialize(); -const char* LanguageTranslate(const char* key); -const char* LanguageMetadata(const char *key); +const std::string &LanguageTranslate(const char* key); +const char *LanguageMetadata(const char *key);