Use heterogenous maps for scripts

This commit is contained in:
Evil Eye 2022-08-12 20:56:50 +02:00
parent 51938f9ef7
commit 2deec591cd
6 changed files with 26 additions and 31 deletions

View file

@ -1,7 +1,7 @@
#ifndef GAME_MWBASE_SCRIPTMANAGER_H #ifndef GAME_MWBASE_SCRIPTMANAGER_H
#define GAME_MWBASE_SCRIPTMANAGER_H #define GAME_MWBASE_SCRIPTMANAGER_H
#include <string> #include <string_view>
namespace Interpreter namespace Interpreter
{ {
@ -38,10 +38,10 @@ namespace MWBase
virtual void clear() = 0; virtual void clear() = 0;
virtual bool run (const std::string& name, Interpreter::Context& interpreterContext) = 0; virtual bool run(std::string_view name, Interpreter::Context& interpreterContext) = 0;
///< Run the script with the given name (compile first, if not compiled yet) ///< Run the script with the given name (compile first, if not compiled yet)
virtual bool compile (const std::string& name) = 0; virtual bool compile(std::string_view name) = 0;
///< Compile script with the given namen ///< Compile script with the given namen
/// \return Success? /// \return Success?

View file

@ -261,7 +261,7 @@ namespace MWGui
if (!script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled()) if (!script.empty() && MWBase::Environment::get().getWorld()->getScriptsEnabled())
{ {
MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr); MWScript::InterpreterContext interpreterContext (&ptr.getRefData().getLocals(), ptr);
MWBase::Environment::get().getScriptManager()->run(std::string{script}, interpreterContext); MWBase::Environment::get().getScriptManager()->run(script, interpreterContext);
} }
// Clean up summoned creatures as well // Clean up summoned creatures as well

View file

@ -309,17 +309,16 @@ namespace MWScript
Locals& GlobalScripts::getLocals(std::string_view name) Locals& GlobalScripts::getLocals(std::string_view name)
{ {
std::string name2 = ::Misc::StringUtils::lowerCase (name); auto iter = mScripts.find(name);
auto iter = mScripts.find (name2);
if (iter==mScripts.end()) if (iter==mScripts.end())
{ {
const ESM::Script *script = mStore.get<ESM::Script>().find(name2); const ESM::Script *script = mStore.get<ESM::Script>().find(name);
auto desc = std::make_shared<GlobalScriptDesc>(); auto desc = std::make_shared<GlobalScriptDesc>();
desc->mLocals.configure (*script); desc->mLocals.configure (*script);
iter = mScripts.insert (std::make_pair (name2, desc)).first; iter = mScripts.emplace(name, desc).first;
} }
return iter->second->mLocals; return iter->second->mLocals;
@ -327,8 +326,7 @@ namespace MWScript
const Locals* GlobalScripts::getLocalsIfPresent(std::string_view name) const const Locals* GlobalScripts::getLocalsIfPresent(std::string_view name) const
{ {
std::string name2 = ::Misc::StringUtils::lowerCase (name); auto iter = mScripts.find(name);
auto iter = mScripts.find (name2);
if (iter==mScripts.end()) if (iter==mScripts.end())
return nullptr; return nullptr;
return &iter->second->mLocals; return &iter->second->mLocals;

View file

@ -3,13 +3,14 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <map> #include <unordered_map>
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <variant> #include <variant>
#include <cstdint> #include <cstdint>
#include <components/misc/algorithm.hpp>
#include "locals.hpp" #include "locals.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
@ -51,7 +52,7 @@ namespace MWScript
class GlobalScripts class GlobalScripts
{ {
const MWWorld::ESMStore& mStore; const MWWorld::ESMStore& mStore;
std::map<std::string, std::shared_ptr<GlobalScriptDesc> > mScripts; std::unordered_map<std::string, std::shared_ptr<GlobalScriptDesc>, ::Misc::StringUtils::CiHash, ::Misc::StringUtils::CiEqual> mScripts;
public: public:

View file

@ -39,14 +39,14 @@ namespace MWScript
std::sort (mScriptBlacklist.begin(), mScriptBlacklist.end()); std::sort (mScriptBlacklist.begin(), mScriptBlacklist.end());
} }
bool ScriptManager::compile (const std::string& name) bool ScriptManager::compile(std::string_view name)
{ {
mParser.reset(); mParser.reset();
mErrorHandler.reset(); mErrorHandler.reset();
if (const ESM::Script *script = mStore.get<ESM::Script>().find (name)) if (const ESM::Script *script = mStore.get<ESM::Script>().find (name))
{ {
mErrorHandler.setContext(name); mErrorHandler.setContext(script->mId);
bool Success = true; bool Success = true;
try try
@ -89,10 +89,10 @@ namespace MWScript
return false; return false;
} }
bool ScriptManager::run (const std::string& name, Interpreter::Context& interpreterContext) bool ScriptManager::run(std::string_view name, Interpreter::Context& interpreterContext)
{ {
// compile script // compile script
ScriptCollection::iterator iter = mScripts.find (name); auto iter = mScripts.find(name);
if (iter==mScripts.end()) if (iter==mScripts.end())
{ {
@ -167,27 +167,25 @@ namespace MWScript
const Compiler::Locals& ScriptManager::getLocals(std::string_view name) const Compiler::Locals& ScriptManager::getLocals(std::string_view name)
{ {
std::string name2 = Misc::StringUtils::lowerCase (name);
{ {
auto iter = mScripts.find (name2); auto iter = mScripts.find(name);
if (iter!=mScripts.end()) if (iter!=mScripts.end())
return iter->second.mLocals; return iter->second.mLocals;
} }
{ {
auto iter = mOtherLocals.find (name2); auto iter = mOtherLocals.find(name);
if (iter!=mOtherLocals.end()) if (iter!=mOtherLocals.end())
return iter->second; return iter->second;
} }
if (const ESM::Script *script = mStore.get<ESM::Script>().search (name2)) if (const ESM::Script* script = mStore.get<ESM::Script>().search(name))
{ {
Compiler::Locals locals; Compiler::Locals locals;
const Compiler::ContextOverride override(mErrorHandler, name2 + "[local variables]"); const Compiler::ContextOverride override(mErrorHandler, std::string{name} + "[local variables]");
std::istringstream stream (script->mScriptText); std::istringstream stream (script->mScriptText);
Compiler::QuickFileParser parser (mErrorHandler, mCompilerContext, locals); Compiler::QuickFileParser parser (mErrorHandler, mCompilerContext, locals);
@ -207,12 +205,12 @@ namespace MWScript
locals.clear(); locals.clear();
} }
auto iter = mOtherLocals.emplace(name2, locals).first; auto iter = mOtherLocals.emplace(name, locals).first;
return iter->second; return iter->second;
} }
throw std::logic_error("script " + name2 + " does not exist"); throw std::logic_error("script " + std::string{name} + " does not exist");
} }
GlobalScripts& ScriptManager::getGlobalScripts() GlobalScripts& ScriptManager::getGlobalScripts()

View file

@ -53,11 +53,9 @@ namespace MWScript
{} {}
}; };
typedef std::map<std::string, CompiledScript> ScriptCollection; std::unordered_map<std::string, CompiledScript, ::Misc::StringUtils::CiHash, ::Misc::StringUtils::CiEqual> mScripts;
ScriptCollection mScripts;
GlobalScripts mGlobalScripts; GlobalScripts mGlobalScripts;
std::map<std::string, Compiler::Locals> mOtherLocals; std::unordered_map<std::string, Compiler::Locals, ::Misc::StringUtils::CiHash, ::Misc::StringUtils::CiEqual> mOtherLocals;
std::vector<std::string> mScriptBlacklist; std::vector<std::string> mScriptBlacklist;
public: public:
@ -68,10 +66,10 @@ namespace MWScript
void clear() override; void clear() override;
bool run (const std::string& name, Interpreter::Context& interpreterContext) override; bool run(std::string_view name, Interpreter::Context& interpreterContext) override;
///< Run the script with the given name (compile first, if not compiled yet) ///< Run the script with the given name (compile first, if not compiled yet)
bool compile (const std::string& name) override; bool compile(std::string_view name) override;
///< Compile script with the given namen ///< Compile script with the given namen
/// \return Success? /// \return Success?