Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/releasetodo/src/libraries/core/Loader.cc @ 7628

Last change on this file since 7628 was 7628, checked in by dafrick, 14 years ago

Adjusting include paths of CEGUIListbox and CEGUILisbtoxItem.
Added verbose parameter to the load and reload methods of the Loader, to be able to supress (i.e. shift the output level) the output, when convenient.
Suppressing the output, when loading all levels to extract the LevelInfo.

  • Property svn:eol-style set to native
File size: 12.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#include "Loader.h"
30
31#include <sstream>
32#include <tinyxml/ticpp.h>
33#include <boost/scoped_ptr.hpp>
34
35#include "util/Debug.h"
36#include "util/Exception.h"
37#include "util/StringUtils.h"
38#include "BaseObject.h"
39#include "Iterator.h"
40#include "ObjectList.h"
41#include "LuaState.h"
42#include "Namespace.h"
43#include "Resource.h"
44#include "XMLFile.h"
45
46namespace orxonox
47{
48    std::vector<std::pair<const XMLFile*, ClassTreeMask> > Loader::files_s;
49    ClassTreeMask Loader::currentMask_s;
50
51    bool Loader::open(const XMLFile* file, const ClassTreeMask& mask)
52    {
53        Loader::add(file, mask);
54        return Loader::load(file, mask);
55    }
56
57    void Loader::close()
58    {
59        Loader::unload();
60        Loader::files_s.clear();
61    }
62
63    void Loader::close(const XMLFile* file)
64    {
65        Loader::unload(file);
66        Loader::remove(file);
67    }
68
69    void Loader::add(const XMLFile* file, const ClassTreeMask& mask)
70    {
71        if (!file)
72            return;
73        Loader::files_s.insert(Loader::files_s.end(), std::pair<const XMLFile*, ClassTreeMask>(file, mask));
74    }
75
76    void Loader::remove(const XMLFile* file)
77    {
78        if (!file)
79            return;
80        for (std::vector<std::pair<const XMLFile*, ClassTreeMask> >::iterator it = Loader::files_s.begin(); it != Loader::files_s.end(); ++it)
81        {
82            if (it->first == file)
83            {
84                Loader::files_s.erase(it);
85                break;
86            }
87        }
88    }
89
90    bool Loader::load(const ClassTreeMask& mask, bool verbose)
91    {
92        bool success = true;
93        for (std::vector<std::pair<const XMLFile*, ClassTreeMask> >::iterator it = Loader::files_s.begin(); it != Loader::files_s.end(); ++it)
94            if (!Loader::load(it->first, it->second * mask, verbose))
95                success = false;
96
97        return success;
98    }
99
100    void Loader::unload(const ClassTreeMask& mask)
101    {
102        for (ObjectList<BaseObject>::iterator it = ObjectList<BaseObject>::begin(); it != ObjectList<BaseObject>::end(); )
103        {
104            if (mask.isIncluded(it->getIdentifier()))
105                (it++)->destroy();
106            else
107                ++it;
108        }
109    }
110
111    bool Loader::reload(const ClassTreeMask& mask, bool verbose)
112    {
113        Loader::unload(mask);
114        return Loader::load(mask, verbose);
115    }
116
117    bool Loader::load(const XMLFile* file, const ClassTreeMask& mask, bool verbose)
118    {
119        if (!file)
120            return false;
121
122        Loader::currentMask_s = file->getMask() * mask;
123
124        std::string xmlInput;
125        if (file->getLuaSupport())
126        {
127            // Use the LuaState to replace the XML tags (calls our function)
128            scoped_ptr<LuaState> luaState(new LuaState());
129            luaState->setIncludeParser(&Loader::replaceLuaTags);
130            luaState->includeFile(file->getFilename());
131            xmlInput = luaState->getOutput().str();
132        }
133        else
134        {
135            shared_ptr<ResourceInfo> info = Resource::getInfo(file->getFilename());
136            if (info == NULL)
137            {
138                COUT(1) << "Error: Could not find XML file '" << file->getFilename() << "'." << std::endl;
139                return false;
140            }
141            xmlInput = Resource::open(file->getFilename())->getAsString();
142        }
143
144        try
145        {
146            if(verbose)
147            {
148                COUT(0) << "Start loading " << file->getFilename() << "..." << std::endl;
149                COUT(3) << "Mask: " << Loader::currentMask_s << std::endl;
150            }
151            else
152            {
153                COUT(4) << "Start loading " << file->getFilename() << "..." << std::endl;
154                COUT(4) << "Mask: " << Loader::currentMask_s << std::endl;
155            }
156
157            ticpp::Document xmlfile(file->getFilename());
158            xmlfile.Parse(xmlInput, true);
159
160            ticpp::Element rootElement;
161            rootElement.SetAttribute("name", "root");
162            rootElement.SetAttribute("bAutogenerated", true);
163
164            for (ticpp::Iterator<ticpp::Element> child = xmlfile.FirstChildElement(false); child != child.end(); child++)
165                rootElement.InsertEndChild(*child);
166
167            COUT(4) << "  creating root-namespace..." << std::endl;
168            Namespace* rootNamespace = new Namespace(0);
169            rootNamespace->setLoaderIndentation("    ");
170            rootNamespace->setFile(file);
171            rootNamespace->setNamespace(rootNamespace);
172            rootNamespace->setRoot(true);
173            rootNamespace->XMLPort(rootElement, XMLPort::LoadObject);
174
175            if(verbose)
176                COUT(0) << "Finished loading " << file->getFilename() << '.' << std::endl;
177            else
178                COUT(4) << "Finished loading " << file->getFilename() << '.' << std::endl;
179
180            COUT(4) << "Namespace-tree:" << std::endl << rootNamespace->toString("  ") << std::endl;
181
182            return true;
183        }
184        catch (ticpp::Exception& ex)
185        {
186            COUT(1) << std::endl;
187            COUT(1) << "An XML-error occurred in Loader.cc while loading " << file->getFilename() << ':' << std::endl;
188            COUT(1) << ex.what() << std::endl;
189            COUT(1) << "Loading aborted." << std::endl;
190            return false;
191        }
192        catch (Exception& ex)
193        {
194            COUT(1) << std::endl;
195            COUT(1) << "A loading-error occurred in Loader.cc while loading " << file->getFilename() << ':' << std::endl;
196            COUT(1) << ex.what() << std::endl;
197            COUT(1) << "Loading aborted." << std::endl;
198            return false;
199        }
200        catch (...)
201        {
202            COUT(1) << std::endl;
203            COUT(1) << "An error occurred in Loader.cc while loading " << file->getFilename() << ':' << std::endl;
204            COUT(1) << Exception::handleMessage() << std::endl;
205            COUT(1) << "Loading aborted." << std::endl;
206            return false;
207        }
208    }
209
210    void Loader::unload(const XMLFile* file, const ClassTreeMask& mask)
211    {
212        if (!file)
213            return;
214        for (ObjectList<BaseObject>::iterator it = ObjectList<BaseObject>::begin(); it; )
215        {
216            if ((it->getFile() == file) && mask.isIncluded(it->getIdentifier()))
217                (it++)->destroy();
218            else
219                ++it;
220        }
221    }
222
223    bool Loader::reload(const XMLFile* file, const ClassTreeMask& mask, bool verbose)
224    {
225        Loader::unload(file, mask);
226        return Loader::load(file, mask, verbose);
227    }
228
229    std::string Loader::replaceLuaTags(const std::string& text)
230    {
231        // create map with all Lua tags
232        std::map<size_t, bool> luaTags;
233        {
234            size_t pos = 0;
235            while ((pos = text.find("<?lua", pos)) != std::string::npos)
236                luaTags[pos++] = true;
237        }
238        {
239            size_t pos = 0;
240            while ((pos = text.find("?>", pos)) != std::string::npos)
241                luaTags[pos++] = false;
242        }
243
244        // erase all tags from the map that are between two quotes
245        {
246            std::map<size_t, bool>::iterator it = luaTags.begin();
247            std::map<size_t, bool>::iterator it2 = it;
248            bool bBetweenQuotes = false;
249            size_t pos = 0;
250            while ((pos = getNextQuote(text, pos)) != std::string::npos)
251            {
252                while ((it != luaTags.end()) && (it->first < pos))
253                {
254                    if (bBetweenQuotes)
255                    {
256                        it2++;
257                        if (it->second && !(it2->second) && it2->first < pos)
258                            it = ++it2;
259                        else
260                            luaTags.erase(it++);
261                    }
262                    else
263                        ++it;
264                }
265                bBetweenQuotes = !bBetweenQuotes;
266                pos++;
267            }
268        }
269
270        // check whether on every opening <?lua tag a closing ?> tag follows
271        {
272            bool expectedValue = true;
273            for (std::map<size_t, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
274            {
275                if (it->second == expectedValue)
276                    expectedValue = !expectedValue;
277                else
278                {
279                    expectedValue = false;
280                    break;
281                }
282            }
283            if (!expectedValue)
284            {
285                COUT(2) << "Warning: Error in level file" << std::endl;
286                // todo: errorhandling
287                return "";
288            }
289        }
290
291        // Use a stringstream object to speed up the parsing
292        std::ostringstream output;
293
294        // cut the original string into pieces and put them together with print() instead of lua tags
295        {
296            std::map<size_t, bool>::iterator it = luaTags.begin();
297            bool bInPrintFunction = true;
298            size_t start = 0;
299            size_t end = 0;
300
301            do
302            {
303                if (it != luaTags.end())
304                    end = (it++)->first;
305                else
306                    end = std::string::npos;
307
308                unsigned int equalSignCounter = 0;
309
310                if (bInPrintFunction)
311                {
312                    // count ['='[ and ]'='] and replace tags with print([[ and ]])
313                    const std::string& temp = text.substr(start, end - start);
314                    {
315                    size_t pos = 0;
316                    while ((pos = temp.find('[', pos)) != std::string::npos)
317                    {
318                        unsigned int tempCounter = 1;
319                        size_t tempPos = pos++;
320                        while (temp[++tempPos] == '=')
321                        {
322                            tempCounter++;
323                        }
324                        if (temp[tempPos] != '[')
325                        {
326                            tempCounter = 0;
327                        }
328                        else if (tempCounter == 0)
329                        {
330                            tempCounter = 1;
331                        }
332                        if (tempCounter > equalSignCounter)
333                            equalSignCounter = tempCounter;
334                        }
335                    }
336                    {
337                        size_t pos = 0;
338                        while ((pos = temp.find(']', pos)) != std::string::npos)
339                        {
340                            unsigned int tempCounter = 1;
341                            size_t tempPos = pos++;
342                            while (temp[++tempPos] == '=')
343                            {
344                                tempCounter++;
345                            }
346                            if (temp[tempPos] != ']')
347                            {
348                                tempCounter = 0;
349                            }
350                            else if (tempCounter == 0)
351                            {
352                                tempCounter = 1;
353                            }
354                            if (tempCounter > equalSignCounter)
355                                equalSignCounter = tempCounter;
356                        }
357                    }
358                    std::string equalSigns;
359                    for (unsigned int i = 0; i < equalSignCounter; i++)
360                    {
361                        equalSigns += '=';
362                    }
363                    output << "print([" + equalSigns + '[' + temp + ']' + equalSigns +"])";
364                    start = end + 5;
365                }
366                else
367                {
368                    output << text.substr(start, end - start);
369                    start = end + 2;
370                }
371
372                bInPrintFunction = !bInPrintFunction;
373            }
374            while (end != std::string::npos);
375        }
376
377        return output.str();
378    }
379}
Note: See TracBrowser for help on using the repository browser.