From 023914d12166ea4af6e23685f96371f769cb0255 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 5 Sep 2013 21:53:33 +0200 Subject: WINTERMUTE: Disambiguate empty and NULL strings when saving The string stored is now strlen(s)+1, with length 0 indicating NULL. Increment savegame version for this new format. Old savegames are fixed by assuming VAL_STRING should never be NULL. --- .../wintermute/base/base_persistence_manager.cpp | 67 ++++++++++++---------- engines/wintermute/base/base_persistence_manager.h | 2 +- .../wintermute/base/scriptables/script_value.cpp | 11 ++++ 3 files changed, 49 insertions(+), 31 deletions(-) (limited to 'engines/wintermute/base') diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp index 2e2726f361..e5542d96b7 100644 --- a/engines/wintermute/base/base_persistence_manager.cpp +++ b/engines/wintermute/base/base_persistence_manager.cpp @@ -465,44 +465,53 @@ uint32 BasePersistenceManager::getDWORD() { ////////////////////////////////////////////////////////////////////////// -void BasePersistenceManager::putString(const Common::String &val) { - if (!val.size()) { - putString("(null)"); - } else { - _saveStream->writeUint32LE(val.size()); - _saveStream->writeString(val); +void BasePersistenceManager::putString(const char *val) { + if (!val) { + _saveStream->writeUint32LE(0); + return; } -} - -Common::String BasePersistenceManager::getStringObj() { - uint32 len = _loadStream->readUint32LE(); - char *ret = new char[len + 1]; - _loadStream->read(ret, len); - ret[len] = '\0'; - Common::String retString = ret; - delete[] ret; + uint32 len = strlen(val); - if (retString == "(null)") { - retString = ""; - } + _saveStream->writeUint32LE(len + 1); + _saveStream->write(val, len); +} - return retString; +Common::String BasePersistenceManager::getStringObj() { + return getString(); } ////////////////////////////////////////////////////////////////////////// char *BasePersistenceManager::getString() { uint32 len = _loadStream->readUint32LE(); - char *ret = new char[len + 1]; - _loadStream->read(ret, len); - ret[len] = '\0'; - if (!strcmp(ret, "(null)")) { - delete[] ret; - return nullptr; + if (checkVersion(1,2,2)) { + // Version 1.2.2 and above: len == strlen() + 1, NULL has len == 0 + + if (len == 0) + return nullptr; + + char *ret = new char[len]; + _loadStream->read(ret, len - 1); + ret[len - 1] = '\0'; + + return ret; + } else { + + // Version 1.2.1 and older: NULL strings are represented as "(null)" + char *ret = new char[len + 1]; + _loadStream->read(ret, len); + ret[len] = '\0'; + + if (!strcmp(ret, "(null)")) { + delete[] ret; + return nullptr; + } + return ret; } + } bool BasePersistenceManager::putTimeDate(const TimeDate &t) { @@ -536,8 +545,7 @@ void BasePersistenceManager::putFloat(float val) { int exponent = 0; float significand = frexp(val, &exponent); Common::String str = Common::String::format("FS%f", significand); - _saveStream->writeUint32LE(str.size()); - _saveStream->writeString(str); + putString(str.c_str()); _saveStream->writeSint32LE(exponent); } @@ -559,8 +567,7 @@ void BasePersistenceManager::putDouble(double val) { int exponent = 0; double significand = frexp(val, &exponent); Common::String str = Common::String::format("DS%f", significand); - _saveStream->writeUint32LE(str.size()); - _saveStream->writeString(str); + putString(str.c_str()); _saveStream->writeSint32LE(exponent); } @@ -711,7 +718,7 @@ bool BasePersistenceManager::transfer(const char *name, const char **val) { // Common::String bool BasePersistenceManager::transfer(const char *name, Common::String *val) { if (_saving) { - putString(*val); + putString(val->c_str()); return STATUS_OK; } else { char *str = getString(); diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h index c09b3345b7..3c0587b362 100644 --- a/engines/wintermute/base/base_persistence_manager.h +++ b/engines/wintermute/base/base_persistence_manager.h @@ -52,7 +52,7 @@ public: void putDWORD(uint32 val); char *getString(); Common::String getStringObj(); - void putString(const Common::String &val); + void putString(const char *val); float getFloat(); void putFloat(float val); double getDouble(); diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp index 3532e127d0..31ec457df1 100644 --- a/engines/wintermute/base/scriptables/script_value.cpp +++ b/engines/wintermute/base/scriptables/script_value.cpp @@ -827,6 +827,17 @@ bool ScValue::persist(BasePersistenceManager *persistMgr) { persistMgr->transferPtr(TMEMBER_PTR(_valRef)); persistMgr->transfer(TMEMBER(_valString)); + if (!persistMgr->getIsSaving() && !persistMgr->checkVersion(1,2,2)) { + // Savegames prior to 1.2.2 stored empty strings as NULL. + // We disambiguate those by turning NULL strings into empty + // strings if _type is VAL_STRING instead of VAL_NULL. + + if (_type == VAL_STRING && !_valString) { + _valString = new char[1]; + _valString[0] = '\0'; + } + } + /* // TODO: Convert to Debug-statements. FILE* f = fopen("c:\\val.log", "a+"); switch(_type) -- cgit v1.2.3