1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-20 20:53:53 +00:00
openmw/apps/opencs/model/world/scriptcontext.cpp
florent.teppe 65cdd489fb create a specific esm reader function for RefID to avoid allocation for string and then again for RefId
Fixed some types

removed useless header

applied clang format

fixed compile tests

fixed clang tidy, and closer to logic before this MR

Removed hardcoded refids

unless there is a returned value we don't use static RefIds
can use == between RefId and hardcoded string

Fix clang format

Fixed a few instances where std::string was used, when only const std::string& was needed

removed unused variable
2022-12-27 19:15:57 +01:00

144 lines
3.7 KiB
C++

#include "scriptcontext.hpp"
#include <algorithm>
#include <sstream>
#include <type_traits>
#include <apps/opencs/model/world/columns.hpp>
#include <apps/opencs/model/world/idcollection.hpp>
#include <apps/opencs/model/world/record.hpp>
#include <apps/opencs/model/world/refidcollection.hpp>
#include <components/compiler/nullerrorhandler.hpp>
#include <components/compiler/quickfileparser.hpp>
#include <components/compiler/scanner.hpp>
#include <components/esm3/loadglob.hpp>
#include <components/esm3/loadscpt.hpp>
#include <components/esm3/variant.hpp>
#include <components/misc/strings/lower.hpp>
#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<char, bool> 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<std::string, Compiler::Locals>::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<std::string, Compiler::Locals>::iterator iter = mLocals.find(Misc::StringUtils::lowerCase(script));
if (iter != mLocals.end())
{
mLocals.erase(iter);
mIdsUpdated = false;
return true;
}
return false;
}