Skip to content

Commit

Permalink
Engine: encase savegame components in global tags
Browse files Browse the repository at this point in the history
This is to explicitly mark the beginning and the end of the components data list in the file. Fixes an issue with screenshots that are appended to the end of the save file.
  • Loading branch information
ivan-mogilko committed Oct 25, 2017
1 parent 1efeae1 commit cfa4c38
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 11 deletions.
4 changes: 4 additions & 0 deletions Engine/game/savegame.cpp
Expand Up @@ -131,6 +131,10 @@ String GetSavegameErrorText(SavegameError err)
return "Save was written by incompatible engine, or file is corrupted";
case kSvgErr_GameGuidMismatch:
return "Game GUID does not match, saved by a different game";
case kSvgErr_ComponentListOpeningTagFormat:
return "Failed to parse opening tag of the components list";
case kSvgErr_ComponentListClosingTagMissing:
return "Closing tag of the components list was not met";
case kSvgErr_ComponentOpeningTagFormat:
return "Failed to parse opening component tag";
case kSvgErr_ComponentClosingTagFormat:
Expand Down
3 changes: 2 additions & 1 deletion Engine/game/savegame.h
Expand Up @@ -60,6 +60,8 @@ enum SavegameError
kSvgErr_FormatVersionNotSupported,
kSvgErr_IncompatibleEngine,
kSvgErr_GameGuidMismatch,
kSvgErr_ComponentListOpeningTagFormat,
kSvgErr_ComponentListClosingTagMissing,
kSvgErr_ComponentOpeningTagFormat,
kSvgErr_ComponentClosingTagFormat,
kSvgErr_ComponentSizeMismatch,
Expand All @@ -71,7 +73,6 @@ enum SavegameError
kSvgErr_InconsistentPlugin,
kSvgErr_DifferentColorDepth,
kSvgErr_GameObjectInitFailed,
kSvgErr_ExpectedEOS,
kNumSavegameError
};

Expand Down
32 changes: 22 additions & 10 deletions Engine/game/savegame_components.cpp
Expand Up @@ -76,6 +76,8 @@ namespace Engine
namespace SavegameComponents
{

const String ComponentListTag = "Components";

void WriteFormatTag(PStream out, const String &tag, bool open = true)
{
String full_tag = String::FromFormat(open ? "<%s>" : "</%s>", tag.GetCStr());
Expand Down Expand Up @@ -1074,11 +1076,8 @@ SavegameError ReadComponent(PStream in, SvgCmpReadHelper &hlp, ComponentInfo &in
size_t pos = in->GetPosition();
info = ComponentInfo(); // reset in case of early error
info.Offset = in->GetPosition();
if (!ReadFormatTag(in, info.Name, true)) {
if (in->EOS())
return kSvgErr_ExpectedEOS; // report end of stream (expected case)
if (!ReadFormatTag(in, info.Name, true))
return kSvgErr_ComponentOpeningTagFormat;
}
info.Version = in->ReadInt32();
info.DataSize = in->ReadInt32();
info.DataOffset = in->GetPosition();
Expand Down Expand Up @@ -1108,21 +1107,32 @@ SavegameError ReadAll(PStream in, SavegameVersion svg_version, const PreservedPa
SvgCmpReadHelper hlp(svg_version, pp, r_data);
GenerateHandlersMap(hlp.Handlers);

while (!in->EOS())
size_t idx = 0;
if (!AssertFormatTag(in, ComponentListTag, true))
return kSvgErr_ComponentListOpeningTagFormat;
do
{
// Look out for the end of the component list:
// this is the only way how this function ends with success
size_t off = in->GetPosition();
if (AssertFormatTag(in, ComponentListTag, false))
return kSvgErr_NoError;
// If the list's end was not detected, then seek back and continue reading
in->Seek(off, kSeekBegin);

ComponentInfo info;
SavegameError err = ReadComponent(in, hlp, info);
if (err == kSvgErr_ExpectedEOS)
break; // this is normal
if (err != kSvgErr_NoError)
{
Debug::Printf(kDbgMsg_Error, "ERROR: failed to read savegame component: type = %s, version = %i, at offset = %u",
info.Name.GetCStr(), info.Version, info.Offset);
Debug::Printf(kDbgMsg_Error, "ERROR: failed to read savegame component: index = %d, type = %s, version = %i, at offset = %u",
idx, info.Name.IsEmpty() ? "unknown" : info.Name.GetCStr(), info.Version, info.Offset);
return err;
}
update_polled_stuff_if_runtime();
idx++;
}
return kSvgErr_NoError;
while (!in->EOS());
return kSvgErr_ComponentListClosingTagMissing;
}

SavegameError WriteComponent(PStream out, ComponentHandler &hdlr)
Expand All @@ -1143,6 +1153,7 @@ SavegameError WriteComponent(PStream out, ComponentHandler &hdlr)

SavegameError WriteAllCommon(PStream out)
{
WriteFormatTag(out, ComponentListTag, true);
for (int type = 0; !ComponentHandlers[type].Name.IsEmpty(); ++type)
{
SavegameError err = WriteComponent(out, ComponentHandlers[type]);
Expand All @@ -1153,6 +1164,7 @@ SavegameError WriteAllCommon(PStream out)
}
update_polled_stuff_if_runtime();
}
WriteFormatTag(out, ComponentListTag, false);
return kSvgErr_NoError;
}

Expand Down

0 comments on commit cfa4c38

Please sign in to comment.