# HG changeset patch # User Darkvater # Date 2006-11-21 16:54:16 # Node ID ab9de233a12a573eb3442d413ba630d58cbaa42a # Parent f7cbf64f6127e6a6b04295e49f5a49792397cb55 (svn r7228) -Codechange: [internal] Add the possibility to save/load string-pointers which do not have a pre-allocated buffer. diff --git a/saveload.c b/saveload.c --- a/saveload.c +++ b/saveload.c @@ -489,7 +489,7 @@ static void SlSaveLoadConv(void *ptr, Va * @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( * @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(con * 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) { - len = SlCalcNetStringLen(ptr, length); + 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(); + } + SlWriteArrayLength(len); SlCopyBytes(ptr, len); - return; - } - - len = SlReadArrayLength(); + } else { /* LOAD string */ + len = SlReadArrayLength(); - 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); + 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(); + } + + ((char*)ptr)[len] = '\0'; // properly terminate the string } - - ((char*)ptr)[len] = '\0'; // properly terminate the string } /** @@ -643,7 +669,7 @@ size_t SlCalcObjMemberLength(const SaveL 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; diff --git a/saveload.h b/saveload.h --- a/saveload.h +++ b/saveload.h @@ -100,10 +100,10 @@ enum VarTypes { SLE_VAR_I64 = 7 << 4, SLE_VAR_U64 = 8 << 4, SLE_VAR_NULL = 9 << 4, ///< useful to write zeros in savegame. - SLE_VAR_STRB = 10 << 4, ///< normal string (with pre-allocated buffer) + SLE_VAR_STRB = 10 << 4, ///< string (with pre-allocated buffer) SLE_VAR_STRBQ = 11 << 4, ///< string enclosed in quotes (with pre-allocated buffer) SLE_VAR_STR = 12 << 4, ///< string pointer - SLE_VAR_STRQ = 13 << 4, ///< string enclosed in quotes + SLE_VAR_STRQ = 13 << 4, ///< string pointer enclosed in quotes /* 2 more possible memory-primitives */ /* Shortcut values */