mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-20 17:11:33 +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)
|
void ESM::RefNum::load (ESMReader& esm, bool wide)
|
||||||
{
|
{
|
||||||
if (wide)
|
if (wide)
|
||||||
esm.getHNT (*this, "FRMR", 8);
|
esm.getHNT (*this, SREC_FRMR, 8);
|
||||||
else
|
else
|
||||||
esm.getHNT (mIndex, "FRMR");
|
esm.getHNT (mIndex, SREC_FRMR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const
|
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.
|
// 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,
|
// 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.
|
// because any item can theoretically be moved by a script.
|
||||||
if (esm.isNextSub ("NAM0"))
|
if (esm.isNextSub (SREC_NAM0))
|
||||||
esm.skipHSub();
|
esm.skipHSub();
|
||||||
|
|
||||||
blank();
|
blank();
|
||||||
|
|
||||||
mRefNum.load (esm, wideRefNum);
|
mRefNum.load (esm, wideRefNum);
|
||||||
|
|
||||||
mRefID = esm.getHNString ("NAME");
|
esm.getHNString (SREC_NAME, mRefID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted)
|
void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted)
|
||||||
|
|
|
@ -128,7 +128,9 @@ enum RecNameInts
|
||||||
enum SubRecNameInts
|
enum SubRecNameInts
|
||||||
{
|
{
|
||||||
SREC_DELE = ESM::FourCC<'D','E','L','E'>::value,
|
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();
|
return getHString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ESMReader::getHNString(const int name, std::string& str)
|
||||||
|
{
|
||||||
|
getSubNameIs(name);
|
||||||
|
getHString(str);
|
||||||
|
}
|
||||||
|
|
||||||
std::string ESMReader::getHString()
|
std::string ESMReader::getHString()
|
||||||
{
|
{
|
||||||
getSubHeader();
|
getSubHeader();
|
||||||
|
@ -130,6 +136,28 @@ std::string ESMReader::getHString()
|
||||||
return getString(mCtx.leftSub);
|
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)
|
void ESMReader::getHExact(void*p, int size)
|
||||||
{
|
{
|
||||||
getSubHeader();
|
getSubHeader();
|
||||||
|
@ -159,6 +187,24 @@ void ESMReader::getSubNameIs(const char* name)
|
||||||
+ mCtx.subName.toString());
|
+ 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)
|
bool ESMReader::isNextSub(const char* name)
|
||||||
{
|
{
|
||||||
if (!mCtx.leftRec)
|
if (!mCtx.leftRec)
|
||||||
|
@ -174,6 +220,21 @@ bool ESMReader::isNextSub(const char* name)
|
||||||
return !mCtx.subCached;
|
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)
|
bool ESMReader::peekNextSub(const char *name)
|
||||||
{
|
{
|
||||||
if (!mCtx.leftRec)
|
if (!mCtx.leftRec)
|
||||||
|
@ -347,6 +408,26 @@ std::string ESMReader::getString(int size)
|
||||||
return std::string (ptr, 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)
|
void ESMReader::fail(const std::string &msg)
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
|
@ -103,6 +103,13 @@ public:
|
||||||
getHT(x);
|
getHT(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename X>
|
||||||
|
void getHNT(X &x, const int name)
|
||||||
|
{
|
||||||
|
getSubNameIs(name);
|
||||||
|
getHT(x);
|
||||||
|
}
|
||||||
|
|
||||||
// Optional version of getHNT
|
// Optional version of getHNT
|
||||||
template <typename X>
|
template <typename X>
|
||||||
void getHNOT(X &x, const char* name)
|
void getHNOT(X &x, const char* name)
|
||||||
|
@ -121,6 +128,14 @@ public:
|
||||||
getHT(x);
|
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>
|
template <typename X>
|
||||||
void getHNOT(X &x, const char* name, int size)
|
void getHNOT(X &x, const char* name, int size)
|
||||||
{
|
{
|
||||||
|
@ -159,9 +174,11 @@ public:
|
||||||
|
|
||||||
// Read a string with the given sub-record name
|
// Read a string with the given sub-record name
|
||||||
std::string getHNString(const char* 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)
|
// Read a string, including the sub-record header (but not the name)
|
||||||
std::string getHString();
|
std::string getHString();
|
||||||
|
void getHString(std::string& str);
|
||||||
|
|
||||||
// Read the given number of bytes from a subrecord
|
// Read the given number of bytes from a subrecord
|
||||||
void getHExact(void*p, int size);
|
void getHExact(void*p, int size);
|
||||||
|
@ -177,6 +194,7 @@ public:
|
||||||
|
|
||||||
// Get the next subrecord name and check if it matches the parameter
|
// Get the next subrecord name and check if it matches the parameter
|
||||||
void getSubNameIs(const char* name);
|
void getSubNameIs(const char* name);
|
||||||
|
void getSubNameIs(const int name);
|
||||||
|
|
||||||
/** Checks if the next sub record name matches the parameter. If it
|
/** Checks if the next sub record name matches the parameter. If it
|
||||||
does, it is read into 'subName' just as if getSubName() was
|
does, it is read into 'subName' just as if getSubName() was
|
||||||
|
@ -184,6 +202,7 @@ public:
|
||||||
calls to getSubName(), isNextSub() and getSubNameIs().
|
calls to getSubName(), isNextSub() and getSubNameIs().
|
||||||
*/
|
*/
|
||||||
bool isNextSub(const char* name);
|
bool isNextSub(const char* name);
|
||||||
|
bool isNextSub(const int name);
|
||||||
|
|
||||||
bool peekNextSub(const char* name);
|
bool peekNextSub(const char* name);
|
||||||
|
|
||||||
|
@ -256,6 +275,7 @@ public:
|
||||||
// Read the next 'size' bytes and return them as a string. Converts
|
// Read the next 'size' bytes and return them as a string. Converts
|
||||||
// them from native encoding to UTF8 in the process.
|
// them from native encoding to UTF8 in the process.
|
||||||
std::string getString(int size);
|
std::string getString(int size);
|
||||||
|
void getString(std::string& str, int size);
|
||||||
|
|
||||||
void skip(int bytes) { mEsm->seek(mEsm->tell()+bytes); }
|
void skip(int bytes) { mEsm->seek(mEsm->tell()+bytes); }
|
||||||
uint64_t getOffset() { return mEsm->tell(); }
|
uint64_t getOffset() { return mEsm->tell(); }
|
||||||
|
|
Loading…
Reference in a new issue