diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 89b343d579..0f012943d1 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1657,6 +1657,18 @@ static inline size_t SlCalcListLen(const void *list) return l->size() * type_size + type_size; } +/** + * Return the size in bytes of a list + * @param list The std::list to find the size of + */ + template +static inline size_t SlCalcVarListLen(const void *list, size_t item_size) +{ + const PtrList *l = (const PtrList *) list; + /* Each entry is saved as item_size bytes, plus 4 bytes are used for the length + * of the list */ + return l->size() * item_size + 4; +} /** * Save/Load a list. @@ -1715,6 +1727,55 @@ static void SlList(void *list, SLRefType conv) } } +/** + * Save/Load a list. + * @param list The list being manipulated + * @param conv VarType type of the list + */ +template +static void SlVarList(void *list, VarType conv) +{ + const size_t size_len = SlCalcConvMemLen(conv); + /* Automatically calculate the length? */ + if (_sl.need_length != NL_NONE) { + SlSetLength(SlCalcVarListLen(list, size_len)); + /* Determine length only? */ + if (_sl.need_length == NL_CALCLENGTH) return; + } + + PtrList *l = (PtrList *)list; + + switch (_sl.action) { + case SLA_SAVE: { + SlWriteUint32((uint32)l->size()); + + typename PtrList::iterator iter; + for (iter = l->begin(); iter != l->end(); ++iter) { + SlSaveLoadConv(&(*iter), conv); + } + break; + } + case SLA_LOAD_CHECK: + case SLA_LOAD: { + size_t length = SlReadUint32(); + l->resize(length); + + typename PtrList::iterator iter; + iter = l->begin(); + + for (size_t i = 0; i < length; i++) { + SlSaveLoadConv(&(*iter), conv); + ++iter; + } + break; + } + case SLA_PTRS: break; + case SLA_NULL: + l->clear(); + break; + default: NOT_REACHED(); + } +} /** Are we going to save this object or not? */ static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld) @@ -1770,6 +1831,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) case SL_DEQ: case SL_VEC: case SL_STDSTR: + case SL_VARVEC: /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) break; @@ -1781,6 +1843,16 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) case SL_LST: return SlCalcListLen>(GetVariableAddress(object, sld)); case SL_DEQ: return SlCalcListLen>(GetVariableAddress(object, sld)); case SL_VEC: return SlCalcListLen>(GetVariableAddress(object, sld)); + case SL_VARVEC: { + const size_t size_len = SlCalcConvMemLen(sld->conv); + switch (size_len) { + case 1: return SlCalcVarListLen>(GetVariableAddress(object, sld), 1); + case 2: return SlCalcVarListLen>(GetVariableAddress(object, sld), 2); + case 4: return SlCalcVarListLen>(GetVariableAddress(object, sld), 4); + case 8: return SlCalcVarListLen>(GetVariableAddress(object, sld), 8); + default: NOT_REACHED(); + } + } case SL_STDSTR: return SlCalcStdStrLen(*static_cast(GetVariableAddress(object, sld))); default: NOT_REACHED(); } @@ -1856,6 +1928,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) case SL_DEQ: case SL_VEC: case SL_STDSTR: + case SL_VARVEC: /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) return false; if (SlSkipVariableOnLoad(sld)) return false; @@ -1885,6 +1958,17 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) case SL_LST: SlList>(ptr, (SLRefType)conv); break; case SL_DEQ: SlList>(ptr, (SLRefType)conv); break; case SL_VEC: SlList>(ptr, (SLRefType)conv); break; + case SL_VARVEC: { + const size_t size_len = SlCalcConvMemLen(sld->conv); + switch (size_len) { + case 1: SlVarList>(ptr, conv); break; + case 2: SlVarList>(ptr, conv); break; + case 4: SlVarList>(ptr, conv); break; + case 8: SlVarList>(ptr, conv); break; + default: NOT_REACHED(); + } + break; + } case SL_STDSTR: SlStdString(*static_cast(ptr), sld->conv); break; default: NOT_REACHED(); } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 5bc710d7a8..39d11e30d5 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -212,6 +212,8 @@ enum SaveLoadTypes { SL_WRITEBYTE = 8, SL_VEH_INCLUDE = 9, SL_ST_INCLUDE = 10, + /* primitive type vector */ + SL_VARVEC = 14, SL_END = 15 }; @@ -349,6 +351,18 @@ typedef SaveLoad SaveLoadGlobVarList; #define SLE_CONDVEC_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_VEC, base, variable, type, 0, from, to, extver) #define SLE_CONDVEC(base, variable, type, from, to) SLE_CONDVEC_X(base, variable, type, from, to, SlXvFeatureTest()) +/** + * Storage of a variable vector in some savegame versions. + * @param base Name of the class or struct containing the list. + * @param variable Name of the variable in the class or struct referenced by \a base. + * @param type Storage of the data in memory and in the savegame. + * @param from First savegame version that has the list. + * @param to Last savegame version that has the list. + * @param extver SlXvFeatureTest to test (along with from and to) which savegames have the field + */ +#define SLE_CONDVARVEC_X(base, variable, type, from, to, extver) SLE_GENERAL_X(SL_VARVEC, base, variable, type, 0, from, to, extver) +#define SLE_CONDVARVEC(base, variable, type, from, to) SLE_CONDVARVEC_X(base, variable, type, from, to, SlXvFeatureTest()) + /** * Storage of a variable in every version of a savegame. * @param base Name of the class or struct containing the variable.