changeset 16444:40e6de30e665 draft

(svn r21160) -Codechange: reuse the strgen LanguageHeader to store some metadata about a language, and keep the language metadata in memory instead of loading it several times from disk
author rubidium <rubidium@openttd.org>
date Sat, 13 Nov 2010 11:11:02 +0000
parents 541565c52d7e
children c7c3bb467609
files projects/openttd_vs100.vcxproj projects/openttd_vs100.vcxproj.filters projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/language.h src/strgen/strgen.cpp src/strgen/strgen.h src/strings.cpp src/strings_type.h
diffstat 10 files changed, 91 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs100.vcxproj
+++ b/projects/openttd_vs100.vcxproj
@@ -453,6 +453,7 @@
     <ClInclude Include="..\src\ini_type.h" />
     <ClInclude Include="..\src\landscape.h" />
     <ClInclude Include="..\src\landscape_type.h" />
+    <ClInclude Include="..\src\language.h" />
     <ClInclude Include="..\src\livery.h" />
     <ClInclude Include="..\src\map_func.h" />
     <ClInclude Include="..\src\map_type.h" />
@@ -551,7 +552,6 @@
     <ClInclude Include="..\src\station_type.h" />
     <ClInclude Include="..\src\statusbar_gui.h" />
     <ClInclude Include="..\src\stdafx.h" />
-    <ClInclude Include="..\src\strgen\strgen.h" />
     <ClInclude Include="..\src\string_func.h" />
     <ClInclude Include="..\src\string_type.h" />
     <ClInclude Include="..\src\strings_func.h" />
--- a/projects/openttd_vs100.vcxproj.filters
+++ b/projects/openttd_vs100.vcxproj.filters
@@ -579,6 +579,9 @@
     <ClInclude Include="..\src\landscape_type.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\src\language.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\livery.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -873,9 +876,6 @@
     <ClInclude Include="..\src\stdafx.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\strgen\strgen.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\src\string_func.h">
       <Filter>Header Files</Filter>
     </ClInclude>
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1087,6 +1087,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\language.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\livery.h"
 				>
 			</File>
@@ -1479,10 +1483,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\strgen\strgen.h"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\string_func.h"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -1084,6 +1084,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\language.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\livery.h"
 				>
 			</File>
@@ -1476,10 +1480,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\strgen\strgen.h"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\string_func.h"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -186,6 +186,7 @@
 ini_type.h
 landscape.h
 landscape_type.h
+language.h
 livery.h
 map_func.h
 map_type.h
@@ -284,7 +285,6 @@
 station_type.h
 statusbar_gui.h
 stdafx.h
-strgen/strgen.h
 string_func.h
 string_type.h
 strings_func.h
new file mode 100644
--- /dev/null
+++ b/src/language.h
@@ -0,0 +1,59 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file language.h Information about languages and their files. */
+
+#ifndef LANGUAGE_H
+#define LANGUAGE_H
+
+/** Header of a language file. */
+struct LanguagePackHeader {
+	static const uint32 IDENT = 0x474E414C; ///< Identifier for OpenTTD language files, big endian for "LANG"
+
+	uint32 ident;       ///< 32-bits identifier
+	uint32 version;     ///< 32-bits of auto generated version info which is basically a hash of strings.h
+	char name[32];      ///< the international name of this language
+	char own_name[32];  ///< the localized name of this language
+	char isocode[16];   ///< the ISO code for the language (not country code)
+	uint16 offsets[32]; ///< the offsets
+
+	/** Thousand separator used for anything not currencies */
+	char digit_group_separator[8];
+	/** Thousand separator used for currencies */
+	char digit_group_separator_currency[8];
+	/** Decimal separator */
+	char digit_decimal_separator[8];
+	byte plural_form;   ///< plural form index
+	byte text_dir;      ///< default direction of the text
+	/**
+	 * Windows language ID:
+	 * Windows cannot and will not convert isocodes to something it can use to
+	 * determine whether a font can be used for the language or not. As a result
+	 * of that we need to pass the language id via strgen to OpenTTD to tell
+	 * what language it is in "Windows". The ID is the 'locale identifier' on:
+	 *   http://msdn.microsoft.com/en-us/library/ms776294.aspx
+	 */
+	uint16 winlangid;   ///< windows language id
+	uint8 newgrflangid; ///< newgrf language id
+	byte pad[3];        ///< pad header to be a multiple of 4
+
+	/**
+	 * Check whether the header is a valid header for OpenTTD.
+	 * @return true iff the header is deemed valid.
+	 */
+	bool IsValid() const;
+};
+assert_compile(sizeof(LanguagePackHeader) % 4 == 0);
+
+/** Metadata about a single language. */
+struct LanguageMetadata : public LanguagePackHeader {
+	char file[MAX_PATH]; ///< Name of the file we read this data from.
+};
+
+#endif /* LANGUAGE_H */
--- a/src/strgen/strgen.cpp
+++ b/src/strgen/strgen.cpp
@@ -16,7 +16,7 @@
 #include "../core/mem_func.hpp"
 #include "../string_func.h"
 #include "../strings_type.h"
