diff options
Diffstat (limited to 'src/saveload/saveload.cpp')
-rw-r--r-- | src/saveload/saveload.cpp | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index f9eebed46..7a41f4c40 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -44,6 +44,7 @@ #include "../fios.h" #include "../error.h" #include <atomic> +#include <string> #include "table/strings.h" @@ -902,6 +903,21 @@ static inline size_t SlCalcStringLen(const void *ptr, size_t length, VarType con } /** + * Calculate the gross length of the string that it + * will occupy in the savegame. This includes the real length, returned + * by SlCalcNetStringLen and the length that the index will occupy. + * @param ptr Pointer to the \c std::string. + * @return The gross length of the string. + */ +static inline size_t SlCalcStdStringLen(const void *ptr) +{ + const std::string *str = reinterpret_cast<const std::string *>(ptr); + + size_t len = str->length(); + return len + SlGetArrayLength(len); // also include the length of the index +} + +/** * Save/Load a string. * @param ptr the string being manipulated * @param length of the string (full length) @@ -981,6 +997,53 @@ static void SlString(void *ptr, size_t length, VarType conv) } /** + * Save/Load a \c std::string. + * @param ptr the string being manipulated + * @param conv must be SLE_FILE_STRING + */ +static void SlStdString(void *ptr, VarType conv) +{ + std::string *str = reinterpret_cast<std::string *>(ptr); + + switch (_sl.action) { + case SLA_SAVE: { + size_t len = str->length(); + SlWriteArrayLength(len); + SlCopyBytes(const_cast<void *>(static_cast<const void *>(str->c_str())), len); + break; + } + + case SLA_LOAD_CHECK: + case SLA_LOAD: { + size_t len = SlReadArrayLength(); + char *buf = AllocaM(char, len + 1); + + SlCopyBytes(buf, len); + buf[len] = '\0'; // properly terminate the string + + StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK; + if ((conv & SLF_ALLOW_CONTROL) != 0) { + settings = settings | SVS_ALLOW_CONTROL_CODE; + if (IsSavegameVersionBefore(SLV_169)) { + str_fix_scc_encoded(buf, buf + len); + } + } + if ((conv & SLF_ALLOW_NEWLINE) != 0) { + settings = settings | SVS_ALLOW_NEWLINE; + } + str_validate(buf, buf + len, settings); + + // Store sanitized string. + str->assign(buf); + } + + case SLA_PTRS: break; + case SLA_NULL: break; + default: NOT_REACHED(); + } +} + +/** * Return the size in bytes of a certain type of atomic array * @param length The length of the array counted in elements * @param conv VarType type of the variable that is used in calculating the size @@ -1403,6 +1466,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) case SL_STR: case SL_LST: case SL_DEQUE: + case SL_STDSTR: /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) break; @@ -1413,6 +1477,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld) 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); + case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); default: NOT_REACHED(); } break; @@ -1461,6 +1526,10 @@ static bool IsVariableSizeRight(const SaveLoad *sld) /* These should be pointer sized, or fixed array. */ return sld->size == sizeof(void *) || sld->size == sld->length; + case SL_STDSTR: + /* These should be all pointers to std::string. */ + return sld->size == sizeof(std::string); + default: return true; } @@ -1482,6 +1551,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) case SL_STR: case SL_LST: case SL_DEQUE: + case SL_STDSTR: /* CONDITIONAL saveload types depend on the savegame version */ if (!SlIsObjectValidInSavegame(sld)) return false; if (SlSkipVariableOnLoad(sld)) return false; @@ -1510,6 +1580,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld) 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; + case SL_STDSTR: SlStdString(ptr, sld->conv); break; default: NOT_REACHED(); } break; |