From 1c725fce47d60907bbf2224c7bdc28607fcf6017 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 18 Jan 2019 22:15:27 +0000 Subject: Change: Add ability to save/load std::deque<> containers. --- src/saveload/saveload.cpp | 129 ++++++++++++++++++++++++++++++++++++++++++++++ src/saveload/saveload.h | 11 ++++ 2 files changed, 140 insertions(+) (limited to 'src/saveload') diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 8cf5ee36b..c60c8b6db 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -21,6 +21,8 @@ *
  • repeat this until everything is done, and flush any remaining output to file * */ +#include + #include "../stdafx.h" #include "../debug.h" #include "../station_base.h" @@ -1420,6 +1422,129 @@ static void SlList(void *list, SLRefType conv) } +/** + * Template class to help with std::deque. + */ +template +class SlDequeHelper { + typedef std::deque SlDequeT; +public: + /** + * Internal templated helper to return the size in bytes of a std::deque. + * @param deque The std::deque to find the size of + * @param conv VarType type of variable that is used for calculating the size + */ + static size_t SlCalcDequeLen(const void *deque, VarType conv) + { + const SlDequeT *l = (const SlDequeT *)deque; + + int type_size = 4; + /* Each entry is saved as type_size bytes, plus type_size bytes are used for the length + * of the list */ + return l->size() * SlCalcConvFileLen(conv) + type_size; + } + + /** + * Internal templated helper to save/load a std::deque. + * @param deque The std::deque being manipulated + * @param conv VarType type of variable that is used for calculating the size + */ + static void SlDeque(void *deque, VarType conv) + { + SlDequeT *l = (SlDequeT *)deque; + + switch (_sl.action) { + case SLA_SAVE: { + SlWriteUint32((uint32)l->size()); + + typename SlDequeT::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(); + + /* Load each value and push to the end of the deque */ + for (size_t i = 0; i < length; i++) { + T data; + SlSaveLoadConv(&data, conv); + l->push_back(data); + } + break; + } + case SLA_PTRS: + break; + case SLA_NULL: + l->clear(); + break; + default: NOT_REACHED(); + } + } +}; + + +/** + * Return the size in bytes of a std::deque. + * @param deque The std::deque to find the size of + * @param conv VarType type of variable that is used for calculating the size + */ +static inline size_t SlCalcDequeLen(const void *deque, VarType conv) +{ + switch (GetVarMemType(conv)) { + case SLE_VAR_BL: + return SlDequeHelper::SlCalcDequeLen(deque, conv); + case SLE_VAR_I8: + case SLE_VAR_U8: + return SlDequeHelper::SlCalcDequeLen(deque, conv); + case SLE_VAR_I16: + case SLE_VAR_U16: + return SlDequeHelper::SlCalcDequeLen(deque, conv); + case SLE_VAR_I32: + case SLE_VAR_U32: + return SlDequeHelper::SlCalcDequeLen(deque, conv); + case SLE_VAR_I64: + case SLE_VAR_U64: + return SlDequeHelper::SlCalcDequeLen(deque, conv); + default: NOT_REACHED(); + } +} + + +/** + * Save/load a std::deque. + * @param deque The std::deque being manipulated + * @param conv VarType type of variable that is used for calculating the size + */ +static void SlDeque(void *deque, VarType conv) +{ + switch (GetVarMemType(conv)) { + case SLE_VAR_BL: + SlDequeHelper::SlDeque(deque, conv); + break; + case SLE_VAR_I8: + case SLE_VAR_U8: + SlDequeHelper::SlDeque(deque, conv); + break; + case SLE_VAR_I16: + case SLE_VAR_U16: + SlDequeHelper::SlDeque(deque, conv); + break; + case SLE_VAR_I32: + case SLE_VAR_U32: + SlDequeHelper::SlDeque(deque, conv); + break; + case SLE_VAR_I64: + case SLE_VAR_U64: + SlDequeHelper::SlDeque(deque, conv); + break; + default: NOT_REACHED(); + } +} + + /** Are we going to save this object or not? */ static inline bool SlIsObjectValidInSavegame(const SaveLoad *sld) { @@ -1471,6 +1596,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) case SL_ARR: case SL_STR: case SL_LST: + case SL_DEQUE: /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) break; @@ -1480,6 +1606,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) case SL_ARR: return SlCalcArrayLen(sld->length, sld->conv); case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv); case SL_LST: return SlCalcListLen(GetVariableAddress(object, sld)); + case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld->conv); default: NOT_REACHED(); } break; @@ -1548,6 +1675,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) case SL_ARR: case SL_STR: case SL_LST: + case SL_DEQUE: /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) return false; if (SlSkipVariableOnLoad(sld)) return false; @@ -1575,6 +1703,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) case SL_ARR: SlArray(ptr, sld->length, conv); break; case SL_STR: SlString(ptr, sld->length, sld->conv); break; case SL_LST: SlList(ptr, (SLRefType)conv); break; + case SL_DEQUE: SlDeque(ptr, conv); break; default: NOT_REACHED(); } break; diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index cca56ce07..a5ef9d58c 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -195,6 +195,7 @@ enum SaveLoadTypes { SL_ARR = 2, ///< Save/load an array. SL_STR = 3, ///< Save/load a string. SL_LST = 4, ///< Save/load a list. + SL_DEQUE = 5, ///< Save/load a deque. /* non-normal save-load types */ SL_WRITEBYTE = 8, SL_VEH_INCLUDE = 9, @@ -287,6 +288,16 @@ typedef SaveLoad SaveLoadGlobVarList; */ #define SLE_CONDLST(base, variable, type, from, to) SLE_GENERAL(SL_LST, base, variable, type, 0, from, to) +/** + * Storage of a deque 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. + */ +#define SLE_CONDDEQUE(base, variable, type, from, to) SLE_GENERAL(SL_DEQUE, base, variable, type, 0, from, to) + /** * Storage of a variable in every version of a savegame. * @param base Name of the class or struct containing the variable. -- cgit v1.2.3-54-g00ecf