diff --git a/saveload.c b/saveload.c index 9383b55f9b..00df02bdb0 100644 --- a/saveload.c +++ b/saveload.c @@ -487,7 +487,8 @@ static void SlSaveLoadConv(void *ptr, VarType conv) * just strlen(), but if the string is not properly terminated, we'll * resort to the maximum length of the buffer. * @param ptr pointer to the stringbuffer - * @param length maximum length of the string (buffer) + * @param length maximum length of the string (buffer). If -1 we don't care + * about a maximum length, but take string length as it is. * @return return the net length of the string */ static inline size_t SlCalcNetStringLen(const char *ptr, size_t length) { @@ -505,10 +506,21 @@ static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType con size_t len; const char *str; - conv = GetVarMemType(conv); - /* For strings without a pre-allocated buffer, we need an extra indirection of course */ - str = (conv == SLE_VAR_STR || conv == SLE_VAR_STRQ) ? *(const char**)ptr : (const char*)ptr; - len = SlCalcNetStringLen(str, length); + switch (GetVarMemType(conv)) { + default: NOT_REACHED(); + case SLE_VAR_STR: + case SLE_VAR_STRQ: + str = *(const char**)ptr; + len = -1; + break; + case SLE_VAR_STRB: + case SLE_VAR_STRBQ: + str = (const char*)ptr; + len = length; + break; + } + + len = SlCalcNetStringLen(str, len); return len + SlGetArrayLength(len); // also include the length of the index } @@ -523,6 +535,7 @@ static void SlString(void *ptr, size_t length, VarType conv) if (_sl.save) { /* SAVE string */ switch (GetVarMemType(conv)) { + default: NOT_REACHED(); case SLE_VAR_STRB: case SLE_VAR_STRBQ: len = SlCalcNetStringLen(ptr, length); @@ -530,9 +543,8 @@ static void SlString(void *ptr, size_t length, VarType conv) case SLE_VAR_STR: case SLE_VAR_STRQ: ptr = *(char**)ptr; - len = SlCalcNetStringLen(ptr, 0); + len = SlCalcNetStringLen(ptr, -1); break; - default: NOT_REACHED(); } SlWriteArrayLength(len); @@ -541,6 +553,7 @@ static void SlString(void *ptr, size_t length, VarType conv) len = SlReadArrayLength(); switch (GetVarMemType(conv)) { + default: NOT_REACHED(); case SLE_VAR_STRB: case SLE_VAR_STRBQ: if (len >= length) { @@ -559,7 +572,6 @@ static void SlString(void *ptr, size_t length, VarType conv) ptr = *(char**)ptr; SlCopyBytes(ptr, len); break; - default: NOT_REACHED(); } ((char*)ptr)[len] = '\0'; // properly terminate the string @@ -642,18 +654,18 @@ static inline bool SlSkipVariableOnLoad(const SaveLoad *sld) * Calculate the size of an object. * @param sld The @SaveLoad description of the object so we know how to manipulate it */ -static size_t SlCalcObjLength(const SaveLoad *sld) +static size_t SlCalcObjLength(const void *object, const SaveLoad *sld) { size_t length = 0; // Need to determine the length and write a length tag. for (; sld->cmd != SL_END; sld++) { - length += SlCalcObjMemberLength(sld); + length += SlCalcObjMemberLength(object, sld); } return length; } -size_t SlCalcObjMemberLength(const SaveLoad *sld) +size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) { assert(_sl.save); @@ -669,12 +681,12 @@ size_t SlCalcObjMemberLength(const SaveLoad *sld) 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(sld->address, sld->length, sld->conv); + case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld->length, sld->conv); default: NOT_REACHED(); } break; case SL_WRITEBYTE: return 1; // a byte is logically of size 1 - case SL_INCLUDE: return SlCalcObjLength(_sl.includes[sld->version_from]); + case SL_INCLUDE: return SlCalcObjLength(object, _sl.includes[sld->version_from]); default: NOT_REACHED(); } return 0; @@ -746,7 +758,7 @@ void SlObject(void *object, const SaveLoad *sld) { // Automatically calculate the length? if (_sl.need_length != NL_NONE) { - SlSetLength(SlCalcObjLength(sld)); + SlSetLength(SlCalcObjLength(object, sld)); if (_sl.need_length == NL_CALCLENGTH) return; } @@ -763,7 +775,7 @@ void SlObject(void *object, const SaveLoad *sld) void SlGlobList(const SaveLoadGlobVarList *sldg) { if (_sl.need_length != NL_NONE) { - SlSetLength(SlCalcObjLength((const SaveLoad*)sldg)); + SlSetLength(SlCalcObjLength(NULL, (const SaveLoad*)sldg)); if (_sl.need_length == NL_CALCLENGTH) return; } diff --git a/saveload.h b/saveload.h index 56c3a314dc..5d490b35a2 100644 --- a/saveload.h +++ b/saveload.h @@ -289,7 +289,7 @@ int SlIterateArray(void); void SlAutolength(AutolengthProc *proc, void *arg); uint SlGetFieldLength(void); void SlSetLength(size_t length); -size_t SlCalcObjMemberLength(const SaveLoad *sld); +size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld); byte SlReadByte(void); void SlWriteByte(byte b); diff --git a/settings.c b/settings.c index 2672f202a3..4e94a97e63 100644 --- a/settings.c +++ b/settings.c @@ -1717,7 +1717,8 @@ static void SaveSettings(const SettingDesc *sd, void *object) const SettingDesc *i; size_t length = 0; for (i = sd; i->save.cmd != SL_END; i++) { - length += SlCalcObjMemberLength(&i->save); + const void *ptr = GetVariableAddress(object, &i->save); + length += SlCalcObjMemberLength(ptr, &i->save); } SlSetLength(length);