Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy2/src/core/Language.cc @ 2344

Last change on this file since 2344 was 2344, checked in by rgrieder, 15 years ago

Completed destruction of static elements like XMLPort, Identifier, etc.
Of initially about 250 memory leaks (not in the actual meaning but the memory was never freed anyway) only 1 remains in TinyCpp.

  • Core class is now a normal Singleton that gets created and destroyed in main.
  • The same goes for Language, LuaBind, SignalHandler and PlayerManager.
  • Added a new std::set to the CommandExecutor so that the external ConsoleCommands can get destroyed too.
  • Code for destroying CommandLineArguments
  • Added destruction code for ConstructionCallbacks in Identifier
  • Moved internal identifier map (the one with the typeid(.) names) in a static function in Identifier. This was necessary in order to destroy ALL Identifiers with the static destruction function. Before it was possible to create an Identifier with having a class instance (that would call RegisterObject) for instance by simply accessing it via getIdentifier.
  • Removed a big memory leak in Button (forgot to destroy the ConfigValueContainers)
  • Added destruction code for InputBufferListenerTuples in InputBuffer destructor.
  • Added destruction code for load and save executors in both XMLPortParam and XMLPortObject
  • Added destruction code for ConsoleCommands in GSRoot, GSGraphics and GSLevel (temporary solution anyway)
  • Deleting the CEGUILua script module seems to work properly now, one memory leak less (GUIManager.cc)
  • Added global destruction calls in Main.cc
  • Property svn:eol-style set to native
