Index: code/branches/resource2/src/core/LuaState.cc
===================================================================
--- code/branches/resource2/src/core/LuaBind.cc	(revision 5645)
+++ code/branches/resource2/src/core/LuaState.cc	(revision 5654)
@@ -22,4 +22,5 @@
  *   Author:
  *      Benjamin Knecht
+ *      Reto Grieder
  *   Co-authors:
  *      ...
@@ -27,317 +28,234 @@
  */
 
-#include "LuaBind.h"
-
-#include <fstream>
-#include <map>
+#include "LuaState.h"
+
+#include <tolua/tolua++.h>
 extern "C" {
+#include <lua.h>
 #include <lualib.h>
 }
-#include <tolua/tolua++.h>
-#include <boost/filesystem.hpp>
 
 #include "util/Debug.h"
-#include "util/StringUtils.h"
 #include "Core.h"
+#include "Resource.h"
 
 namespace orxonox
 {
-  LuaBind* LuaBind::singletonPtr_s = NULL;
-
-  LuaBind::LuaBind()
-  {
-    this->includePath_ = Core::getDataPathString();
-
-    luaState_ = lua_open();
-    luaSource_ = "";
+    LuaState::ToluaInterfaceMap LuaState::toluaInterfaces_s;
+    std::vector<LuaState*> LuaState::instances_s;
+
+    LuaState::LuaState()
+        : bIsRunning_(false)
+        , includeParseFunction_(NULL)
+    {
+        // Create new lua state and configure it
+        luaState_ = lua_open();
 #if LUA_VERSION_NUM == 501
-    luaL_openlibs(luaState_);
+        luaL_openlibs(luaState_);
 #else
-    luaopen_base(luaState_);
-    luaopen_string(luaState_);
-    luaopen_table(luaState_);
-    luaopen_math(luaState_);
-    luaopen_io(luaState_);
-    luaopen_debug(luaState_);
+        luaopen_base(luaState_);
+        luaopen_string(luaState_);
+        luaopen_table(luaState_);
+        luaopen_math(luaState_);
+        luaopen_io(luaState_);
+        luaopen_debug(luaState_);
 #endif
 
-    // Open all available tolua interfaces
-    this->openToluaInterfaces(luaState_);
-
-    output_ = "";
-    isRunning_ = false;
-  }
-
-  LuaBind::~LuaBind()
-  {
-    this->closeToluaInterfaces(luaState_);
-  };
-
-  void LuaBind::luaPrint(const std::string& str)
-  {
-    output_ += str;
-//    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
-    COUT(5) << str;
-  }
-
-  /**
-      @brief Loads the specified file line by line
-      @param filename The filename of the file
-      @param luaTags if true, the loaded file gets stripped off luaTags
-  */
-  void LuaBind::loadFile(const std::string& filename, bool luaTags)
-  {
-    boost::filesystem::path filepath(filename);
-
-    output_ = "";
-    std::ifstream file;
-    file.open(filepath.string().c_str(), std::fstream::in);
-
-    if (!file.is_open())
-    {
-      // some error msg
-    }
-
-    std::string levelString = "";
-
-    while (file.good() && !file.eof())
-    {
-      std::string line;
-      std::getline(file, line);
-      levelString += line;
-      levelString += "\n";
-    }
-
-    file.close();
-    //std::string output;
-
-    if (luaTags)
-      luaSource_ = replaceLuaTags(levelString);
-    else
-      luaSource_ = levelString;
-    COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
-  }
-
-  void LuaBind::loadString(const std::string& code)
-  {
-    luaSource_ = code;
-    output_ = "";
-  }
-
+        // Open all available tolua interfaces
+        this->openToluaInterfaces(luaState_);
+
+        // Create dummy file info
+        sourceFileInfo_.reset(new ResourceInfo());
+        sourceFileInfo_->group = "General";
+        sourceFileInfo_->size = 0;
+
+        // Push this pointer
+        tolua_pushusertype(luaState_, static_cast<void*>(this), "orxonox::LuaState");
+        lua_setglobal(luaState_, "luaState");
+
+        // Parse init script
+        // Note: We have to use a hard coded path because the script is required for the resource loading
+        this->doString("dofile(\"" + Core::getDataPathString() + "lua/LuaStateInit.lua\")");
+    }
+
+    LuaState::~LuaState()
+    {
+        lua_close(luaState_);
+    }
+
+    shared_ptr<ResourceInfo> LuaState::getFileInfo(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
+    {
+        shared_ptr<ResourceInfo> sourceInfo;
+        if (resourceGroup != "NoResourceGroupProvided")
+            sourceInfo = Resource::getInfo(filename, resourceGroup);
+
+        // Continue search if not explicitely forbidden
+        if (bSearchOtherPaths && sourceInfo == NULL)
+        {
+            // Call might be relative to the file currently being processed
+            sourceInfo = Resource::getInfo(sourceFileInfo_->path + filename, sourceFileInfo_->group);
+            if (sourceInfo == NULL)
+            {
+                // Maybe find something in the same group but in the root path
+                sourceInfo = Resource::getInfo(filename, sourceFileInfo_->group);
+            }
+        }
+        return sourceInfo;
+    }
+
+    void LuaState::includeFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
+    {
+        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
+        if (sourceInfo != NULL)
+            this->includeString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
+        else
+            COUT(2) << "LuaState: Cannot include file '" << filename << "' in resource group '"
+                    << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
+    }
+
+    void LuaState::includeString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
+    {
+        // Parse string with provided include parser (otherwise don't preparse at all)
+        std::string luaInput;
+        if (includeParseFunction_ != NULL)
+            luaInput = (*includeParseFunction_)(code);
+        else
+            luaInput = code;
+
+        this->doString(luaInput, sourceFileInfo);
+    }
+
+    void LuaState::doFile(const std::string& filename, const std::string& resourceGroup, bool bSearchOtherPaths)
+    {
+        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename, resourceGroup, bSearchOtherPaths);
+        if (sourceInfo != NULL)
+            this->doString(Resource::open(sourceInfo->filename, sourceInfo->group)->getAsString(), sourceInfo);
+        else
+            COUT(2) << "LuaState: Cannot do file '" << filename << "' in resource group '"
+                << (resourceGroup == "NoResourceGroupProvided" ? sourceFileInfo_->group : resourceGroup) << "': group not found." << std::endl;
+    }
+
+    void LuaState::doString(const std::string& code, shared_ptr<ResourceInfo> sourceFileInfo)
+    {
+        // Save the oold source file info
+        shared_ptr<ResourceInfo> oldSourceFileInfo = sourceFileInfo_;
+        // Only override if sourceFileInfo provides useful information
+        if (sourceFileInfo != NULL)
+            sourceFileInfo_ = sourceFileInfo;
+
+        //if (!bIsRunning_)
+        //{
+        //    bIsRunning_ = true;
+
+        int error = 0;
 #if LUA_VERSION_NUM != 501
-  const char * LuaBind::lua_Chunkreader(lua_State *L, void *data, size_t *size)
-  {
-    LoadS* ls = static_cast<LoadS*>(data);
-    if (ls->size == 0) return NULL;
-    *size = ls->size;
-    ls->size = 0;
-    return ls->s;
-  }
+        LoadS ls;
+        ls.s = code.c_str();
+        ls.size = code.size();
+        error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());
+#else
+        error = luaL_loadstring(luaState_, code.c_str());
 #endif
-  void LuaBind::run()
-  {
-    if (!isRunning_)
-    {
-      isRunning_ = true;
-      int error = 0;
-      std::string init =
-         "local scr = orxonox.LuaBind:getInstance()\n \
-          local debug = print\n \
-          print = function(s)\n \
-              scr:luaPrint(s)\n \
-          end\n \
-          include = function(f)\n \
-              file = assert(io.open(\"" + this->includePath_ + "\"..\"/\"..f))\n \
-              content = file:read(\"*a\")\n \
-              file:close()\n \
-              source = scr:replaceLuaTags(content)\n \
-              assert(loadstring(source))()\n \
-          end\n";
-      init += luaSource_;
-  #if LUA_VERSION_NUM == 501
-      error = luaL_loadstring(luaState_, init.c_str());
-  #else
-      LoadS ls;
-      ls.s = init.c_str();
-      ls.size = init.size();
-      error = lua_load(luaState_, &orxonox::LuaBind::lua_Chunkreader, &ls, init.c_str());
-  #endif
-      if (error == 0)
-      {
-        error = lua_pcall(luaState_, 0, 0, 0);
-      }
-      if (error != 0)
-      {
-        COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
-      }
-      isRunning_ = false;
-    }
-    else
-    {
-      COUT(2) << "Warning: Lua's run is called while running!" << std::endl;
-    }
-  }
-
-  std::string LuaBind::replaceLuaTags(const std::string& text)
-  {
-    // chreate map with all Lua tags
-    std::map<size_t, bool> luaTags;
-    {
-      size_t pos = 0;
-      while ((pos = text.find("<?lua", pos)) != std::string::npos)
-        luaTags[pos++] = true;
-    }
-    {
-      size_t pos = 0;
-      while ((pos = text.find("?>", pos)) != std::string::npos)
-        luaTags[pos++] = false;
-    }
-
-    // erase all tags from the map that are between two quotes
-    {
-      std::map<size_t, bool>::iterator it = luaTags.begin();
-      std::map<size_t, bool>::iterator it2 = it;
-      bool bBetweenQuotes = false;
-      size_t pos = 0;
-      while ((pos = getNextQuote(text, pos)) != std::string::npos)
-      {
-        while ((it != luaTags.end()) && (it->first < pos))
-        {
-          if (bBetweenQuotes) {
-            it2++;
-            if(it->second && !(it2->second) && it2->first < pos)
-              it = ++it2;
-            else
-              luaTags.erase(it++);
-          }
-          else
-            ++it;
-        }
-        bBetweenQuotes = !bBetweenQuotes;
-        pos++;
-      }
-    }
-
-    // check whether on every opening <?lua tag a closing ?> tag follows
-    {
-      bool expectedValue = true;
-      for (std::map<size_t, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
-      {
-        if (it->second == expectedValue)
-          expectedValue = !expectedValue;
-        else
-        {
-          expectedValue = false;
-          break;
-        }
-      }
-      if (!expectedValue) {
-        COUT(2) << "Warning: Error in level file" << std::endl;
-        // todo: errorhandling
-        return "";
-      }
-    }
-
-    // cut the original string into pieces and put them together with print() instead of lua tags
-    std::string output;
-    {
-      std::map<size_t, bool>::iterator it = luaTags.begin();
-      bool bInPrintFunction = true;
-      size_t start = 0;
-      size_t end = 0;
-
-      do
-      {
-        if (it != luaTags.end())
-          end = (*(it++)).first;
-        else
-          end = std::string::npos;
-
-        unsigned int equalSignCounter = 0;
-
-        if (bInPrintFunction)
-        {
-          // count ['='[ and ]'='] and replace tags with print([[ and ]])
-          std::string temp = text.substr(start, end - start);
-          {
-            size_t pos = 0;
-            while ((pos = temp.find('[', pos)) != std::string::npos)
+
+        // execute the chunk
+        if (error == 0)
+            error = lua_pcall(luaState_, 0, 0, 0);
+        if (error != 0)
+        {
+            std::string origin;
+            if (sourceFileInfo != NULL)
+                origin = " originating from " + sourceFileInfo_->filename;
+            COUT(2) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl;
+        }
+
+        //    bIsRunning_ = false;
+        //}
+        //else
+        //{
+        //    COUT(2) << "Warning: LuaState do function called while running!" << std::endl;
+        //}
+
+        // Load the old info again
+        sourceFileInfo_ = oldSourceFileInfo;
+    }
+
+    void LuaState::luaPrint(const std::string& str)
+    {
+        output_ << str;
+    }
+
+    void LuaState::luaLog(unsigned int level, const std::string& message)
+    {
+        OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
+    }
+
+#if LUA_VERSION_NUM != 501
+    const char * LuaState::lua_Chunkreader(lua_State *L, void *data, size_t *size)
+    {
+        LoadS* ls = static_cast<LoadS*>(data);
+        if (ls->size == 0)
+            return NULL;
+        *size = ls->size;
+        ls->size = 0;
+        return ls->s;
+    }
+#endif
+
+    /*static*/ bool LuaState::addToluaInterface(int (*function)(lua_State*), const std::string& name)
+    {
+        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
+        {
+            if (it->first == name || it->second == function)
             {
-              unsigned int tempCounter = 1;
-              size_t tempPos = pos++;
-              while(temp[++tempPos] == '=') {
-                tempCounter++;
-              }
-              if(temp[tempPos] != '[') {
-                tempCounter = 0;
-              }
-              else if(tempCounter == 0) {
-                tempCounter = 1;
-              }
-              if (tempCounter > equalSignCounter)
-                equalSignCounter = tempCounter;
+                COUT(2) << "Warning: Trying to add a Tolua interface with the same name or function." << std::endl;
+                return true;
             }
-          }
-          {
-            size_t pos = 0;
-            while ((pos = temp.find(']', pos)) != std::string::npos)
-            {
-              unsigned int tempCounter = 1;
-              size_t tempPos = pos++;
-              while(temp[++tempPos] == '=') {
-                tempCounter++;
-              }
-              if(temp[tempPos] != ']') {
-                tempCounter = 0;
-              }
-              else if(tempCounter == 0) {
-                tempCounter = 1;
-              }
-              if (tempCounter > equalSignCounter)
-                equalSignCounter = tempCounter;
-            }
-          }
-          std::string equalSigns = "";
-          for(unsigned int i = 0; i < equalSignCounter; i++) {
-            equalSigns += "=";
-          }
-          output += "print([" + equalSigns + "[" + temp + "]" + equalSigns +"])";
-          start = end + 5;
-        }
-        else
-        {
-          output += text.substr(start, end - start);
-          start = end + 2;
-        }
-
-        bInPrintFunction = !bInPrintFunction;
-      }
-      while (end != std::string::npos);
-    }
-
-    return output;
-  }
-
-  void LuaBind::addToluaInterface(int (*function)(lua_State*), const std::string& name)
-  {
-    toluaInterfaces_.push_back(std::make_pair(name, function));
-    // Apply changes to our own lua state as well 
-    (*function)(luaState_);
-  }
-
-  void LuaBind::openToluaInterfaces(lua_State* state)
-  {
-    for (unsigned int i = 0; i < toluaInterfaces_.size(); ++i)
-      (*toluaInterfaces_[i].second)(state);
-  }
-
-  void LuaBind::closeToluaInterfaces(lua_State* state)
-  {
-    for (unsigned int i = 0; i < toluaInterfaces_.size(); ++i)
-    {
-      lua_pushnil(state);
-      lua_setglobal(state, toluaInterfaces_[i].first.c_str());
-    }
-  }
-
+        }
+        toluaInterfaces_s[name] = function;
+
+        // Open interface in all LuaStates
+        for (std::vector<LuaState*>::const_iterator it = instances_s.begin(); it != instances_s.end(); ++it)
+            (*function)((*it)->luaState_);
+
+        // Return dummy bool
+        return true;
+    }
+
+    /*static*/ bool LuaState::removeToluaInterface(const std::string& name)
+    {
+        ToluaInterfaceMap::iterator it = toluaInterfaces_s.find(name);
+        if (it == toluaInterfaces_s.end())
+        {
+            COUT(2) << "Warning: Cannot remove Tolua interface '" << name << "': Not found" << std::endl;
+            return true;
+        }
+
+        // Close interface in all LuaStates
+        for (std::vector<LuaState*>::const_iterator itState = instances_s.begin(); itState != instances_s.end(); ++itState)
+        {
+            lua_pushnil((*itState)->luaState_);
+            lua_setglobal((*itState)->luaState_, it->first.c_str());
+        }
+
+        // Remove entry
+        toluaInterfaces_s.erase(it);
+
+        // Return dummy bool
+        return true;
+    }
+
+    /*static*/ void LuaState::openToluaInterfaces(lua_State* state)
+    {
+        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
+            (*it->second)(state);
+    }
+
+    /*static*/ void LuaState::closeToluaInterfaces(lua_State* state)
+    {
+        for (ToluaInterfaceMap::const_iterator it = toluaInterfaces_s.begin(); it != toluaInterfaces_s.end(); ++it)
+        {
+            lua_pushnil(state);
+            lua_setglobal(state, it->first.c_str());
+        }
+    }
 }
