changeset 16478:b0d4949e2996 draft

(svn r21202) -Codechange: allow strings with embedded '\0' in GRFText.
author rubidium <rubidium@openttd.org>
date Tue, 16 Nov 2010 11:34:19 +0000
parents 51073f01788c
children cf48dafca908
files src/newgrf_text.cpp src/newgrf_text.h
diffstat 2 files changed, 27 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf_text.cpp
+++ b/src/newgrf_text.cpp
@@ -123,12 +123,17 @@
 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)
+	static GRFText *New(byte langid, const char *text, int len)
 	{
-		return new (strlen(text) + 1) GRFText(langid, text);
+		return new (len) GRFText(langid, text, len);
 	}
 
 	/**
@@ -138,7 +143,7 @@
 	 */
 	static GRFText *Copy(GRFText *orig)
 	{
-		return GRFText::New(orig->langid, orig->text);
+		return GRFText::New(orig->langid, orig->text, orig->len);
 	}
 
 	/**
@@ -164,10 +169,14 @@
 	 * 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_) : next(NULL), langid(langid_)
+	GRFText(byte langid_, const char *text_, int len_) : next(NULL), len(len_), langid(langid_)
 	{
-		strcpy(text, text_);
+		/* We need to use memcpy instead of strcpy due to
+		 * the possibility of "choice lists" and therefor
+		 * intermediate string terminators. */
+		memcpy(this->text, text_, len);
 	}
 
 	/**
@@ -183,6 +192,7 @@
 
 public:
 	GRFText *next; ///< The next GRFText in this chain.
+	int len;       ///< The length of the stored string, used for copying.
 	byte langid;   ///< The language associated with this GRFText.
 	char text[];   ///< The actual (translated) text.
 };
@@ -211,9 +221,10 @@
  * @param grfid       The (NewGRF) ID associated with this string
  * @param language_id The (NewGRF) language ID associated with this string.
  * @param str         The string to translate.
+ * @param [out] olen  The length of the final string.
  * @return The translated string.
  */
-char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, const char *str)
+char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, const char *str, int *olen)
 {
 	char *tmp = MallocT<char>(strlen(str) * 10 + 1); // Allocate space to allow for expansion
 	char *d = tmp;
@@ -360,7 +371,8 @@
 	}
 
 	*d = '\0';
-	tmp = ReallocT(tmp, strlen(tmp) + 1);
+	if (olen != NULL) *olen = d - tmp + 1;
+	tmp = ReallocT(tmp, d - tmp + 1);
 	return tmp;
 }
 
@@ -397,8 +409,9 @@
  */
 void AddGRFTextToList(struct GRFText **list, byte langid, uint32 grfid, const char *text_to_add)
 {
-	char *translatedtext = TranslateTTDPatchCodes(grfid, langid, text_to_add);
-	GRFText *newtext = GRFText::New(langid, translatedtext);
+	int len;
+	char *translatedtext = TranslateTTDPatchCodes(grfid, langid, text_to_add, &len);
+	GRFText *newtext = GRFText::New(langid, translatedtext, len);
 	free(translatedtext);
 
 	AddGRFTextToList(list, newtext);
@@ -412,7 +425,7 @@
  */
 void AddGRFTextToList(struct GRFText **list, const char *text_to_add)
 {
-	AddGRFTextToList(list, GRFText::New(0x7F, text_to_add));
+	AddGRFTextToList(list, GRFText::New(0x7F, text_to_add, strlen(text_to_add) + 1));
 }
 
 /**
@@ -466,9 +479,10 @@
 	/* Too many strings allocated, return empty */
 	if (id == lengthof(_grf_text)) return STR_EMPTY;
 
-	translatedtext = TranslateTTDPatchCodes(grfid, langid_to_add, text_to_add);
+	int len;
+	translatedtext = TranslateTTDPatchCodes(grfid, langid_to_add, text_to_add, &len);
 
-	GRFText *newtext = GRFText::New(langid_to_add, translatedtext);
+	GRFText *newtext = GRFText::New(langid_to_add, translatedtext, len);
 
 	free(translatedtext);
 
--- a/src/newgrf_text.h
+++ b/src/newgrf_text.h
@@ -20,7 +20,7 @@
 const char *GetGRFStringPtr(uint16 stringid);
 void CleanUpStrings();
 void SetCurrentGrfLangID(byte language_id);
-char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, const char *str);
+char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, const char *str, int *olen = NULL);
 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, const char *text_to_add);