Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core4/src/core/LuaBind.cc @ 3673

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

Executing decision on #300: Renaming String.h to StringUtils.h (String.h doesn't exactly suggest you would find utilities for string manipulations there).

  • Property svn:eol-style set to native
File size: 8.3 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 *      Benjamin Knecht
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "LuaBind.h"
30
31#include <fstream>
32#include <map>
33extern "C" {
34#include <lualib.h>
35}
36#include <tolua/tolua++.h>
37#include <boost/filesystem.hpp>
38
39#include "util/Debug.h"
40#include "util/StringUtils.h"
41#include "ToluaBindCore.h"
42#include "Core.h"
43
44namespace orxonox
45{
46  LuaBind* LuaBind::singletonRef_s = NULL;
47
48  LuaBind::LuaBind()
49  {
50    assert(LuaBind::singletonRef_s == 0);
51    LuaBind::singletonRef_s = this;
52
53    this->includePath_ = Core::getMediaPathString();
54
55    luaState_ = lua_open();
56    luaSource_ = "";
57#if LUA_VERSION_NUM == 501
58    luaL_openlibs(luaState_);
59#else
60    luaopen_base(luaState_);
61    luaopen_string(luaState_);
62    luaopen_table(luaState_);
63    luaopen_math(luaState_);
64    luaopen_io(luaState_);
65    luaopen_debug(luaState_);
66#endif
67    tolua_Core_open(luaState_);
68    output_ = "";
69    isRunning_ = false;
70  }
71
72  void LuaBind::luaPrint(const std::string& str)
73  {
74    output_ += str;
75//    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
76    COUT(5) << str;
77  }
78
79  /**
80      @brief Loads the specified file line by line
81      @param filename The filename of the file
82      @param luaTags if true, the loaded file gets stripped off luaTags
83  */
84  void LuaBind::loadFile(const std::string& filename, bool luaTags)
85  {
86    boost::filesystem::path filepath(filename);
87
88    output_ = "";
89    std::ifstream file;
90    file.open(filepath.string().c_str(), std::fstream::in);
91
92    if (!file.is_open())
93    {
94      // some error msg
95    }
96
97    std::string levelString = "";
98
99    while (file.good() && !file.eof())
100    {
101      std::string line;
102      std::getline(file, line);
103      levelString += line;
104      levelString += "\n";
105    }
106
107    file.close();
108    //std::string output;
109
110    if (luaTags)
111      luaSource_ = replaceLuaTags(levelString);
112    else
113      luaSource_ = levelString;
114    COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
115  }
116
117  void LuaBind::loadString(const std::string& code)
118  {
119    luaSource_ = code;
120    output_ = "";
121  }
122
123#if LUA_VERSION_NUM != 501
124  const char * LuaBind::lua_Chunkreader(lua_State *L, void *data, size_t *size)
125  {
126    LoadS* ls = ((LoadS*)data);
127    if (ls->size == 0) return NULL;
128    *size = ls->size;
129    ls->size = 0;
130    return ls->s;
131  }
132#endif
133  void LuaBind::run()
134  {
135    if (!isRunning_)
136    {
137      isRunning_ = true;
138      int error = 0;
139      std::string init =
140         "local scr = orxonox.LuaBind:getInstance()\n \
141          local debug = print\n \
142          print = function(s)\n \
143              scr:luaPrint(s)\n \
144          end\n \
145          include = function(f)\n \
146              file = assert(io.open(\"" + this->includePath_ + "\"..\"/\"..f))\n \
147              content = file:read(\"*a\")\n \
148              file:close()\n \
149              source = scr:replaceLuaTags(content)\n \
150              assert(loadstring(source))()\n \
151          end\n";
152      init += luaSource_;
153  #if LUA_VERSION_NUM == 501
154      error = luaL_loadstring(luaState_, init.c_str());
155  #else
156      LoadS ls;
157      ls.s = init.c_str();
158      ls.size = init.size();
159      error = lua_load(luaState_, &orxonox::LuaBind::lua_Chunkreader, &ls, init.c_str());
160  #endif
161      if (error == 0)
162      {
163        error = lua_pcall(luaState_, 0, 0, 0);
164      }
165      if (error != 0)
166      {
167        COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
168      }
169      isRunning_ = false;
170    }
171    else
172    {
173      COUT(2) << "Warning: Lua's run is called while running!" << std::endl;
174    }
175  }
176
177  std::string LuaBind::replaceLuaTags(const std::string& text)
178  {
179    // chreate map with all Lua tags
180    std::map<size_t, bool> luaTags;
181    {
182      size_t pos = 0;
183      while ((pos = text.find("<?lua", pos)) != std::string::npos)
184        luaTags[pos++] = true;
185    }
186    {
187      size_t pos = 0;
188      while ((pos = text.find("?>", pos)) != std::string::npos)
189        luaTags[pos++] = false;
190    }
191
192    // erase all tags from the map that are between two quotes
193    {
194      std::map<size_t, bool>::iterator it = luaTags.begin();
195      std::map<size_t, bool>::iterator it2 = it;
196      bool bBetweenQuotes = false;
197      size_t pos = 0;
198      while ((pos = getNextQuote(text, pos)) != std::string::npos)
199      {
200        while ((it != luaTags.end()) && (it->first < pos))
201        {
202          if (bBetweenQuotes) {
203            it2++;
204            if(it->second && !(it2->second) && it2->first < pos)
205              it = ++it2;
206            else
207              luaTags.erase(it++);
208          }
209          else
210            ++it;
211        }
212        bBetweenQuotes = !bBetweenQuotes;
213        pos++;
214      }
215    }
216
217    // check whether on every opening <?lua tag a closing ?> tag follows
218    {
219      bool expectedValue = true;
220      for (std::map<size_t, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
221      {
222        if (it->second == expectedValue)
223          expectedValue = !expectedValue;
224        else
225        {
226          expectedValue = false;
227          break;
228        }
229      }
230      if (!expectedValue) {
231        COUT(2) << "Warning: Error in level file" << std::endl;
232        // todo: errorhandling
233        return "";
234      }
235    }
236
237    // cut the original string into pieces and put them together with print() instead of lua tags
238    std::string output;
239    {
240      std::map<size_t, bool>::iterator it = luaTags.begin();
241      bool bInPrintFunction = true;
242      size_t start = 0;
243      size_t end = 0;
244
245      do
246      {
247        if (it != luaTags.end())
248          end = (*(it++)).first;
249        else
250          end = std::string::npos;
251
252        unsigned int equalSignCounter = 0;
253
254        if (bInPrintFunction)
255        {
256          // count ['='[ and ]'='] and replace tags with print([[ and ]])
257          std::string temp = text.substr(start, end - start);
258          {
259            size_t pos = 0;
260            while ((pos = temp.find('[', pos)) != std::string::npos)
261            {
262              unsigned int tempCounter = 1;
263              size_t tempPos = pos++;
264              while(temp[++tempPos] == '=') {
265                tempCounter++;
266              }
267              if(temp[tempPos] != '[') {
268                tempCounter = 0;
269              }
270              else if(tempCounter == 0) {
271                tempCounter = 1;
272              }
273              if (tempCounter > equalSignCounter)
274                equalSignCounter = tempCounter;
275            }
276          }
277          {
278            size_t pos = 0;
279            while ((pos = temp.find(']', pos)) != std::string::npos)
280            {
281              unsigned int tempCounter = 1;
282              size_t tempPos = pos++;
283              while(temp[++tempPos] == '=') {
284                tempCounter++;
285              }
286              if(temp[tempPos] != ']') {
287                tempCounter = 0;
288              }
289              else if(tempCounter == 0) {
290                tempCounter = 1;
291              }
292              if (tempCounter > equalSignCounter)
293                equalSignCounter = tempCounter;
294            }
295          }
296          std::string equalSigns = "";
297          for(unsigned int i = 0; i < equalSignCounter; i++) {
298            equalSigns += "=";
299          }
300          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
301          start = end + 5;
302        }
303        else
304        {
305          output += text.substr(start, end - start);
306          start = end + 2;
307        }
308
309        bInPrintFunction = !bInPrintFunction;
310      }
311      while (end != std::string::npos);
312    }
313
314    return output;
315  }
316
317}
Note: See TracBrowser for help on using the repository browser.