#include "scriptcontext.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "data.hpp" CSMWorld::ScriptContext::ScriptContext(const Data& data) : mData(data) , mIdsUpdated(false) { } bool CSMWorld::ScriptContext::canDeclareLocals() const { return true; } char CSMWorld::ScriptContext::getGlobalType(const std::string& name) const { int index = mData.getGlobals().searchId(name); if (index != -1) { switch (mData.getGlobals().getRecord(index).get().mValue.getType()) { case ESM::VT_Short: return 's'; case ESM::VT_Long: return 'l'; case ESM::VT_Float: return 'f'; default: return ' '; } } return ' '; } std::pair CSMWorld::ScriptContext::getMemberType(const std::string& name, const ESM::RefId& id) const { ESM::RefId id2 = id; int index = mData.getScripts().searchId(id2); bool reference = false; if (index == -1) { // ID is not a script ID. Search for a matching referenceable instead. index = mData.getReferenceables().searchId(id2); if (index != -1) { // Referenceable found. int columnIndex = mData.getReferenceables().findColumnIndex(Columns::ColumnId_Script); id2 = ESM::RefId::stringRefId( mData.getReferenceables().getData(index, columnIndex).toString().toUtf8().constData()); if (!id2.empty()) { // Referenceable has a script -> use it. index = mData.getScripts().searchId(id2); reference = true; } } } if (index == -1) return std::make_pair(' ', false); std::map::iterator iter = mLocals.find(id2.getRefIdString()); if (iter == mLocals.end()) { Compiler::Locals locals; Compiler::NullErrorHandler errorHandler; std::istringstream stream(mData.getScripts().getRecord(index).get().mScriptText); Compiler::QuickFileParser parser(errorHandler, *this, locals); Compiler::Scanner scanner(errorHandler, stream, getExtensions()); scanner.scan(parser); iter = mLocals.insert(std::make_pair(id2.getRefIdString(), locals)).first; } return std::make_pair(iter->second.getType(Misc::StringUtils::lowerCase(name)), reference); } bool CSMWorld::ScriptContext::isId(const ESM::RefId& name) const { if (!mIdsUpdated) { mIds = mData.getIds(); std::sort(mIds.begin(), mIds.end()); mIdsUpdated = true; } return std::binary_search(mIds.begin(), mIds.end(), name); } void CSMWorld::ScriptContext::invalidateIds() { mIdsUpdated = false; } void CSMWorld::ScriptContext::clear() { mIds.clear(); mIdsUpdated = false; mLocals.clear(); } bool CSMWorld::ScriptContext::clearLocals(const std::string& script) { std::map::iterator iter = mLocals.find(Misc::StringUtils::lowerCase(script)); if (iter != mLocals.end()) { mLocals.erase(iter); mIdsUpdated = false; return true; } return false; }