File size: 11.6 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @brief Implementation of the Language and the LanguageEntry classes.
32*/
33
34#include "Language.h"
35
36#include <fstream>
37
38#include "Core.h"
39#include "util/Debug.h"
40
41namespace orxonox
42{
43    // ###############################
44    // ###      LanguageEntry      ###
45    // ###############################
46    /**
47        @brief Constructor: Sets the default entry.
48        @param fallbackEntry The default entry
49    */
50    LanguageEntry::LanguageEntry(const std::string& fallbackEntry)
51    {
52        this->fallbackEntry_ = fallbackEntry;
53        this->localisedEntry_ = fallbackEntry; // Set the localisation to the fallback entry, for the case that no translation gets assigned
54        this->bLocalisationSet_ = false;
55    }
56
57    /**
58        @brief Sets the localisation of the entry.
59        @param localisation The localisation
60    */
61    void LanguageEntry::setLocalisation(const std::string& localisation)
62    {
63        // Check if the translation is more than just an empty string
64        if ((localisation != "") && (localisation.size() > 0))
65        {
66            this->localisedEntry_ = localisation;
67            this->bLocalisationSet_ = true;
68        }
69        else
70            this->localisedEntry_ = this->fallbackEntry_;
71    }
72
73    /**
74        @brief Sets the default entry.
75        @param fallbackEntry The default entry
76    */
77    void LanguageEntry::setDefault(const std::string& fallbackEntry)
78    {
79        // If the default entry changes and the translation wasn't set yet, use the new default entry as translation
80        if (!this->bLocalisationSet_)
81            this->localisedEntry_ = fallbackEntry;
82
83        this->fallbackEntry_ = fallbackEntry;
84    }
85
86    // ###############################
87    // ###        Language         ###
88    // ###############################
89
90    Language* Language::singletonRef_s = 0;
91
92    /**
93        @brief Constructor: Reads the default language file and sets some values.
94    */
95    Language::Language()
96    {
97        assert(singletonRef_s == 0);
98        singletonRef_s = this;
99
100        this->defaultLanguage_ = "default";
101        this->defaultLocalisation_ = "ERROR: LANGUAGE ENTRY DOESN'T EXIST!";
102
103        // Read the default language file to create all known LanguageEntry objects
104        this->readDefaultLanguageFile();
105    }
106
107    /**
108        @brief Destructor: Deletes all language entries.
109    */
110    Language::~Language()
111    {
112        for (std::map<std::string, LanguageEntry*>::iterator it = this->languageEntries_.begin(); it != this->languageEntries_.end(); ++it)
113            delete (it->second);
114
115        assert(singletonRef_s);
116        singletonRef_s = 0;
117    }
118
119    /**
120        @brief Creates a new LanguageEntry with a given label and a given default entry.
121        @param label The label of the entry
122        @param entry The default entry
123        @return The created LanguageEntry object
124    */
125    LanguageEntry* Language::createEntry(const LanguageEntryLabel& label, const std::string& entry)
126    {
127        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
128
129        // Make sure we don't create a duplicate entry
130        if (it == this->languageEntries_.end())
131        {
132            LanguageEntry* newEntry = new LanguageEntry(entry);
133            newEntry->setLabel(label);
134            this->languageEntries_[label] = newEntry;
135            return newEntry;
136        }
137
138        COUT(2) << "Warning: Language entry " << label << " is duplicate in " << getFilename(this->defaultLanguage_) << "!" << std::endl;
139        return it->second;
140    }
141
142    /**
143        @brief Adds a new LanguageEntry, if it's not already existing.
144        @param label The label of the entry
145        @param entry The default entry
146    */
147    void Language::addEntry(const LanguageEntryLabel& label, const std::string& entry)
148    {
149        COUT(5) << "Language: Called addEntry with\n  label: " << label << "\n  entry: " <<  entry << std::endl;
150        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
151        if (it == this->languageEntries_.end())
152        {
153            // The entry isn't available yet, meaning it's new, so create it
154            this->createEntry(label, entry);
155        }
156        else if (it->second->getDefault().compare(entry) == 0)
157        {
158            // The entry is available and the default string is the same, so return because everything is fine
159            return;
160        }
161        else
162        {
163            // The defined default entry is not the same as in the default language file - change it to the new entry
164            it->second->setDefault(entry);
165        }
166
167        // Write the default language file because either a new entry was created or an existing entry has changed
168        this->writeDefaultLanguageFile();
169
170    }
171
172    /**
173        @brief Returns the localisation of a given entry.
174        @param label The label of the entry
175        @return The localisation
176    */
177    const std::string& Language::getLocalisation(const LanguageEntryLabel& label) const
178    {
179        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
180        if (it != this->languageEntries_.end())
181            return it->second->getLocalisation();
182        else
183        {
184            // Uh, oh, an undefined entry was requested: return the default string
185            COUT(2) << "Warning: Language entry \"" << label << "\" not found!" << std::endl;
186            return this->defaultLocalisation_;
187        }
188    }
189
190    /**
191        @brief Creates the name of the language file out of the languages name.
192        @param language The name of the language
193        @return The filename
194    */
195    const std::string Language::getFilename(const std::string& language)
196    {
197        return std::string("translation_" + language + ".lang");
198    }
199
200    /**
201        @brief Reads the default language file and creates a LanguageEntry objects for every entry.
202    */
203    void Language::readDefaultLanguageFile()
204    {
205        COUT(4) << "Read default language file." << std::endl;
206
207        // This creates the file if it's not existing
208        std::ofstream createFile;
209        createFile.open(getFilename(this->defaultLanguage_).c_str(), std::fstream::app);
210        createFile.close();
211
212        // Open the file
213        std::ifstream file;
214        file.open(getFilename(this->defaultLanguage_).c_str(), std::fstream::in);
215
216        if (!file.is_open())
217        {
218            COUT(1) << "An error occurred in Language.cc:" << std::endl;
219            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to read the default language entries!" << std::endl;
220            return;
221        }
222
223        char line[1024];
224
225        // Iterate through the file and create the LanguageEntries
226        while (file.good() && !file.eof())
227        {
228            file.getline(line, 1024);
229            std::string lineString = std::string(line);
230
231            // Check if the line is empty
232            if ((lineString != "") && (lineString.size() > 0))
233            {
234                unsigned int pos = lineString.find('=');
235
236                // Check if the length is at least 3 and if there's an entry before and behind the =
237                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
238                    this->createEntry(lineString.substr(0, pos), lineString.substr(pos + 1));
239                else
240                {
241                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(this->defaultLanguage_) << std::endl;
242                }
243            }
244        }
245
246        file.close();
247    }
248
249    /**
250        @brief Reads the language file of the configured language and assigns the localisation to the corresponding LanguageEntry object.
251    */
252    void Language::readTranslatedLanguageFile()
253    {
254        COUT(4) << "Read translated language file (" << Core::getLanguage() << ")." << std::endl;
255
256        // Open the file
257        std::ifstream file;
258        file.open(getFilename(Core::getLanguage()).c_str(), std::fstream::in);
259
260        if (!file.is_open())
261        {
262            COUT(1) << "An error occurred in Language.cc:" << std::endl;
263            COUT(1) << "Error: Couldn't open file " << getFilename(Core::getLanguage()) << " to read the translated language entries!" << std::endl;
264            Core::resetLanguage();
265            COUT(3) << "Info: Reset language to " << this->defaultLanguage_ << "." << std::endl;
266            return;
267        }
268
269        char line[1024];
270
271        // Iterate through the file and create the LanguageEntries
272        while (file.good() && !file.eof())
273        {
274            file.getline(line, 1024);
275            std::string lineString = std::string(line);
276
277            // Check if the line is empty
278            if ((lineString != "") && (lineString.size() > 0))
279            {
280                unsigned int pos = lineString.find('=');
281
282                // Check if the length is at least 3 and if there's an entry before and behind the =
283                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
284                {
285                    std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(lineString.substr(0, pos));
286
287                    // Check if the entry exists
288                    if (it != this->languageEntries_.end())
289                        it->second->setLocalisation(lineString.substr(pos + 1));
290                    else
291                        this->createEntry(lineString.substr(0, pos), this->defaultLocalisation_)->setLocalisation(lineString.substr(pos + 1));
292                }
293                else
294                {
295                    COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(Core::getLanguage()) << std::endl;
296                }
297            }
298        }
299
300        file.close();
301    }
302
303    /**
304        @brief Writes all default entries to the default language file.
305    */
306    void Language::writeDefaultLanguageFile() const
307    {
308        COUT(4) << "Language: Write default language file." << std::endl;
309
310        // Open the file
311        std::ofstream file;
312        file.open(getFilename(this->defaultLanguage_).c_str(), std::fstream::out);
313
314        if (!file.is_open())
315        {
316            COUT(1) << "An error occurred in Language.cc:" << std::endl;
317            COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to write the default language entries!" << std::endl;
318            return;
319        }
320
321        // Iterate through the list an write the lines into the file
322        for (std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.begin(); it != this->languageEntries_.end(); ++it)
323        {
324            file << (*it).second->getLabel() << "=" << (*it).second->getDefault() << std::endl;
325        }
326
327        file.close();
328    }
329}
Note: See TracBrowser for help on using the repository browser.