-#include "strgen.h"
+#include "../language.h"
 #include "../table/control_codes.h"
 
 #include <stdarg.h>
deleted file mode 100644
--- a/src/strgen/strgen.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id$ */
-
-/*
- * This file is part of OpenTTD.
- * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
- * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/** @file strgen.h Language pack header for strgen (needs to match). */
-
-#ifndef STRGEN_H
-#define STRGEN_H
-
-/** Header of a language file. */
-struct LanguagePackHeader {
-	static const uint32 IDENT = 0x474E414C; ///< Identifier for OpenTTD language files, big endian for "LANG"
-
-	uint32 ident;       ///< 32-bits identifier
-	uint32 version;     ///< 32-bits of auto generated version info which is basically a hash of strings.h
-	char name[32];      ///< the international name of this language
-	char own_name[32];  ///< the localized name of this language
-	char isocode[16];   ///< the ISO code for the language (not country code)
-	uint16 offsets[32]; ///< the offsets
-
-	/** Thousand separator used for anything not currencies */
-	char digit_group_separator[8];
-	/** Thousand separator used for currencies */
-	char digit_group_separator_currency[8];
-	/** Decimal separator */
-	char digit_decimal_separator[8];
-	byte plural_form;   ///< plural form index
-	byte text_dir;      ///< default direction of the text
-	/**
-	 * Windows language ID:
-	 * Windows cannot and will not convert isocodes to something it can use to
-	 * determine whether a font can be used for the language or not. As a result
-	 * of that we need to pass the language id via strgen to OpenTTD to tell
-	 * what language it is in "Windows". The ID is the 'locale identifier' on:
-	 *   http://msdn.microsoft.com/en-us/library/ms776294.aspx
-	 */
-	uint16 winlangid;   ///< windows language id
-	uint8 newgrflangid; ///< newgrf language id
-	byte pad[3];        ///< pad header to be a multiple of 4
-
-	/**
-	 * Check whether the header is a valid header for OpenTTD.
-	 * @return true iff the header is deemed valid.
-	 */
-	bool IsValid() const;
-};
-
-assert_compile(sizeof(LanguagePackHeader) % 4 == 0);
-
-#endif /* STRGEN_H */
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -30,7 +30,7 @@
 #include "date_func.h"
 #include "vehicle_base.h"
 #include "engine_base.h"
-#include "strgen/strgen.h"
+#include "language.h"
 #include "townname_func.h"
 #include "string_func.h"
 #include "company_base.h"
@@ -1439,12 +1439,12 @@
 
 /**
  * Checks whether the given language is already found.
- * @param langs    languages we've found so fa
+ * @param langs    languages we've found so far
  * @param max      the length of the language list
  * @param language name of the language to check
  * @return true if and only if a language file with the same name has not been found
  */
