diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index 4cf528c832..8c079a0e55 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -97,7 +97,7 @@ namespace ESSImport void ConvertFMAP::read(ESM::ESMReader& esm) { MAPH maph; - esm.getHNT(maph, "MAPH"); + esm.getHNTSized<8>(maph, "MAPH"); std::vector data; esm.getSubNameIs("MAPD"); esm.getSubHeader(); diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index 8470fd7cf7..7c2159299a 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -48,14 +48,14 @@ namespace ESSImport if (esm.isNextSub("ACDT")) { mActorData.mHasACDT = true; - esm.getHT(mActorData.mACDT); + esm.getHTSized<264>(mActorData.mACDT); } mActorData.mHasACSC = false; if (esm.isNextSub("ACSC")) { mActorData.mHasACSC = true; - esm.getHT(mActorData.mACSC); + esm.getHTSized<112>(mActorData.mACSC); } if (esm.isNextSub("ACSL")) @@ -137,7 +137,7 @@ namespace ESSImport if (esm.isNextSub("ANIS")) { mActorData.mHasANIS = true; - esm.getHT(mActorData.mANIS); + esm.getHTSized<8>(mActorData.mANIS); } if (esm.isNextSub("LVCR")) diff --git a/apps/essimporter/importgame.cpp b/apps/essimporter/importgame.cpp index 2a2572aae3..5295d2a1e8 100644 --- a/apps/essimporter/importgame.cpp +++ b/apps/essimporter/importgame.cpp @@ -16,7 +16,7 @@ namespace ESSImport } else if (esm.getSubSize() == 96) { - esm.getT(mGMDT); + esm.getTSized<96>(mGMDT); } else esm.fail("unexpected subrecord size for GAME.GMDT"); diff --git a/apps/essimporter/importinventory.cpp b/apps/essimporter/importinventory.cpp index 707a804830..743f2c1cf7 100644 --- a/apps/essimporter/importinventory.cpp +++ b/apps/essimporter/importinventory.cpp @@ -12,7 +12,7 @@ namespace ESSImport while (esm.isNextSub("NPCO")) { ContItem contItem; - esm.getHT(contItem); + esm.getHTSized<36>(contItem); InventoryItem item; item.mId = contItem.mItem.toString(); diff --git a/apps/essimporter/importnpcc.cpp b/apps/essimporter/importnpcc.cpp index 1b1a87ab8e..c115040074 100644 --- a/apps/essimporter/importnpcc.cpp +++ b/apps/essimporter/importnpcc.cpp @@ -7,7 +7,7 @@ namespace ESSImport void NPCC::load(ESM::ESMReader& esm) { - esm.getHNT(mNPDT, "NPDT"); + esm.getHNTSized<8>(mNPDT, "NPDT"); while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F") || esm.isNextSub("AI_A")) diff --git a/apps/essimporter/importplayer.cpp b/apps/essimporter/importplayer.cpp index aa00e45b3e..165926d15a 100644 --- a/apps/essimporter/importplayer.cpp +++ b/apps/essimporter/importplayer.cpp @@ -19,7 +19,7 @@ namespace ESSImport mMNAM = esm.getHString(); } - esm.getHNT(mPNAM, "PNAM"); + esm.getHNTSized<212>(mPNAM, "PNAM"); if (esm.isNextSub("SNAM")) esm.skipHSub(); @@ -54,7 +54,7 @@ namespace ESSImport if (esm.isNextSub("ENAM")) { mHasENAM = true; - esm.getHT(mENAM); + esm.getHTSized<8>(mENAM); } if (esm.isNextSub("LNAM")) @@ -63,7 +63,7 @@ namespace ESSImport while (esm.isNextSub("FNAM")) { FNAM fnam; - esm.getHT(fnam); + esm.getHTSized<44>(fnam); mFactions.push_back(fnam); } @@ -71,7 +71,7 @@ namespace ESSImport if (esm.isNextSub("AADT")) // Attack animation data? { mHasAADT = true; - esm.getHT(mAADT); + esm.getHTSized<44>(mAADT); } if (esm.isNextSub("KNAM")) diff --git a/apps/essimporter/importproj.cpp b/apps/essimporter/importproj.cpp index 909b228417..f9a92095e0 100644 --- a/apps/essimporter/importproj.cpp +++ b/apps/essimporter/importproj.cpp @@ -10,7 +10,7 @@ namespace ESSImport while (esm.isNextSub("PNAM")) { PNAM pnam; - esm.getHT(pnam); + esm.getHTSized<184>(pnam); mProjectiles.push_back(pnam); } } diff --git a/apps/essimporter/importscpt.cpp b/apps/essimporter/importscpt.cpp index 8768c27010..746d0b90e7 100644 --- a/apps/essimporter/importscpt.cpp +++ b/apps/essimporter/importscpt.cpp @@ -7,7 +7,7 @@ namespace ESSImport void SCPT::load(ESM::ESMReader& esm) { - esm.getHNT(mSCHD, "SCHD"); + esm.getHNTSized<52>(mSCHD, "SCHD"); mSCRI.load(esm); diff --git a/apps/essimporter/importsplm.cpp b/apps/essimporter/importsplm.cpp index b49a07cde2..a0478f4d92 100644 --- a/apps/essimporter/importsplm.cpp +++ b/apps/essimporter/importsplm.cpp @@ -11,13 +11,13 @@ namespace ESSImport { ActiveSpell spell; esm.getHT(spell.mIndex); - esm.getHNT(spell.mSPDT, "SPDT"); + esm.getHNTSized<160>(spell.mSPDT, "SPDT"); spell.mTarget = esm.getHNOString("TNAM"); while (esm.isNextSub("NPDT")) { ActiveEffect effect; - esm.getHT(effect.mNPDT); + esm.getHTSized<56>(effect.mNPDT); // Effect-specific subrecords can follow: // - INAM for disintegration and bound effects diff --git a/components/esm3/activespells.cpp b/components/esm3/activespells.cpp index 97d56d1a2b..77386c2d82 100644 --- a/components/esm3/activespells.cpp +++ b/components/esm3/activespells.cpp @@ -61,7 +61,7 @@ namespace ESM if (esm.isNextSub("WORS")) { esm.getHT(params.mWorsenings); - esm.getHNT(params.mNextWorsening, "TIME"); + esm.getHNTSized<8>(params.mNextWorsening, "TIME"); } else params.mWorsenings = -1; diff --git a/components/esm3/aisequence.cpp b/components/esm3/aisequence.cpp index 66bda9be62..1c1d3bf6ce 100644 --- a/components/esm3/aisequence.cpp +++ b/components/esm3/aisequence.cpp @@ -13,13 +13,13 @@ namespace ESM void AiWander::load(ESMReader& esm) { - esm.getHNT(mData, "DATA"); - esm.getHNT(mDurationData, "STAR"); // was mStartTime + esm.getHNTSized<14>(mData, "DATA"); + esm.getHNTSized<8>(mDurationData, "STAR"); // was mStartTime mStoredInitialActorPosition = false; if (esm.isNextSub("POS_")) { mStoredInitialActorPosition = true; - esm.getHT(mInitialActorPosition); + esm.getHTSized<12>(mInitialActorPosition); } } @@ -33,7 +33,7 @@ namespace ESM void AiTravel::load(ESMReader& esm) { - esm.getHNT(mData, "DATA"); + esm.getHNTSized<12>(mData, "DATA"); esm.getHNOT(mHidden, "HIDD"); mRepeat = false; esm.getHNOT(mRepeat, "REPT"); @@ -49,7 +49,7 @@ namespace ESM void AiEscort::load(ESMReader& esm) { - esm.getHNT(mData, "DATA"); + esm.getHNTSized<14>(mData, "DATA"); mTargetId = esm.getHNRefId("TARG"); mTargetActorId = -1; esm.getHNOT(mTargetActorId, "TAID"); @@ -81,7 +81,7 @@ namespace ESM void AiFollow::load(ESMReader& esm) { - esm.getHNT(mData, "DATA"); + esm.getHNTSized<14>(mData, "DATA"); mTargetId = esm.getHNRefId("TARG"); mTargetActorId = -1; esm.getHNOT(mTargetActorId, "TAID"); diff --git a/components/esm3/cellref.cpp b/components/esm3/cellref.cpp index 4c19abf527..2944a17db4 100644 --- a/components/esm3/cellref.cpp +++ b/components/esm3/cellref.cpp @@ -110,9 +110,13 @@ namespace ESM getHTOrSkip(cellRef.mGoldValue); break; case fourCC("DODT"): - getHTOrSkip(cellRef.mDoorDest); if constexpr (load) + { + esm.getHTSized<24>(cellRef.mDoorDest); cellRef.mTeleport = true; + } + else + esm.skipHTSized<24, ESM::Position>(); break; case fourCC("DNAM"): getHStringOrSkip(cellRef.mDestCell); diff --git a/components/esm3/cellstate.cpp b/components/esm3/cellstate.cpp index 7855aeac40..1c5514480a 100644 --- a/components/esm3/cellstate.cpp +++ b/components/esm3/cellstate.cpp @@ -16,7 +16,7 @@ namespace ESM mLastRespawn.mDay = 0; mLastRespawn.mHour = 0; - esm.getHNOT(mLastRespawn, "RESP"); + esm.getHNOTSized<8>(mLastRespawn, "RESP"); } void CellState::save(ESMWriter& esm) const diff --git a/components/esm3/creaturestats.cpp b/components/esm3/creaturestats.cpp index 9121bcb8f5..6460cada21 100644 --- a/components/esm3/creaturestats.cpp +++ b/components/esm3/creaturestats.cpp @@ -21,7 +21,7 @@ namespace ESM mTradeTime.mDay = 0; mTradeTime.mHour = 0; - esm.getHNOT(mTradeTime, "TIME"); + esm.getHNOTSized<8>(mTradeTime, "TIME"); int flags = 0; mDead = false; @@ -108,7 +108,7 @@ namespace ESM mTimeOfDeath.mDay = 0; mTimeOfDeath.mHour = 0; - esm.getHNOT(mTimeOfDeath, "DTIM"); + esm.getHNOTSized<8>(mTimeOfDeath, "DTIM"); mSpells.load(esm); mActiveSpells.load(esm); @@ -164,7 +164,7 @@ namespace ESM CorprusStats stats; esm.getHNT(stats.mWorsenings, "WORS"); - esm.getHNT(stats.mNextWorsening, "TIME"); + esm.getHNTSized<8>(stats.mNextWorsening, "TIME"); mCorprusSpells[id] = stats; } diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index b602bbd253..e92cafd67a 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -484,7 +484,7 @@ namespace ESM case RefIdType::FormId: { FormId formId{}; - getT(formId); + getTSized<8>(formId); return RefId::formIdRefId(formId); } case RefIdType::Generated: diff --git a/components/esm3/esmreader.hpp b/components/esm3/esmreader.hpp index 71611e58be..606d2a1e32 100644 --- a/components/esm3/esmreader.hpp +++ b/components/esm3/esmreader.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,9 @@ namespace ESM { + template + constexpr bool IsReadable + = std::is_arithmetic_v || std::is_enum_v || (std::is_array_v && IsReadable>); class ReadersCache; @@ -100,19 +104,17 @@ namespace ESM ESM::RefId getCellId(); // Read data of a given type, stored in a subrecord of a given name - template + template >> void getHNT(X& x, NAME name) { - getSubNameIs(name); - getHT(x); + getHNTSized(x, name); } // Optional version of getHNT - template + template >> void getHNOT(X& x, NAME name) { - if (isNextSub(name)) - getHT(x); + getHNOTSized(x, name); } // Version with extra size checking, to make sure the compiler @@ -120,34 +122,28 @@ namespace ESM template void getHNTSized(X& x, NAME name) { - static_assert(sizeof(X) == size); - getHNT(x, name); + getSubNameIs(name); + getHTSized(x); } template void getHNOTSized(X& x, NAME name) { - static_assert(sizeof(X) == size); - getHNOT(x, name); + if (isNextSub(name)) + getHTSized(x); } // Get data of a given type/size, including subrecord header - template + template >> void getHT(X& x) { - getSubHeader(); - if (mCtx.leftSub != sizeof(X)) - reportSubSizeMismatch(sizeof(X), mCtx.leftSub); - getT(x); + getHTSized(x); } - template + template >> void skipHT() { - getSubHeader(); - if (mCtx.leftSub != sizeof(T)) - reportSubSizeMismatch(sizeof(T), mCtx.leftSub); - skipT(); + skipHTSized(); } // Version with extra size checking, to make sure the compiler @@ -155,15 +151,27 @@ namespace ESM template void getHTSized(X& x) { - static_assert(sizeof(X) == size); - getHT(x); + getSubHeader(); + if (mCtx.leftSub != size) + reportSubSizeMismatch(size, mCtx.leftSub); + getTSized(x); } template void skipHTSized() { static_assert(sizeof(T) == size); - skipHT(); + getSubHeader(); + if (mCtx.leftSub != size) + reportSubSizeMismatch(size, mCtx.leftSub); + skip(size); + } + + template + void getTSized(X& x) + { + static_assert(sizeof(X) == size); + getExact(&x, size); } // Read a string by the given name if it is the next record. @@ -266,13 +274,13 @@ namespace ESM * *************************************************************************/ - template + template >> void getT(X& x) { getExact(&x, sizeof(X)); } - template + template >> void skipT() { skip(sizeof(T)); @@ -283,7 +291,7 @@ namespace ESM mEsm->read(static_cast(x), static_cast(size)); } - void getName(NAME& name) { getT(name); } + void getName(NAME& name) { getTSized<4>(name); } void getUint(uint32_t& u) { getT(u); } std::string getMaybeFixedStringSize(std::size_t size); diff --git a/components/esm3/fogstate.cpp b/components/esm3/fogstate.cpp index 65f391cefb..fda36dc113 100644 --- a/components/esm3/fogstate.cpp +++ b/components/esm3/fogstate.cpp @@ -58,7 +58,7 @@ namespace ESM void FogState::load(ESMReader& esm) { - esm.getHNOT(mBounds, "BOUN"); + esm.getHNOTSized<16>(mBounds, "BOUN"); esm.getHNOT(mNorthMarkerAngle, "ANGL"); const FormatVersion dataFormat = esm.getFormatVersion(); while (esm.isNextSub("FTEX")) diff --git a/components/esm3/globalmap.cpp b/components/esm3/globalmap.cpp index 5fb58e8e7b..6ed6976147 100644 --- a/components/esm3/globalmap.cpp +++ b/components/esm3/globalmap.cpp @@ -8,7 +8,7 @@ namespace ESM void GlobalMap::load(ESMReader& esm) { - esm.getHNT(mBounds, "BNDS"); + esm.getHNTSized<16>(mBounds, "BNDS"); esm.getSubNameIs("DATA"); esm.getSubHeader(); diff --git a/components/esm3/loadappa.cpp b/components/esm3/loadappa.cpp index f5c49dc856..793a51614b 100644 --- a/components/esm3/loadappa.cpp +++ b/components/esm3/loadappa.cpp @@ -28,7 +28,7 @@ namespace ESM mName = esm.getHString(); break; case fourCC("AADT"): - esm.getHT(mData); + esm.getHTSized<16>(mData); hasData = true; break; case fourCC("SCRI"): diff --git a/components/esm3/loadcell.cpp b/components/esm3/loadcell.cpp index 5a328d8f03..25a9878658 100644 --- a/components/esm3/loadcell.cpp +++ b/components/esm3/loadcell.cpp @@ -144,7 +144,7 @@ namespace ESM mWater = waterLevel; break; case fourCC("AMBI"): - esm.getHT(mAmbi); + esm.getHTSized<16>(mAmbi); mHasAmbi = true; break; case fourCC("RGNN"): diff --git a/components/esm3/loadregn.cpp b/components/esm3/loadregn.cpp index 31384e680d..3411d49a7c 100644 --- a/components/esm3/loadregn.cpp +++ b/components/esm3/loadregn.cpp @@ -29,7 +29,7 @@ namespace ESM // Cold weather not included before 1.3 if (esm.getSubSize() == sizeof(mData)) { - esm.getT(mData); + esm.getTSized<10>(mData); } else if (esm.getSubSize() == sizeof(mData) - 2) { diff --git a/components/esm3/loadscpt.cpp b/components/esm3/loadscpt.cpp index 1724479f4c..51752deca3 100644 --- a/components/esm3/loadscpt.cpp +++ b/components/esm3/loadscpt.cpp @@ -99,7 +99,7 @@ namespace ESM { esm.getSubHeader(); mId = esm.getMaybeFixedRefIdSize(32); - esm.getT(mData); + esm.getTSized<20>(mData); hasHeader = true; break; diff --git a/components/esm3/loadtes3.cpp b/components/esm3/loadtes3.cpp index f64acc26f4..86b62234da 100644 --- a/components/esm3/loadtes3.cpp +++ b/components/esm3/loadtes3.cpp @@ -45,7 +45,7 @@ namespace ESM if (esm.isNextSub("GMDT")) { - esm.getHT(mGameData); + esm.getHTSized<124>(mGameData); } if (esm.isNextSub("SCRD")) { diff --git a/components/esm3/objectstate.cpp b/components/esm3/objectstate.cpp index a56988843a..308d953451 100644 --- a/components/esm3/objectstate.cpp +++ b/components/esm3/objectstate.cpp @@ -35,7 +35,7 @@ namespace ESM if (esm.isNextSub("POS_")) { std::array pos; - esm.getHT(pos); + esm.getHTSized<24>(pos); memcpy(mPosition.pos, pos.data(), sizeof(float) * 3); memcpy(mPosition.rot, pos.data() + 3, sizeof(float) * 3); } diff --git a/components/esm3/projectilestate.cpp b/components/esm3/projectilestate.cpp index 2b9eccc3e8..f5242c040b 100644 --- a/components/esm3/projectilestate.cpp +++ b/components/esm3/projectilestate.cpp @@ -17,8 +17,8 @@ namespace ESM void BaseProjectileState::load(ESMReader& esm) { mId = esm.getHNRefId("ID__"); - esm.getHNT(mPosition, "VEC3"); - esm.getHNT(mOrientation, "QUAT"); + esm.getHNTSized<12>(mPosition, "VEC3"); + esm.getHNTSized<16>(mOrientation, "QUAT"); esm.getHNT(mActorId, "ACTO"); } @@ -64,7 +64,7 @@ namespace ESM BaseProjectileState::load(esm); mBowId = esm.getHNRefId("BOW_"); - esm.getHNT(mVelocity, "VEL_"); + esm.getHNTSized<12>(mVelocity, "VEL_"); mAttackStrength = 1.f; esm.getHNOT(mAttackStrength, "STR_"); diff --git a/components/esm3/spellstate.cpp b/components/esm3/spellstate.cpp index 449bf6b179..4b54bf31c9 100644 --- a/components/esm3/spellstate.cpp +++ b/components/esm3/spellstate.cpp @@ -79,7 +79,7 @@ namespace ESM CorprusStats stats; esm.getHNT(stats.mWorsenings, "WORS"); - esm.getHNT(stats.mNextWorsening, "TIME"); + esm.getHNTSized<8>(stats.mNextWorsening, "TIME"); mCorprusSpells[id] = stats; } @@ -88,7 +88,7 @@ namespace ESM { ESM::RefId id = esm.getRefId(); TimeStamp time; - esm.getHNT(time, "TIME"); + esm.getHNTSized<8>(time, "TIME"); mUsedPowers[id] = time; }