summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Lutz <michi@icosahedron.de>2020-05-17 23:31:47 +0200
committerMichael Lutz <michi@icosahedron.de>2020-05-21 20:02:34 +0200
commit43cd892e0c2c012355d7eb6d47cfa4ad4b7e68eb (patch)
tree589c8791baba745a7dfc3a33b19a28c8b0046ea8 /src
parentf2b40f40aa7cbccaed20ec52b41d4704a45d8db1 (diff)
downloadopenttd-43cd892e0c2c012355d7eb6d47cfa4ad4b7e68eb.tar.xz
Codechange: Replace custom linked list for GRF texts with STL vectors and strings.
Diffstat (limited to 'src')
-rw-r--r--src/network/network_gamelist.cpp6
-rw-r--r--src/network/network_udp.cpp14
-rw-r--r--src/newgrf.cpp22
-rw-r--r--src/newgrf_config.cpp93
-rw-r--r--src/newgrf_config.h34
-rw-r--r--src/newgrf_text.cpp190
-rw-r--r--src/newgrf_text.h27
7 files changed, 128 insertions, 258 deletions
diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp
index ff744e875..dfe07bdbb 100644
--- a/src/network/network_gamelist.cpp
+++ b/src/network/network_gamelist.cpp
@@ -175,21 +175,15 @@ void NetworkAfterNewGRFScan()
/* Don't know the GRF, so mark game incompatible and the (possibly)
* already resolved name for this GRF (another server has sent the
* name of the GRF already. */
- c->name->Release();
c->name = FindUnknownGRFName(c->ident.grfid, c->ident.md5sum, true);
- c->name->AddRef();
c->status = GCS_NOT_FOUND;
/* If we miss a file, we're obviously incompatible. */
item->info.compatible = false;
} else {
c->filename = f->filename;
- c->name->Release();
c->name = f->name;
- c->name->AddRef();
- c->info->Release();
c->info = f->info;
- c->info->AddRef();
c->status = GCS_UNKNOWN;
}
}
diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp
index 90b99ec44..03344fe57 100644
--- a/src/network/network_udp.cpp
+++ b/src/network/network_udp.cpp
@@ -426,9 +426,9 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
/* Try to find the GRFTextWrapper for the name of this GRF ID and MD5sum tuple.
* If it exists and not resolved yet, then name of the fake GRF is
* overwritten with the name from the reply. */
- GRFTextWrapper *unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
- if (unknown_name != nullptr && strcmp(GetGRFStringFromGRFText(unknown_name->text), UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
- AddGRFTextToList(&unknown_name->text, name);
+ GRFTextWrapper unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
+ if (unknown_name && strcmp(GetGRFStringFromGRFText(unknown_name), UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
+ AddGRFTextToList(unknown_name, name);
}
}
}
@@ -441,21 +441,13 @@ void ClientNetworkUDPSocketHandler::HandleIncomingNetworkGameInfoGRFConfig(GRFCo
/* Don't know the GRF, so mark game incompatible and the (possibly)
* already resolved name for this GRF (another server has sent the
* name of the GRF already */
- config->name->Release();
config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true);
- config->name->AddRef();
config->status = GCS_NOT_FOUND;
} else {
config->filename = f->filename;
- config->name->Release();
config->name = f->name;
- config->name->AddRef();
- config->info->Release();
config->info = f->info;
- config->info->AddRef();
- config->url->Release();
config->url = f->url;
- config->url->AddRef();
}
SetBit(config->flags, GCF_COPY);
}
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index c1b836481..4ada53a0a 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -6720,11 +6720,11 @@ static void ScanInfo(ByteReader *buf)
/* GRF IDs starting with 0xFF are reserved for internal TTDPatch use */
if (GB(grfid, 0, 8) == 0xFF) SetBit(_cur.grfconfig->flags, GCF_SYSTEM);
- AddGRFTextToList(&_cur.grfconfig->name->text, 0x7F, grfid, false, name);
+ AddGRFTextToList(_cur.grfconfig->name, 0x7F, grfid, false, name);
if (buf->HasData()) {
const char *info = buf->ReadString();
- AddGRFTextToList(&_cur.grfconfig->info->text, 0x7F, grfid, true, info);
+ AddGRFTextToList(_cur.grfconfig->info, 0x7F, grfid, true, info);
}
/* GLS_INFOSCAN only looks for the action 8, so we can skip the rest of the file */
@@ -7806,21 +7806,21 @@ static void TranslateGRFStrings(ByteReader *buf)
/** Callback function for 'INFO'->'NAME' to add a translation to the newgrf name. */
static bool ChangeGRFName(byte langid, const char *str)
{
- AddGRFTextToList(&_cur.grfconfig->name->text, langid, _cur.grfconfig->ident.grfid, false, str);
+ AddGRFTextToList(_cur.grfconfig->name, langid, _cur.grfconfig->ident.grfid, false, str);
return true;
}
/** Callback function for 'INFO'->'DESC' to add a translation to the newgrf description. */
static bool ChangeGRFDescription(byte langid, const char *str)
{
- AddGRFTextToList(&_cur.grfconfig->info->text, langid, _cur.grfconfig->ident.grfid, true, str);
+ AddGRFTextToList(_cur.grfconfig->info, langid, _cur.grfconfig->ident.grfid, true, str);
return true;
}
/** Callback function for 'INFO'->'URL_' to set the newgrf url. */
static bool ChangeGRFURL(byte langid, const char *str)
{
- AddGRFTextToList(&_cur.grfconfig->url->text, langid, _cur.grfconfig->ident.grfid, false, str);
+ AddGRFTextToList(_cur.grfconfig->url, langid, _cur.grfconfig->ident.grfid, false, str);
return true;
}
@@ -7922,14 +7922,14 @@ static GRFParameterInfo *_cur_parameter; ///< The parameter which info is curren
/** Callback function for 'INFO'->'PARAM'->param_num->'NAME' to set the name of a parameter. */
static bool ChangeGRFParamName(byte langid, const char *str)
{
- AddGRFTextToList(&_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
+ AddGRFTextToList(_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
return true;
}
/** Callback function for 'INFO'->'PARAM'->param_num->'DESC' to set the description of a parameter. */
static bool ChangeGRFParamDescription(byte langid, const char *str)
{
- AddGRFTextToList(&_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
+ AddGRFTextToList(_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
return true;
}
@@ -8113,12 +8113,12 @@ static bool ChangeGRFParamValueNames(ByteReader *buf)
byte langid = buf->ReadByte();
const char *name_string = buf->ReadString();
- std::pair<uint32, GRFText *> *val_name = _cur_parameter->value_names.Find(id);
+ std::pair<uint32, GRFTextList> *val_name = _cur_parameter->value_names.Find(id);
if (val_name != _cur_parameter->value_names.End()) {
- AddGRFTextToList(&val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
+ AddGRFTextToList(val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
} else {
- GRFText *list = nullptr;
- AddGRFTextToList(&list, langid, _cur.grfconfig->ident.grfid, false, name_string);
+ GRFTextList list;
+ AddGRFTextToList(list, langid, _cur.grfconfig->ident.grfid, false, name_string);
_cur_parameter->value_names.Insert(id, list);
}
diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp
index 605bceca5..8452d0829 100644
--- a/src/newgrf_config.cpp
+++ b/src/newgrf_config.cpp
@@ -21,23 +21,13 @@
#include "textfile_gui.h"
#include "thread.h"
#include "newgrf_config.h"
+#include "newgrf_text.h"
#include "fileio_func.h"
#include "fios.h"
#include "safeguards.h"
-/** Create a new GRFTextWrapper. */
-GRFTextWrapper::GRFTextWrapper() :
- text(nullptr)
-{
-}
-
-/** Cleanup a GRFTextWrapper object. */
-GRFTextWrapper::~GRFTextWrapper()
-{
- CleanUpGRFText(this->text);
-}
/**
* Create a new GRFConfig.
@@ -45,15 +35,9 @@ GRFTextWrapper::~GRFTextWrapper()
* is copied so the original string isn't needed after the constructor.
*/
GRFConfig::GRFConfig(const char *filename) :
- name(new GRFTextWrapper()),
- info(new GRFTextWrapper()),
- url(new GRFTextWrapper()),
num_valid_params(lengthof(param))
{
if (filename != nullptr) this->filename = stredup(filename);
- this->name->AddRef();
- this->info->AddRef();
- this->url->AddRef();
}
/**
@@ -79,9 +63,6 @@ GRFConfig::GRFConfig(const GRFConfig &config) :
MemCpyT<uint8>(this->original_md5sum, config.original_md5sum, lengthof(this->original_md5sum));
MemCpyT<uint32>(this->param, config.param, lengthof(this->param));
if (config.filename != nullptr) this->filename = stredup(config.filename);
- this->name->AddRef();
- this->info->AddRef();
- this->url->AddRef();
if (config.error != nullptr) this->error = new GRFError(*config.error);
for (uint i = 0; i < config.param_info.size(); i++) {
if (config.param_info[i] == nullptr) {
@@ -100,9 +81,6 @@ GRFConfig::~GRFConfig()
free(this->filename);
delete this->error;
}
- this->name->Release();
- this->info->Release();
- this->url->Release();
for (uint i = 0; i < this->param_info.size(); i++) delete this->param_info[i];
}
@@ -125,7 +103,7 @@ void GRFConfig::CopyParams(const GRFConfig &src)
*/
const char *GRFConfig::GetName() const
{
- const char *name = GetGRFStringFromGRFText(this->name->text);
+ const char *name = GetGRFStringFromGRFText(this->name);
return StrEmpty(name) ? this->filename : name;
}
@@ -135,7 +113,7 @@ const char *GRFConfig::GetName() const
*/
const char *GRFConfig::GetDescription() const
{
- return GetGRFStringFromGRFText(this->info->text);
+ return GetGRFStringFromGRFText(this->info);
}
/**
@@ -144,7 +122,7 @@ const char *GRFConfig::GetDescription() const
*/
const char *GRFConfig::GetURL() const
{
- return GetGRFStringFromGRFText(this->url->text);
+ return GetGRFStringFromGRFText(this->url);
}
/** Set the default value for all parameters as specified by action14. */
@@ -232,8 +210,8 @@ GRFError::~GRFError()
* @param nr The newgrf parameter that is changed.
*/
GRFParameterInfo::GRFParameterInfo(uint nr) :
- name(nullptr),
- desc(nullptr),
+ name(),
+ desc(),
type(PTYPE_UINT_ENUM),
min_value(0),
max_value(UINT32_MAX),
@@ -241,6 +219,7 @@ GRFParameterInfo::GRFParameterInfo(uint nr) :
param_nr(nr),
first_bit(0),
num_bit(32),
+ value_names(),
complete_labels(false)
{}
@@ -250,8 +229,8 @@ GRFParameterInfo::GRFParameterInfo(uint nr) :
* @param info The GRFParameterInfo object to make a copy of.
*/
GRFParameterInfo::GRFParameterInfo(GRFParameterInfo &info) :
- name(DuplicateGRFText(info.name)),
- desc(DuplicateGRFText(info.desc)),
+ name(info.name),
+ desc(info.desc),
type(info.type),
min_value(info.min_value),
max_value(info.max_value),
@@ -259,23 +238,9 @@ GRFParameterInfo::GRFParameterInfo(GRFParameterInfo &info) :
param_nr(info.param_nr),
first_bit(info.first_bit),
num_bit(info.num_bit),
+ value_names(info.value_names),
complete_labels(info.complete_labels)
{
- for (uint i = 0; i < info.value_names.size(); i++) {
- std::pair<uint32, GRFText *> *data = info.value_names.data() + i;
- this->value_names.Insert(data->first, DuplicateGRFText(data->second));
- }
-}
-
-/** Cleanup all parameter info. */
-GRFParameterInfo::~GRFParameterInfo()
-{
- CleanUpGRFText(this->name);
- CleanUpGRFText(this->desc);
- for (uint i = 0; i < this->value_names.size(); i++) {
- std::pair<uint32, GRFText *> *data = this->value_names.data() + i;
- CleanUpGRFText(data->second);
- }
}
/**
@@ -598,12 +563,8 @@ compatible_grf:
free(c->filename);
c->filename = stredup(f->filename);
memcpy(c->ident.md5sum, f->ident.md5sum, sizeof(c->ident.md5sum));
- c->name->Release();
c->name = f->name;
- c->name->AddRef();
- c->info->Release();
c->info = f->name;
- c->info->AddRef();
c->error = nullptr;
c->version = f->version;
c->min_loadable_version = f->min_loadable_version;
@@ -686,7 +647,7 @@ bool GRFFileScanner::AddFile(const char *filename, size_t basepath_length, const
_modal_progress_paint_mutex.lock();
const char *name = nullptr;
- if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name->text);
+ if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name);
if (name == nullptr) name = c->filename;
UpdateNewGRFScanStatus(this->num_scanned, name);
@@ -820,8 +781,12 @@ const GRFConfig *FindGRFConfig(uint32 grfid, FindGRFConfigMode mode, const uint8
/** Structure for UnknownGRFs; this is a lightweight variant of GRFConfig */
struct UnknownGRF : public GRFIdentifier {
- UnknownGRF *next; ///< The next unknown GRF.
- GRFTextWrapper *name; ///< Name of the GRF.
+ GRFTextWrapper name; ///< Name of the GRF.
+
+ UnknownGRF() = default;
+ UnknownGRF(const UnknownGRF &other) = default;
+ UnknownGRF(UnknownGRF &&other) = default;
+ UnknownGRF(uint32 grfid, const uint8 *_md5sum) : GRFIdentifier(grfid, _md5sum), name(new GRFTextList) {}
};
/**
@@ -841,30 +806,24 @@ struct UnknownGRF : public GRFIdentifier {
* and MD5 checksum or nullptr when it does not exist and create is false.
* This value must NEVER be freed by the caller.
*/
-GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
+GRFTextWrapper FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
{
- UnknownGRF *grf;
- static UnknownGRF *unknown_grfs = nullptr;
+ static std::vector<UnknownGRF> unknown_grfs;
- for (grf = unknown_grfs; grf != nullptr; grf = grf->next) {
- if (grf->grfid == grfid) {
- if (memcmp(md5sum, grf->md5sum, sizeof(grf->md5sum)) == 0) return grf->name;
+ for (const auto &grf : unknown_grfs) {
+ if (grf.grfid == grfid) {
+ if (memcmp(md5sum, grf.md5sum, sizeof(grf.md5sum)) == 0) return grf.name;
}
}
if (!create) return nullptr;
- grf = CallocT<UnknownGRF>(1);
- grf->grfid = grfid;
- grf->next = unknown_grfs;
- grf->name = new GRFTextWrapper();
- grf->name->AddRef();
+ unknown_grfs.emplace_back(grfid, md5sum);
+ UnknownGRF &grf = unknown_grfs.back();
- AddGRFTextToList(&grf->name->text, UNKNOWN_GRF_NAME_PLACEHOLDER);
- memcpy(grf->md5sum, md5sum, sizeof(grf->md5sum));
+ AddGRFTextToList(grf.name, UNKNOWN_GRF_NAME_PLACEHOLDER);
- unknown_grfs = grf;
- return grf->name;
+ return grf.name;
}
/**
diff --git a/src/newgrf_config.h b/src/newgrf_config.h
index 8c3b2ecdf..2c8a8559d 100644
--- a/src/newgrf_config.h
+++ b/src/newgrf_config.h
@@ -16,6 +16,7 @@
#include "misc/countedptr.hpp"
#include "fileio_type.h"
#include "textfile_type.h"
+#include "newgrf_text.h"
/** GRF config bit flags */
enum GCF_Flags {
@@ -83,6 +84,16 @@ struct GRFIdentifier {
uint32 grfid; ///< GRF ID (defined by Action 0x08)
uint8 md5sum[16]; ///< MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
+ GRFIdentifier() = default;
+ GRFIdentifier(const GRFIdentifier &other) = default;
+ GRFIdentifier(GRFIdentifier &&other) = default;
+ GRFIdentifier(uint32 grfid, const uint8 *md5sum) : grfid(grfid)
+ {
+ MemCpyT(this->md5sum, md5sum, lengthof(this->md5sum));
+ }
+
+ GRFIdentifier& operator =(const GRFIdentifier &other) = default;
+
/**
* Does the identification match the provided values?
* @param grfid Expected grfid.
@@ -121,9 +132,8 @@ enum GRFParameterType {
struct GRFParameterInfo {
GRFParameterInfo(uint nr);
GRFParameterInfo(GRFParameterInfo &info);
- ~GRFParameterInfo();
- struct GRFText *name; ///< The name of this parameter
- struct GRFText *desc; ///< The description of this parameter
+ GRFTextList name; ///< The name of this parameter
+ GRFTextList desc; ///< The description of this parameter
GRFParameterType type; ///< The type of this parameter
uint32 min_value; ///< The minimal value this parameter can have
uint32 max_value; ///< The maximal value of this parameter
@@ -131,7 +141,7 @@ struct GRFParameterInfo {
byte param_nr; ///< GRF parameter to store content in
byte first_bit; ///< First bit to use in the GRF parameter
byte num_bit; ///< Number of bits to use for this parameter
- SmallMap<uint32, struct GRFText *> value_names; ///< Names for each value.
+ SmallMap<uint32, GRFTextList> value_names; ///< Names for each value.
bool complete_labels; ///< True if all values have a label.
uint32 GetValue(struct GRFConfig *config) const;
@@ -139,14 +149,6 @@ struct GRFParameterInfo {
void Finalize();
};
-/** Reference counted wrapper around a GRFText pointer. */
-struct GRFTextWrapper : public SimpleCountedObject {
- struct GRFText *text; ///< The actual text
-
- GRFTextWrapper();
- ~GRFTextWrapper();
-};
-
/** Information about GRF, used in the game and (part of it) in savegames */
struct GRFConfig : ZeroedMemoryAllocator {
GRFConfig(const char *filename = nullptr);
@@ -156,9 +158,9 @@ struct GRFConfig : ZeroedMemoryAllocator {
GRFIdentifier ident; ///< grfid and md5sum to uniquely identify newgrfs
uint8 original_md5sum[16]; ///< MD5 checksum of original file if only a 'compatible' file was loaded
char *filename; ///< Filename - either with or without full path
- GRFTextWrapper *name; ///< NOSAVE: GRF name (Action 0x08)
- GRFTextWrapper *info; ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
- GRFTextWrapper *url; ///< NOSAVE: URL belonging to this GRF.
+ GRFTextWrapper name; ///< NOSAVE: GRF name (Action 0x08)
+ GRFTextWrapper info; ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
+ GRFTextWrapper url; ///< NOSAVE: URL belonging to this GRF.
GRFError *error; ///< NOSAVE: Error/Warning during GRF loading (Action 0x0B)
uint32 version; ///< NOSAVE: Version a NewGRF can set so only the newest NewGRF is shown
@@ -229,7 +231,7 @@ void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFC
/** For communication about GRFs over the network */
#define UNKNOWN_GRF_NAME_PLACEHOLDER "<Unknown>"
-GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create);
+GRFTextWrapper FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create);
void UpdateNewGRFScanStatus(uint num, const char *name);
bool UpdateNewGRFConfigPalette(int32 p1 = 0);
diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp
index 134511944..4f1a6ffd4 100644
--- a/src/newgrf_text.cpp
+++ b/src/newgrf_text.cpp
@@ -60,89 +60,6 @@ enum GRFExtendedLanguages {
GRFLX_UNSPECIFIED = 0x7F,
};
-/**
- * Element of the linked list.
- * Each of those elements represent the string,
- * but according to a different lang.
- */
-struct GRFText {
-public:
- /**
- * Allocate, and assign a new GRFText with the given text.
- * As these strings can have string terminations in them, e.g.
- * due to "choice lists" we (sometimes) cannot rely on detecting
- * the length by means of strlen. Also, if the length of already
- * known not scanning the whole string is more efficient.
- * @param langid The language of the text.
- * @param text The text to store in the new GRFText.
- * @param len The length of the text.
- */
- static GRFText *New(byte langid, const char *text, size_t len)
- {
- return new (len) GRFText(langid, text, len);
- }
-
- /**
- * Create a copy of this GRFText.
- * @param orig the grftext to copy.
- * @return an exact copy of the given text.
- */
- static GRFText *Copy(GRFText *orig)
- {
- return GRFText::New(orig->langid, orig->text, orig->len);
- }
-
- /**
- * Helper allocation function to disallow something.
- * Don't allow simple 'news'; they wouldn't have enough memory.
- * @param size the amount of space not to allocate.
- */
- void *operator new(size_t size)
- {
- NOT_REACHED();
- }
-
- /**
- * Free the memory we allocated.
- * @param p memory to free.
- */
- void operator delete(void *p)
- {
- free(p);
- }
-private:
- /**
- * Actually construct the GRFText.
- * @param langid_ The language of the text.
- * @param text_ The text to store in this GRFText.
- * @param len_ The length of the text to store.
- */
- GRFText(byte langid_, const char *text_, size_t len_) : next(nullptr), len(len_), langid(langid_)
- {
- /* We need to use memcpy instead of strcpy due to
- * the possibility of "choice lists" and therefore
- * intermediate string terminators. */
- memcpy(this->text, text_, len);
- }
-
- /**
- * Allocate memory for this class.
- * @param size the size of the instance
- * @param extra the extra memory for the text
- * @return the requested amount of memory for both the instance and the text
- */
- void *operator new(size_t size, size_t extra)
- {
- return MallocT<byte>(size + extra);
- }
-
-public:
- GRFText *next; ///< The next GRFText in this chain.
- size_t len; ///< The length of the stored string, used for copying.
- byte langid; ///< The language associated with this GRFText.
- char text[]; ///< The actual (translated) text.
-};
-
/**
* Holder of the above structure.
@@ -153,7 +70,7 @@ struct GRFTextEntry {
uint32 grfid;
uint16 stringid;
StringID def_string;
- GRFText *textholder;
+ GRFTextList textholder;
};
@@ -576,26 +493,23 @@ string_end:
}
/**
- * Add a GRFText to a GRFText list.
+ * Add a new text to a GRFText list.
* @param list The list where the text should be added to.
- * @param text_to_add The GRFText to add to the list.
+ * @param langid The The language of the new text.
+ * @param text_to_add The text to add to the list.
*/
-void AddGRFTextToList(GRFText **list, GRFText *text_to_add)
+static void AddGRFTextToList(GRFTextList &list, byte langid, const std::string &text_to_add)
{
- GRFText **ptext, *text;
-
/* Loop through all languages and see if we can replace a string */
- for (ptext = list; (text = *ptext) != nullptr; ptext = &text->next) {
- if (text->langid == text_to_add->langid) {
- text_to_add->next = text->next;
- *ptext = text_to_add;
- delete text;
+ for (auto &text : list) {
+ if (text.langid == langid) {
+ text.text = text_to_add;
return;
}
}
/* If a string wasn't replaced, then we must append the new string */
- *ptext = text_to_add;
+ list.push_back(GRFText{ langid, text_to_add });
}
/**
@@ -607,41 +521,41 @@ void AddGRFTextToList(GRFText **list, GRFText *text_to_add)
* @param text_to_add The text to add to the list.
* @note All text-codes will be translated.
*/
-void AddGRFTextToList(struct GRFText **list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
+void AddGRFTextToList(GRFTextList &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
{
int len;
char *translatedtext = TranslateTTDPatchCodes(grfid, langid, allow_newlines, text_to_add, &len);
- GRFText *newtext = GRFText::New(langid, translatedtext, len);
+ std::string newtext(translatedtext, len);
free(translatedtext);
- AddGRFTextToList(list, newtext);
+ AddGRFTextToList(list, langid, newtext);
}
/**
- * Add a GRFText to a GRFText list. The text should not contain any text-codes.
- * The text will be added as a 'default language'-text.
+ * Add a string to a GRFText list.
* @param list The list where the text should be added to.
+ * @param langid The language of the new text.
+ * @param grfid The grfid where this string is defined.
+ * @param allow_newlines Whether newlines are allowed in this string.
* @param text_to_add The text to add to the list.
+ * @note All text-codes will be translated.
*/
-void AddGRFTextToList(struct GRFText **list, const char *text_to_add)
+void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
{
- AddGRFTextToList(list, GRFText::New(0x7F, text_to_add, strlen(text_to_add) + 1));
+ if (!list) list.reset(new GRFTextList());
+ AddGRFTextToList(*list, langid, grfid, allow_newlines, text_to_add);
}
/**
- * Create a copy of this GRFText list.
- * @param orig The GRFText list to copy.
- * @return A duplicate of the given GRFText.
+ * Add a GRFText to a GRFText list. The text should not contain any text-codes.
+ * The text will be added as a 'default language'-text.
+ * @param list The list where the text should be added to.
+ * @param text_to_add The text to add to the list.
*/
-GRFText *DuplicateGRFText(GRFText *orig)
+void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add)
{
- GRFText *newtext = nullptr;
- GRFText **ptext = &newtext;
- for (; orig != nullptr; orig = orig->next) {
- *ptext = GRFText::Copy(orig);
- ptext = &(*ptext)->next;
- }
- return newtext;
+ if (!list) list.reset(new GRFTextList());
+ AddGRFTextToList(*list, GRFLX_UNSPECIFIED, std::string(text_to_add));
}
/**
@@ -681,22 +595,20 @@ StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid_to_add, bool ne
int len;
translatedtext = TranslateTTDPatchCodes(grfid, langid_to_add, allow_newlines, text_to_add, &len);
-
- GRFText *newtext = GRFText::New(langid_to_add, translatedtext, len);
-
+ std::string newtext(translatedtext, len);
free(translatedtext);
/* If we didn't find our stringid and grfid in the list, allocate a new id */
if (id == _num_grf_texts) _num_grf_texts++;
- if (_grf_text[id].textholder == nullptr) {
+ if (_grf_text[id].textholder.empty()) {
_grf_text[id].grfid = grfid;
_grf_text[id].stringid = stringid;
_grf_text[id].def_string = def_string;
}
- AddGRFTextToList(&_grf_text[id].textholder, newtext);
+ AddGRFTextToList(_grf_text[id].textholder, langid_to_add, newtext);
- grfmsg(3, "Added 0x%X: grfid %08X string 0x%X lang 0x%X string '%s' (%X)", id, grfid, stringid, newtext->langid, newtext->text, MakeStringID(TEXT_TAB_NEWGRF_START, id));
+ grfmsg(3, "Added 0x%X: grfid %08X string 0x%X lang 0x%X string '%s' (%X)", id, grfid, stringid, langid_to_add, newtext.c_str(), MakeStringID(TEXT_TAB_NEWGRF_START, id));
return MakeStringID(TEXT_TAB_NEWGRF_START, id);
}
@@ -721,20 +633,20 @@ StringID GetGRFStringID(uint32 grfid, StringID stringid)
* current language it is returned, otherwise the default translation
* is returned. If there is neither a default nor a translation for the
* current language nullptr is returned.
- * @param text The GRFText to get the string from.
+ * @param text_list The GRFTextList to get the string from.
*/
-const char *GetGRFStringFromGRFText(const GRFText *text)
+const char *GetGRFStringFromGRFText(const GRFTextList &text_list)
{
const char *default_text = nullptr;
/* Search the list of lang-strings of this stringid for current lang */
- for (; text != nullptr; text = text->next) {
- if (text->langid == _currentLangID) return text->text;
+ for (const auto &text : text_list) {
+ if (text.langid == _currentLangID) return text.text.c_str();
/* If the current string is English or American, set it as the
* fallback language if the specific language isn't available. */
- if (text->langid == GRFLX_UNSPECIFIED || (default_text == nullptr && (text->langid == GRFLX_ENGLISH || text->langid == GRFLX_AMERICAN))) {
- default_text = text->text;
+ if (text.langid == GRFLX_UNSPECIFIED || (default_text == nullptr && (text.langid == GRFLX_ENGLISH || text.langid == GRFLX_AMERICAN))) {
+ default_text = text.text.c_str();
}
}
@@ -742,6 +654,18 @@ const char *GetGRFStringFromGRFText(const GRFText *text)
}
/**
+ * Get a C-string from a GRFText-list. If there is a translation for the
+ * current language it is returned, otherwise the default translation
+ * is returned. If there is neither a default nor a translation for the
+ * current language nullptr is returned.
+ * @param text The GRFTextList to get the string from.
+ */
+const char *GetGRFStringFromGRFText(const GRFTextWrapper &text)
+{
+ return text ? GetGRFStringFromGRFText(*text) : nullptr;
+}
+
+/**
* Get a C-string from a stringid set by a newgrf.
*/
const char *GetGRFStringPtr(uint16 stringid)
@@ -783,19 +707,6 @@ bool CheckGrfLangID(byte lang_id, byte grf_version)
}
/**
- * Delete all items of a linked GRFText list.
- * @param grftext the head of the list to delete
- */
-void CleanUpGRFText(GRFText *grftext)
-{
- while (grftext != nullptr) {
- GRFText *grftext2 = grftext->next;
- delete grftext;
- grftext = grftext2;
- }
-}
-
-/**
* House cleaning.
* Remove all strings and reset the text counter.
*/
@@ -804,10 +715,9 @@ void CleanUpStrings()
uint id;
for (id = 0; id < _num_grf_texts; id++) {
- CleanUpGRFText(_grf_text[id].textholder);
_grf_text[id].grfid = 0;
_grf_text[id].stringid = 0;
- _grf_text[id].textholder = nullptr;
+ _grf_text[id].textholder.clear();
}
_num_grf_texts = 0;
diff --git a/src/newgrf_text.h b/src/newgrf_text.h
index 709f4dd24..bdd1f1bc9 100644
--- a/src/newgrf_text.h
+++ b/src/newgrf_text.h
@@ -14,26 +14,39 @@
#include "strings_type.h"
#include "core/smallvec_type.hpp"
#include "table/control_codes.h"
+#include <utility>
+#include <vector>
+#include <string>
/** This character, the thorn ('รพ'), indicates a unicode string to NFO. */
static const WChar NFO_UTF8_IDENTIFIER = 0x00DE;
+/** A GRF text with associated language ID. */
+struct GRFText {
+ byte langid; ///< The language associated with this GRFText.
+ std::string text; ///< The actual (translated) text.
+};
+
+/** A GRF text with a list of translations. */
+typedef std::vector<GRFText> GRFTextList;
+/** Reference counted wrapper around a GRFText pointer. */
+typedef std::shared_ptr<GRFTextList> GRFTextWrapper;
+
StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid, bool new_scheme, bool allow_newlines, const char *text_to_add, StringID def_string);
StringID GetGRFStringID(uint32 grfid, StringID stringid);
-const char *GetGRFStringFromGRFText(const struct GRFText *text);
+const char *GetGRFStringFromGRFText(const GRFTextList &text_list);
+const char *GetGRFStringFromGRFText(const GRFTextWrapper &text);
const char *GetGRFStringPtr(uint16 stringid);
void CleanUpStrings();
void SetCurrentGrfLangID(byte language_id);
char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const char *str, int *olen = nullptr, StringControlCode byte80 = SCC_NEWGRF_PRINT_WORD_STRING_ID);
-struct GRFText *DuplicateGRFText(struct GRFText *orig);
-void AddGRFTextToList(struct GRFText **list, struct GRFText *text_to_add);
-void AddGRFTextToList(struct GRFText **list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
-void AddGRFTextToList(struct GRFText **list, const char *text_to_add);
-void CleanUpGRFText(struct GRFText *grftext);
+void AddGRFTextToList(GRFTextList &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
+void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
+void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add);
bool CheckGrfLangID(byte lang_id, byte grf_version);
-void StartTextRefStackUsage(const GRFFile *grffile, byte numEntries, const uint32 *values = nullptr);
+void StartTextRefStackUsage(const struct GRFFile *grffile, byte numEntries, const uint32 *values = nullptr);
void StopTextRefStackUsage();
void RewindTextRefStack();
bool UsingNewGRFTextStack();