ScriptEngine.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
00004  *       mailto: <tevs@mpi-sb.mpg.de>                                      *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 
00014 //----------------------------------------------------------------------------------
00015 // Includes
00016 //----------------------------------------------------------------------------------
00017 #include "ScriptEngine.h"
00018 #include "Log.h"
00019 #include "events/EngineEvent.h"
00020 #include "EventManager.h"
00021 #include "VariadicArgument.h"
00022 #include "IScript.h"
00023 
00024 namespace nrEngine{
00025 
00026         //----------------------------------------------------------------------------------
00027         ScriptFunctionDec(scriptLoad, ScriptEngine)
00028         {
00029                 // check parameter count
00030                 if (args.size() < 2){
00031                         return ScriptResult(std::string("Not valid parameter count! Parameters (name, filename)"));
00032                 }
00033 
00034                 // get parameters
00035                 IResourcePtr ptr = Engine::sScriptEngine()->load(args[1], args[2]);
00036 
00037                 if (ptr.isNull())
00038                 {
00039                         return ScriptResult(std::string("Can not load script ") + args[1] + " from file " + args[2]);
00040                 }
00041 
00042                 return ScriptResult();
00043         }
00044 
00045         //----------------------------------------------------------------------------------
00046         ScriptFunctionDec(scriptRun, ScriptEngine)
00047         {
00048                 // check parameter count
00049                 if (args.size() < 1){
00050                         return ScriptResult(std::string("Not valid parameter count! Parameters (name [, runonce = true [, immediate = false]])"));
00051                 }
00052 
00053                 // get parameters
00054                 try{
00055                         const std::string& name = args[1];
00056                         bool once = true;
00057                         if (args.size() > 2) once = boost::lexical_cast<bool>(args[2]);
00058                         bool force = false;
00059                         if (args.size() > 3) force = boost::lexical_cast<bool>(args[3]);
00060 
00061                         // run
00062                         if (!Engine::sScriptEngine()->execute(name, once, force))
00063                                 return ScriptResult(std::string("Can not execute script ") + name);
00064                 }catch(boost::bad_lexical_cast s){
00065                         return ScriptResult(std::string("Wrong parameter value! "));
00066                 }
00067                 
00068                 return ScriptResult();
00069         }
00070 
00071         //----------------------------------------------------------------------------------
00072         ScriptFunctionDec(scriptLoadAndRun, ScriptEngine)
00073         {
00074                 // check parameter count
00075                 if (args.size() < 2){
00076                         return ScriptResult(std::string("Not valid parameter count! Parameters (name, filename)"));
00077                 }
00078 
00079                 // get name and filename
00080                 const std::string& name = args[1];
00081                 const std::string& fileName = args[2];
00082                 
00083                 // create argument for calling
00084                 std::vector<std::string> arg;
00085                 arg.push_back(args[0]);
00086                 arg.push_back(name);
00087                 arg.push_back(fileName);
00088                 
00089                 // call load method
00090                 ScriptResult res = scriptLoad(arg, param);
00091                 
00092                 // create arguments for run method 
00093                 arg.pop_back();
00094                 
00095                 // call run if load was successfull
00096                 if (res.size() == 0) res = scriptRun(arg, param);
00097                 
00098                 return res;
00099         }
00100 
00101         //----------------------------------------------------------------------------------
00102         ScriptFunctionDec(scriptCall, ScriptEngine)
00103         {
00104                 // check parameter count
00105                 if (args.size() < 2){
00106                         return ScriptResult(std::string("Not valid parameter count! Parameters (name, funcname, [, param1, ..., paramn])"));
00107                 }
00108                 
00109                 IScript::ArgumentList ar;
00110                         
00111                 // we get parameters, so extract them
00112                 if (args.size() >= 3 )
00113                 {
00114                         for (uint32 i=3; i < args.size(); i++)
00115                         {
00116                                 // get value 
00117                                 std::string param = args[i];
00118                                 
00119                                 // check if it contains ':' character
00120                                 std::string::size_type pos = param.find(':');
00121                                 if (pos == std::string::npos)
00122                                 {
00123                                         char msg[4096];
00124                                         sprintf(msg, "ScriptEngine: Parameter %s does not contain type information", param.c_str());
00125                                         return ScriptResult(std::string(msg));
00126                                 }
00127                                 
00128                                 // split on that character 
00129                                 std::string type = param.substr(pos + 1);
00130                                 std::string value = param.substr(0, pos);
00131         
00132                                 // store them
00133                                 ar.push_back(std::pair<std::string, std::string>(type, value));
00134                         } 
00135                 }
00136 
00137                 // get resource
00138                 ResourcePtr<IScript> ptr = Engine::sResourceManager()->getByName(args[1]);
00139                 if (ptr.isNull())
00140                         return ScriptResult(std::string("Can not find script ") + args[1]);
00141 
00142                 // now prepare arguments
00143                 ptr->setArguments(args[2], ar);
00144                 ScriptResult res;
00145                 ptr->call(args[2]);
00146                 
00147                 // call a specific function
00148                 return res;
00149         }
00150         
00151         //----------------------------------------------------------------------------------
00152         ScriptEngine::ScriptEngine(){
00153                 mDatabase["scriptLoad"].first = scriptLoad;
00154                 mDatabase["scriptRun"].first = scriptRun;
00155                 mDatabase["scriptExecute"].first = scriptRun;
00156                 mDatabase["scriptCall"].first = scriptCall;
00157                 mDatabase["scriptLoadAndRun"].first = scriptLoadAndRun;
00158         }
00159 
00160         //----------------------------------------------------------------------------------
00161         ScriptEngine::~ScriptEngine(){
00162 
00163                 // empty the database
00164                 mDatabase.clear();
00165 
00166         }
00167 
00168         //----------------------------------------------------------------------------------
00169         Result ScriptEngine::add(const std::string& name, ScriptFunctor func, const std::vector<ScriptParam>& param)
00170         {
00171                 // first check whenever such function already registered
00172                 if (isRegistered(name))
00173                         return SCRIPT_FUNCTION_REGISTERED;
00174 
00175                 // now add the function to the database
00176                 mDatabase[name].first = func;
00177                 mDatabase[name].second = param;
00178 
00179                 // some statistical information
00180                 NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ScriptEngine: New function \"%s\" registered", name.c_str());
00181 
00182                 // emit a new event
00183                 SharedPtr<Event> msg(new ScriptRegisterFunctionEvent(name, func));
00184                 Engine::sEventManager()->emitSystem(msg);
00185                 
00186                 return OK;
00187         }
00188 
00189         //----------------------------------------------------------------------------------
00190         Result ScriptEngine::add(const std::string& name, ScriptFunctor func, const VarArg& v){
00191 
00192                 // get the elements and store them in vector
00193                 std::vector<ScriptParam> p;
00194                 v.convert<ScriptParam>(p);
00195 
00196                 // OK
00197                 return add(name, func, p);
00198         }
00199 
00200         //----------------------------------------------------------------------------------
00201         Result ScriptEngine::del(const std::string& name)
00202         {
00203                 // get the function
00204                 FunctionDatabase::iterator it = mDatabase.find(name);
00205                 if (it == mDatabase.end()) return SCRIPT_FUNCTION_NOT_REGISTERED;
00206 
00207                 mDatabase.erase(it);
00208 
00209                 // some statistical information
00210                 NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ScriptEngine: Function \"%s\" was removed", name.c_str());
00211 
00212                 // emit a new event
00213                 SharedPtr<Event> msg(new ScriptRemoveFunctionEvent(name));
00214                 Engine::sEventManager()->emitSystem(msg);
00215 
00216                 return OK;
00217         }
00218 
00219         //----------------------------------------------------------------------------------
00220         ScriptResult ScriptEngine::call(const std::string& name, const std::vector<std::string>& args)
00221         {
00222                 // if no such function was found
00223                 FunctionDatabase::iterator f = get(name);
00224                 if (f == mDatabase.end()){
00225                         NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "ScriptEngine: Function \"%s\" was not found!", name.c_str());
00226                         return ScriptResult();
00227                 }
00228                 
00229                 // debug information 
00230                 std::string msg;
00231                 for (unsigned int i=1; i < args.size(); i++) msg += std::string(" ") + args[i];
00232                 NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "ScriptEngine: Call \"%s (%s)\" function!", name.c_str(), msg.c_str());
00233 
00234                 // call the function
00235                 return ((*f).second).first(args, (*f).second.second);
00236         }
00237 
00238         //----------------------------------------------------------------------------------
00239         bool ScriptEngine::isRegistered(const std::string& name)
00240         {
00241                 // search for that name in the database
00242                 FunctionDatabase::const_iterator it = mDatabase.find(name);
00243                 return it != mDatabase.end();
00244         }
00245 
00246         //----------------------------------------------------------------------------------
00247         ScriptEngine::FunctionDatabase::iterator ScriptEngine::get(const std::string& name)
00248         {
00249                 // search for that name in the database
00250                 FunctionDatabase::iterator it = mDatabase.find(name);
00251 
00252                 return it;
00253         }
00254 
00255         //------------------------------------------------------------------------
00256         ResourcePtr<IScript> ScriptEngine::load(const std::string& name, const std::string& file)
00257         {
00258                 // try to load the resource and check for the error code
00259                 ResourcePtr<IScript> plg = Engine::sResourceManager()->loadResource(name, "Scripts", file);
00260 
00261                 if (plg.isNull()){
00262                         NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Can not load the script %s from %s", name.c_str(), file.c_str());
00263                 }
00264                 return plg;
00265         }
00266 
00267 
00268         //------------------------------------------------------------------------
00269         Result ScriptEngine::execute(const std::string& name, bool runOnce, bool immediate)
00270         {
00271                 // get the pointer to the script resource
00272                 ResourcePtr<IScript> scr = Engine::sResourceManager()->getByName(name);
00273                 return _execute(scr, runOnce, immediate);               
00274         }
00275 
00276         //------------------------------------------------------------------------
00277         Result ScriptEngine::execute(const std::string& name, const std::string& fileName, bool runOnce, bool immediate)
00278         {
00279                 ResourcePtr<IScript> scr = load(name, fileName);
00280                 return _execute(scr, runOnce, immediate);
00281         }
00282 
00283         //------------------------------------------------------------------------
00284         Result ScriptEngine::_execute(const ResourcePtr<IScript>& ptr, bool runOnce, bool immediate)
00285         {
00286                 if (ptr.isNull()) return RES_NOT_FOUND;
00287                 if (immediate) return ptr->forceExecute(runOnce);
00288                 return ptr->execute(runOnce);
00289         }
00290 
00291         //------------------------------------------------------------------------
00292         const std::string& ScriptEngine::getFunction(uint32 index, ScriptFunctor& functor)
00293         {
00294                 NR_ASSERT(index < getFunctionCount());
00295                 FunctionDatabase::const_iterator it = mDatabase.begin();
00296                 for (uint32 i = 0; i < index; i++, it++){}
00297 
00298                 functor = it->second.first;
00299                 return it->first;
00300         }
00301 
00302 };
00303 

Generated on Wed Sep 12 23:19:42 2007 for nrEngine by  doxygen 1.5.1