-static bool UniqueLanguageFile(const Language *langs, uint max, const char *language)
+static bool UniqueLanguageFile(const LanguageMetadata *langs, uint max, const char *language)
 {
 	for (uint i = 0; i < max; i++) {
 		const char *f_name = strrchr(langs[i].file, PATHSEPCHAR) + 1;
@@ -1460,7 +1460,7 @@
  * @param hdr  the place to write the header information to
  * @return true if and only if the language file is of a compatible version
  */
-static bool GetLanguageFileHeader(const char *file, LanguagePack *hdr)
+static bool GetLanguageFileHeader(const char *file, LanguagePackHeader *hdr)
 {
 	FILE *f = fopen(file, "rb");
 	if (f == NULL) return false;
@@ -1483,7 +1483,7 @@
  * @param path  the base directory to search in
  * @return the number of added languages
  */
-static int GetLanguageList(Language *langs, int start, int max, const char *path)
+static int GetLanguageList(LanguageMetadata *langs, int start, int max, const char *path)
 {
 	int i = start;
 
@@ -1500,13 +1500,11 @@
 			/* Filter any duplicate language-files, first-come first-serve */
 			if (!UniqueLanguageFile(langs, i, d_name)) continue;
 
-			langs[i].file = str_fmt("%s%s", path, d_name);
+			seprintf(langs[i].file, lastof(langs[i].file), "%s%s", path, d_name);
 
 			/* Check whether the file is of the correct version */
-			LanguagePack hdr;
-			if (!GetLanguageFileHeader(langs[i].file, &hdr)) {
+			if (!GetLanguageFileHeader(langs[i].file, &langs[i])) {
 				DEBUG(misc, 3, "%s is not a valid language file", langs[i].file);
-				free(langs[i].file);
 				continue;
 			}
 
@@ -1524,13 +1522,12 @@
 void InitializeLanguagePacks()
 {
 	Searchpath sp;
-	Language files[MAX_LANG];
 	uint language_count = 0;
 
 	FOR_ALL_SEARCHPATHS(sp) {
 		char path[MAX_PATH];
 		FioAppendDirectory(path, lengthof(path), sp, LANG_DIR);
-		language_count += GetLanguageList(files, language_count, lengthof(files), path);
+		language_count += GetLanguageList(_dynlang.ent, language_count, lengthof(_dynlang.ent), path);
 	}
 	if (language_count == 0) usererror("No available language packs (invalid versions?)");
 
@@ -1542,41 +1539,29 @@
 	int language_fallback = -1; ///< Using pt_PT for pt_BR locale when pt_BR is not available
 	int en_GB_fallback    =  0; ///< Fallback when no locale-matching language has been found
 
-	DynamicLanguages *dl = &_dynlang;
-	dl->num = 0;
+	_dynlang.num = language_count;
 	/* Fill the dynamic languages structures */
 	for (uint i = 0; i < language_count; i++) {
-		/* File read the language header */
-		LanguagePack hdr;
-		if (!GetLanguageFileHeader(files[i].file, &hdr)) continue;
-
-		dl->ent[dl->num].file = files[i].file;
-		dl->ent[dl->num].name = strdup(hdr.name);
-
 		/* We are trying to find a default language. The priority is by
 		 * configuration file, local environment and last, if nothing found,
 		 * english. If def equals -1, we have not picked a default language */
-		const char *lang_file = strrchr(dl->ent[dl->num].file, PATHSEPCHAR) + 1;
-		if (strcmp(lang_file, dl->curr_file) == 0) chosen_language = dl->num;
+		const char *lang_file = strrchr(_dynlang.ent[i].file, PATHSEPCHAR) + 1;
+		if (strcmp(lang_file, _dynlang.curr_file) == 0) chosen_language = i;
 
 		if (chosen_language == -1) {
-			if (strcmp (hdr.isocode, "en_GB") == 0) en_GB_fallback    = dl->num;
-			if (strncmp(hdr.isocode, lang, 5) == 0) chosen_language   = dl->num;
-			if (strncmp(hdr.isocode, lang, 2) == 0) language_fallback = dl->num;
+			if (strcmp (_dynlang.ent[i].isocode, "en_GB") == 0) en_GB_fallback    = i;
+			if (strncmp(_dynlang.ent[i].isocode, lang, 5) == 0) chosen_language   = i;
+			if (strncmp(_dynlang.ent[i].isocode, lang, 2) == 0) language_fallback = i;
 		}
-
-		dl->num++;
 	}
 
-	if (dl->num == 0) usererror("Invalid version of language packs");
-
 	/* We haven't found the language in the config nor the one in the locale.
 	 * Now we set it to one of the fallback languages */
 	if (chosen_language == -1) {
 		chosen_language = (language_fallback != -1) ? language_fallback : en_GB_fallback;
 	}
 
-	if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", dl->ent[chosen_language].file);
+	if (!ReadLanguagePack(chosen_language)) usererror("Can't read language pack '%s'", _dynlang.ent[chosen_language].file);
 }
 
 /**
--- a/src/strings_type.h
+++ b/src/strings_type.h
@@ -12,6 +12,8 @@
 #ifndef STRINGS_TYPE_H
 #define STRINGS_TYPE_H
 
+#include "language.h"
+
 /**
  * Numeric value that represents a string, independent of the selected language.
  */
@@ -26,18 +28,12 @@
 	TD_RTL, ///< Text is written right-to-left by default
 };
 
-/** Information about a language */
-struct Language {
-	char *name; ///< The internal name of the language
-	char *file; ///< The name of the language as it appears on disk
-};
-
 /** Used for dynamic language support */
 struct DynamicLanguages {
 	int num;                  ///< Number of languages
 	int curr;                 ///< Currently selected language index
 	char curr_file[MAX_PATH]; ///< Currently selected language file name without path (needed for saving the filename of the loaded language).
-	Language ent[MAX_LANG];   ///< Information about the languages
+	LanguageMetadata ent[MAX_LANG]; ///< Information about the languages
 };
 
 /** Special string constants */