# HG changeset patch # User Patric Stout # Date 2021-06-15 09:59:38 # Node ID 265cb5def15f3f3d0d9e8bed8d10dd001569804a # Parent 08b2e668e823d3d82045e83fb0c5eaaf26b8df4a Codechange: use SL_NULL if you want to store null-bytes or load to nothing Using SL_ARR for this gives us a bit of trouble later on, where we add a length-field to SL_ARR. This of course is not the intention of SLE_CONDNULL. So better seperate it. diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1425,33 +1425,21 @@ size_t SlCalcObjMemberLength(const void { assert(_sl.action == SLA_SAVE); + if (!SlIsObjectValidInSavegame(sld)) return 0; + switch (sld.cmd) { - case SL_VAR: - case SL_REF: - case SL_ARR: - case SL_STR: - case SL_REFLIST: - case SL_DEQUE: - case SL_STDSTR: - /* CONDITIONAL saveload types depend on the savegame version */ - if (!SlIsObjectValidInSavegame(sld)) break; - - switch (sld.cmd) { - case SL_VAR: return SlCalcConvFileLen(sld.conv); - case SL_REF: return SlCalcRefLen(); - case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); - case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); - case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); - case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); - case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); - default: NOT_REACHED(); - } - break; + case SL_VAR: return SlCalcConvFileLen(sld.conv); + case SL_REF: return SlCalcRefLen(); + case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); + case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); + case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); + case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); + case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); case SL_SAVEBYTE: return 1; // a byte is logically of size 1 + case SL_NULL: return SlCalcConvFileLen(sld.conv) * sld.length; + case SL_STRUCT: case SL_STRUCTLIST: { - if (!SlIsObjectValidInSavegame(sld)) break; - NeedLength old_need_length = _sl.need_length; size_t old_obj_len = _sl.obj_len; @@ -1473,6 +1461,7 @@ size_t SlCalcObjMemberLength(const void return length; } + default: NOT_REACHED(); } return 0; @@ -1530,6 +1519,8 @@ static bool SlObjectMember(void *object, { assert(IsVariableSizeRight(sld)); + if (!SlIsObjectValidInSavegame(sld)) return false; + VarType conv = GB(sld.conv, 0, 8); switch (sld.cmd) { case SL_VAR: @@ -1539,9 +1530,6 @@ static bool SlObjectMember(void *object, case SL_REFLIST: case SL_DEQUE: case SL_STDSTR: { - /* CONDITIONAL saveload types depend on the savegame version */ - if (!SlIsObjectValidInSavegame(sld)) return false; - void *ptr = GetVariableAddress(object, sld); switch (sld.cmd) { @@ -1574,10 +1562,22 @@ static bool SlObjectMember(void *object, break; } + case SL_NULL: { + assert(GetVarMemType(sld.conv) == SLE_VAR_NULL); + + switch (_sl.action) { + case SLA_LOAD_CHECK: + case SLA_LOAD: SlSkipBytes(SlCalcConvFileLen(sld.conv) * sld.length); break; + case SLA_SAVE: for (int i = 0; i < SlCalcConvFileLen(sld.conv) * sld.length; i++) SlWriteByte(0); break; + case SLA_PTRS: + case SLA_NULL: break; + default: NOT_REACHED(); + } + break; + } + case SL_STRUCT: case SL_STRUCTLIST: - if (!SlIsObjectValidInSavegame(sld)) return false; - switch (_sl.action) { case SLA_SAVE: { if (sld.cmd == SL_STRUCT) { diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -573,6 +573,7 @@ enum SaveLoadType : byte { SL_STRUCT = 7, ///< Save/load a struct. SL_STRUCTLIST = 8, ///< Save/load a list of structs. SL_SAVEBYTE = 9, ///< Save (but not load) a byte. + SL_NULL = 10, ///< Save null-bytes and load to nowhere. }; typedef void *SaveLoadAddrProc(void *base, size_t extra); @@ -737,7 +738,7 @@ struct SaveLoad { * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLE_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} +#define SLE_CONDNULL(length, from, to) {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} /** * Only write byte during saving; never read it during loading. @@ -895,7 +896,7 @@ struct SaveLoad { * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLEG_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} +#define SLEG_CONDNULL(length, from, to) {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} /** * Checks whether the savegame is below \a major.\a minor.