mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 12:23:51 +00:00
Minor performance gains on loading cell references.
- Use integers where possible - Unfortunately many functions are simply duplicated for now, but over time the deprecated ones will be removed
This commit is contained in:
parent
003b0d48be
commit
abe6904a94
4 changed files with 110 additions and 7 deletions
|
@ -6,9 +6,9 @@
|
|||
void ESM::RefNum::load (ESMReader& esm, bool wide)
|
||||
{
|
||||
if (wide)
|
||||
esm.getHNT (*this, "FRMR", 8);
|
||||
esm.getHNT (*this, SREC_FRMR, 8);
|
||||
else
|
||||
esm.getHNT (mIndex, "FRMR");
|
||||
esm.getHNT (mIndex, SREC_FRMR);
|
||||
}
|
||||
|
||||
void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const
|
||||
|
@ -36,14 +36,14 @@ void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum)
|
|||
// the following refs are part of a "temp refs" section. A temp ref is not being tracked by the moved references system.
|
||||
// Its only purpose is a performance optimization for "immovable" things. We don't need this, and it's problematic anyway,
|
||||
// because any item can theoretically be moved by a script.
|
||||
if (esm.isNextSub ("NAM0"))
|
||||
if (esm.isNextSub (SREC_NAM0))
|
||||
esm.skipHSub();
|
||||
|
||||
blank();
|
||||
|
||||
mRefNum.load (esm, wideRefNum);
|
||||
|
||||
mRefID = esm.getHNString ("NAME");
|
||||
esm.getHNString (SREC_NAME, mRefID);
|
||||
}
|
||||
|
||||
void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted)
|
||||
|
@ -180,7 +180,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory, bool
|
|||
void ESM::CellRef::blank()
|
||||
{
|
||||
mRefNum.unset();
|
||||
mRefID.clear();
|
||||
mRefID.clear();
|
||||
mScale = 1;
|
||||
mOwner.clear();
|
||||
mGlobalVariable.clear();
|
||||
|
@ -196,7 +196,7 @@ void ESM::CellRef::blank()
|
|||
mTrap.clear();
|
||||
mReferenceBlocked = -1;
|
||||
mTeleport = false;
|
||||
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
mDoorDest.pos[i] = 0;
|
||||
|
|
|
@ -128,7 +128,9 @@ enum RecNameInts
|
|||
enum SubRecNameInts
|
||||
{
|
||||
SREC_DELE = ESM::FourCC<'D','E','L','E'>::value,
|
||||
SREC_NAME = ESM::FourCC<'N','A','M','E'>::value
|
||||
SREC_NAME = ESM::FourCC<'N','A','M','E'>::value,
|
||||
SREC_NAM0 = ESM::FourCC<'N','A','M','0'>::value,
|
||||
SREC_FRMR = ESM::FourCC<'F','R','M','R'>::value
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -109,6 +109,12 @@ std::string ESMReader::getHNString(const char* name)
|
|||
return getHString();
|
||||
}
|
||||
|
||||
void ESMReader::getHNString(const int name, std::string& str)
|
||||
{
|
||||
getSubNameIs(name);
|
||||
getHString(str);
|
||||
}
|
||||
|
||||
std::string ESMReader::getHString()
|
||||
{
|
||||
getSubHeader();
|
||||
|
@ -130,6 +136,28 @@ std::string ESMReader::getHString()
|
|||
return getString(mCtx.leftSub);
|
||||
}
|
||||
|
||||
void ESMReader::getHString(std::string& str)
|
||||
{
|
||||
getSubHeader();
|
||||
|
||||
// Hack to make MultiMark.esp load. Zero-length strings do not
|
||||
// occur in any of the official mods, but MultiMark makes use of
|
||||
// them. For some reason, they break the rules, and contain a byte
|
||||
// (value 0) even if the header says there is no data. If
|
||||
// Morrowind accepts it, so should we.
|
||||
if (mCtx.leftSub == 0)
|
||||
{
|
||||
// Skip the following zero byte
|
||||
mCtx.leftRec--;
|
||||
char c;
|
||||
getExact(&c, 1);
|
||||
str = "";
|
||||
return;
|
||||
}
|
||||
|
||||
getString(str, mCtx.leftSub);
|
||||
}
|
||||
|
||||
void ESMReader::getHExact(void*p, int size)
|
||||
{
|
||||
getSubHeader();
|
||||
|
@ -159,6 +187,24 @@ void ESMReader::getSubNameIs(const char* name)
|
|||
+ mCtx.subName.toString());
|
||||
}
|
||||
|
||||
void ESMReader::getSubNameIs(const int name)
|
||||
{
|
||||
getSubName();
|
||||
if (mCtx.subName != name)
|
||||
{
|
||||
unsigned char typeName[4];
|
||||
typeName[0] = name & 0xff;
|
||||
typeName[1] = (name >> 8) & 0xff;
|
||||
typeName[2] = (name >> 16) & 0xff;
|
||||
typeName[3] = (name >> 24) & 0xff;
|
||||
|
||||
std::string subName = std::string((char*)typeName, 4);
|
||||
|
||||
fail("Expected subrecord " + subName + " but got "
|
||||
+ mCtx.subName.toString());
|
||||
}
|
||||
}
|
||||
|
||||
bool ESMReader::isNextSub(const char* name)
|
||||
{
|
||||
if (!mCtx.leftRec)
|
||||
|
@ -174,6 +220,21 @@ bool ESMReader::isNextSub(const char* name)
|
|||
return !mCtx.subCached;
|
||||
}
|
||||
|
||||
bool ESMReader::isNextSub(const int name)
|
||||
{
|
||||
if (!mCtx.leftRec)
|
||||
return false;
|
||||
|
||||
getSubName();
|
||||
|
||||
// If the name didn't match, then mark the it as 'cached' so it's
|
||||
// available for the next call to getSubName.
|
||||
mCtx.subCached = (mCtx.subName != name);
|
||||
|
||||
// If subCached is false, then subName == name.
|
||||
return !mCtx.subCached;
|
||||
}
|
||||
|
||||
bool ESMReader::peekNextSub(const char *name)
|
||||
{
|
||||
if (!mCtx.leftRec)
|
||||
|
@ -347,6 +408,26 @@ std::string ESMReader::getString(int size)
|
|||
return std::string (ptr, size);
|
||||
}
|
||||
|
||||
void ESMReader::getString(std::string& str, int size)
|
||||
{
|
||||
size_t s = size;
|
||||
if (mBuffer.size() <= s)
|
||||
// Add some extra padding to reduce the chance of having to resize again later.
|
||||
mBuffer.resize(3*s);
|
||||
|
||||
mBuffer[s] = 0; // And make sure the string is zero terminated
|
||||
|
||||
char *ptr = &mBuffer[0];
|
||||
getExact(ptr, size); // read ESM data
|
||||
|
||||
size = static_cast<int>(strnlen(ptr, size));
|
||||
|
||||
if (mEncoder)
|
||||
str = mEncoder->getUtf8(ptr, size); // Convert to UTF8 and return
|
||||
else
|
||||
str = std::string (ptr, size);
|
||||
}
|
||||
|
||||
void ESMReader::fail(const std::string &msg)
|
||||
{
|
||||
using namespace std;
|
||||
|
|
|
@ -103,6 +103,13 @@ public:
|
|||
getHT(x);
|
||||
}
|
||||
|
||||
template <typename X>
|
||||
void getHNT(X &x, const int name)
|
||||
{
|
||||
getSubNameIs(name);
|
||||
getHT(x);
|
||||
}
|
||||
|
||||
// Optional version of getHNT
|
||||
template <typename X>
|
||||
void getHNOT(X &x, const char* name)
|
||||
|
@ -121,6 +128,14 @@ public:
|
|||
getHT(x);
|
||||
}
|
||||
|
||||
template <typename X>
|
||||
void getHNT(X &x, const int name, int size)
|
||||
{
|
||||
assert(sizeof(X) == size);
|
||||
getSubNameIs(name);
|
||||
getHT(x);
|
||||
}
|
||||
|
||||
template <typename X>
|
||||
void getHNOT(X &x, const char* name, int size)
|
||||
{
|
||||
|
@ -159,9 +174,11 @@ public:
|
|||
|
||||
// Read a string with the given sub-record name
|
||||
std::string getHNString(const char* name);
|
||||
void getHNString(const int name, std::string& str);
|
||||
|
||||
// Read a string, including the sub-record header (but not the name)
|
||||
std::string getHString();
|
||||
void getHString(std::string& str);
|
||||
|
||||
// Read the given number of bytes from a subrecord
|
||||
void getHExact(void*p, int size);
|
||||
|
@ -177,6 +194,7 @@ public:
|
|||
|
||||
// Get the next subrecord name and check if it matches the parameter
|
||||
void getSubNameIs(const char* name);
|
||||
void getSubNameIs(const int name);
|
||||
|
||||
/** Checks if the next sub record name matches the parameter. If it
|
||||
does, it is read into 'subName' just as if getSubName() was
|
||||
|
@ -184,6 +202,7 @@ public:
|
|||
calls to getSubName(), isNextSub() and getSubNameIs().
|
||||
*/
|
||||
bool isNextSub(const char* name);
|
||||
bool isNextSub(const int name);
|
||||
|
||||
bool peekNextSub(const char* name);
|
||||
|
||||
|
@ -256,6 +275,7 @@ public:
|
|||
// Read the next 'size' bytes and return them as a string. Converts
|
||||
// them from native encoding to UTF8 in the process.
|
||||
std::string getString(int size);
|
||||
void getString(std::string& str, int size);
|
||||
|
||||
void skip(int bytes) { mEsm->seek(mEsm->tell()+bytes); }
|
||||
uint64_t getOffset() { return mEsm->tell(); }
|
||||
|
|
Loading…
Reference in a new issue