diff options
Diffstat (limited to 'saveload.c')
-rw-r--r-- | saveload.c | 78 |
1 files changed, 52 insertions, 26 deletions
diff --git a/saveload.c b/saveload.c index 21e537084..433229a72 100644 --- a/saveload.c +++ b/saveload.c @@ -489,7 +489,7 @@ static void SlSaveLoadConv(void *ptr, VarType conv) * @param ptr pointer to the stringbuffer * @param length maximum length of the string (buffer) * @return return the net length of the string */ -static inline size_t SlCalcNetStringLen(const char *ptr, uint length) +static inline size_t SlCalcNetStringLen(const char *ptr, size_t length) { return minu(strlen(ptr), length - 1); } @@ -500,9 +500,15 @@ static inline size_t SlCalcNetStringLen(const char *ptr, uint length) * @param ptr pointer to the stringbuffer * @param length maximum length of the string (buffer size, etc.) * @return return the gross length of the string */ -static inline size_t SlCalcStringLen(const char *ptr, uint length) +static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType conv) { - uint len = SlCalcNetStringLen(ptr, length); + 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); return len + SlGetArrayLength(len); // also include the length of the index } @@ -510,34 +516,54 @@ static inline size_t SlCalcStringLen(const char *ptr, uint length) * Save/Load a string. * @param ptr the string being manipulated * @param the length of the string (full length) - * @param conv must be SLE_FILE_STRING - * XXX - only works with global strings of a pre-allocated buffer */ -static void SlString(void *ptr, uint length, VarType conv) + * @param conv must be SLE_FILE_STRING */ +static void SlString(void *ptr, size_t length, VarType conv) { - uint len; - assert(GetVarFileType(conv) == SLE_FILE_STRING); - assert(GetVarMemType(conv) == SLE_VAR_STRB || GetVarMemType(conv) == SLE_VAR_STRBQ); - assert(ptr != NULL); + size_t len; + + if (_sl.save) { /* SAVE string */ + switch (GetVarMemType(conv)) { + case SLE_VAR_STRB: + case SLE_VAR_STRBQ: + len = SlCalcNetStringLen(ptr, length); + break; + case SLE_VAR_STR: + case SLE_VAR_STRQ: + ptr = *(char**)ptr; + len = SlCalcNetStringLen(ptr, 0); + break; + default: NOT_REACHED(); + } - if (_sl.save) { - len = SlCalcNetStringLen(ptr, length); SlWriteArrayLength(len); SlCopyBytes(ptr, len); - return; - } - - len = SlReadArrayLength(); + } else { /* LOAD string */ + len = SlReadArrayLength(); + + switch (GetVarMemType(conv)) { + case SLE_VAR_STRB: + case SLE_VAR_STRBQ: + if (len >= length) { + DEBUG(misc, 0) ("[Sl] String length in savegame is bigger than buffer, truncating"); + SlCopyBytes(ptr, length); + SlSkipBytes(len - length); + len = length - 1; + } else { + SlCopyBytes(ptr, len); + } + break; + case SLE_VAR_STR: + case SLE_VAR_STRQ: /* Malloc'd string, free previous incarnation, and allocate */ + free(*(char**)ptr); + *(char**)ptr = malloc(len + 1); // terminating '\0' + ptr = *(char**)ptr; + SlCopyBytes(ptr, len); + break; + default: NOT_REACHED(); + } - if (len >= length) { - DEBUG(misc, 0) ("[Sl] String length in savegame is bigger than buffer, truncating"); - SlCopyBytes(ptr, length); - SlSkipBytes(len - length); - len = length - 1; - } else { - SlCopyBytes(ptr, len); + ((char*)ptr)[len] = '\0'; // properly terminate the string } - - ((char*)ptr)[len] = '\0'; // properly terminate the string } /** @@ -643,7 +669,7 @@ 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); + case SL_STR: return SlCalcStringLen(sld->address, sld->length, sld->conv); default: NOT_REACHED(); } break; |