diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index 008aaebf9e..20f4894c57 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -110,6 +110,10 @@ template<> struct DataSerializerTraits_t : public DataSerializerTraitsIn { }; +template<> struct DataSerializerTraits_t : public DataSerializerTraitsIntegral +{ +}; + template<> struct DataSerializerTraits_t : public DataSerializerTraitsIntegral { }; @@ -141,6 +145,10 @@ template<> struct DataSerializerTraits_t uint16_t len = static_cast(str.size()); uint16_t swapped = ByteSwapBE(len); stream->Write(&swapped); + if (len == 0) + { + return; + } stream->WriteArray(str.c_str(), len); } static void decode(OpenRCT2::IStream* stream, std::string& res) @@ -148,7 +156,11 @@ template<> struct DataSerializerTraits_t uint16_t len; stream->Read(&len); len = ByteSwapBE(len); - + if (len == 0) + { + res = ""; + return; + } const char* str = stream->ReadArray(len); res.assign(str, len); @@ -157,7 +169,10 @@ template<> struct DataSerializerTraits_t static void log(OpenRCT2::IStream* stream, const std::string& str) { stream->Write("\"", 1); - stream->Write(str.data(), str.size()); + if (str.size() != 0) + { + stream->Write(str.data(), str.size()); + } stream->Write("\"", 1); } }; @@ -327,6 +342,10 @@ template struct DataSerializerTraits_t : public Da { }; +template struct DataSerializerTraits_t : public DataSerializerTraitsPODArray +{ +}; + template struct DataSerializerTraits_t : public DataSerializerTraitsPODArray { }; diff --git a/src/openrct2/core/FileIndex.hpp b/src/openrct2/core/FileIndex.hpp index 6a6fab1fd8..f536536692 100644 --- a/src/openrct2/core/FileIndex.hpp +++ b/src/openrct2/core/FileIndex.hpp @@ -11,6 +11,7 @@ #include "../common.h" #include "Console.hpp" +#include "DataSerialiser.h" #include "File.h" #include "FileScanner.h" #include "FileStream.h" @@ -130,14 +131,9 @@ protected: virtual std::tuple Create(int32_t language, const std::string& path) const abstract; /** - * Serialises an index item to the given stream. + * Serialises/DeSerialises an index item to/from the given stream. */ - virtual void Serialise(OpenRCT2::IStream* stream, const TItem& item) const abstract; - - /** - * Deserialises an index item from the given stream. - */ - virtual TItem Deserialise(OpenRCT2::IStream* stream) const abstract; + virtual void Serialise(DataSerialiser& ds, TItem& item) const abstract; private: ScanResult Scan() const @@ -272,10 +268,12 @@ private: && header.Stats.PathChecksum == stats.PathChecksum) { items.reserve(header.NumItems); + DataSerialiser ds(false, fs); // Directory is the same, just read the saved items for (uint32_t i = 0; i < header.NumItems; i++) { - auto item = Deserialise(&fs); + TItem item; + Serialise(ds, item); items.emplace_back(std::move(item)); } loadedItems = true; @@ -294,7 +292,7 @@ private: return std::make_tuple(loadedItems, std::move(items)); } - void WriteIndexFile(int32_t language, const DirectoryStats& stats, const std::vector& items) const + void WriteIndexFile(int32_t language, const DirectoryStats& stats, std::vector& items) const { try { @@ -312,10 +310,11 @@ private: header.NumItems = static_cast(items.size()); fs.WriteValue(header); + DataSerialiser ds(true, fs); // Write items - for (const auto& item : items) + for (auto& item : items) { - Serialise(&fs, item); + Serialise(ds, item); } } catch (const std::exception& e) diff --git a/src/openrct2/core/FileStream.cpp b/src/openrct2/core/FileStream.cpp index a60b4f9aac..3310c86e53 100644 --- a/src/openrct2/core/FileStream.cpp +++ b/src/openrct2/core/FileStream.cpp @@ -168,6 +168,10 @@ namespace OpenRCT2 void FileStream::Write(const void* buffer, uint64_t length) { + if (length == 0) + { + return; + } if (fwrite(buffer, static_cast(length), 1, _file) != 1) { throw IOException("Unable to write to file."); diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index f79e16edd0..5b6ad4e929 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -76,7 +76,7 @@ class ObjectFileIndex final : public FileIndex { private: static constexpr uint32_t MAGIC_NUMBER = 0x5844494F; // OIDX - static constexpr uint16_t VERSION = 25; + static constexpr uint16_t VERSION = 26; static constexpr auto PATTERN = "*.dat;*.pob;*.json;*.parkobj"; IObjectRepository& _objectRepository; @@ -126,48 +126,26 @@ public: } protected: - void Serialise(IStream* stream, const ObjectRepositoryItem& item) const override + void Serialise(DataSerialiser& ds, ObjectRepositoryItem& item) const override { - stream->WriteString(item.Identifier); - stream->WriteValue(item.ObjectEntry); - stream->WriteString(item.Path); - stream->WriteString(item.Name); + ds << item.Identifier; + ds << item.ObjectEntry; + ds << item.Path; + ds << item.Name; - uint8_t sourceLength = static_cast(item.Sources.size()); - stream->WriteValue(sourceLength); - for (auto source : item.Sources) - { - stream->WriteValue(source); - } - - uint8_t authorsLength = static_cast(item.Authors.size()); - stream->WriteValue(authorsLength); - for (const auto& author : item.Authors) - { - stream->WriteString(author); - } + ds << item.Sources; + ds << item.Authors; switch (item.ObjectEntry.GetType()) { case ObjectType::Ride: - stream->WriteValue(item.RideInfo.RideFlags); - for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++) - { - stream->WriteValue(item.RideInfo.RideCategory[i]); - } - for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) - { - stream->WriteValue(item.RideInfo.RideType[i]); - } + ds << item.RideInfo.RideFlags; + ds << item.RideInfo.RideCategory; + ds << item.RideInfo.RideType; break; case ObjectType::SceneryGroup: { - stream->WriteValue(static_cast(item.SceneryGroupInfo.Entries.size())); - DataSerialiser serialiser(true, *stream); - for (const auto& entry : item.SceneryGroupInfo.Entries) - { - serialiser << entry; - } + ds << item.SceneryGroupInfo.Entries; break; } default: @@ -176,60 +154,6 @@ protected: } } - ObjectRepositoryItem Deserialise(IStream* stream) const override - { - ObjectRepositoryItem item; - - item.Identifier = stream->ReadStdString(); - item.ObjectEntry = stream->ReadValue(); - item.Path = stream->ReadStdString(); - item.Name = stream->ReadStdString(); - - auto sourceLength = stream->ReadValue(); - for (size_t i = 0; i < sourceLength; i++) - { - auto value = stream->ReadValue(); - item.Sources.push_back(static_cast(value)); - } - - auto authorsLength = stream->ReadValue(); - for (size_t i = 0; i < authorsLength; i++) - { - auto author = stream->ReadStdString(); - item.Authors.emplace_back(author); - } - - switch (item.ObjectEntry.GetType()) - { - case ObjectType::Ride: - item.RideInfo.RideFlags = stream->ReadValue(); - for (int32_t i = 0; i < MAX_CATEGORIES_PER_RIDE; i++) - { - item.RideInfo.RideCategory[i] = stream->ReadValue(); - } - for (int32_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) - { - item.RideInfo.RideType[i] = stream->ReadValue(); - } - break; - case ObjectType::SceneryGroup: - { - auto numEntries = stream->ReadValue(); - item.SceneryGroupInfo.Entries = std::vector(numEntries); - DataSerialiser serialiser(false, *stream); - for (size_t i = 0; i < numEntries; i++) - { - serialiser << item.SceneryGroupInfo.Entries[i]; - } - break; - } - default: - // Switch processes only ObjectType::Ride and ObjectType::SceneryGroup - break; - } - return item; - } - private: bool IsTrackReadOnly(const std::string& path) const { diff --git a/src/openrct2/ride/TrackDesignRepository.cpp b/src/openrct2/ride/TrackDesignRepository.cpp index 7e215c9aed..0b15b0ea71 100644 --- a/src/openrct2/ride/TrackDesignRepository.cpp +++ b/src/openrct2/ride/TrackDesignRepository.cpp @@ -57,7 +57,7 @@ class TrackDesignFileIndex final : public FileIndex { private: static constexpr uint32_t MAGIC_NUMBER = 0x58444954; // TIDX - static constexpr uint16_t VERSION = 3; + static constexpr uint16_t VERSION = 4; static constexpr auto PATTERN = "*.td4;*.td6"; public: @@ -97,24 +97,13 @@ public: } protected: - void Serialise(IStream* stream, const TrackRepositoryItem& item) const override + void Serialise(DataSerialiser& ds, TrackRepositoryItem& item) const override { - stream->WriteString(item.Name); - stream->WriteString(item.Path); - stream->WriteValue(item.RideType); - stream->WriteString(item.ObjectEntry); - stream->WriteValue(item.Flags); - } - - TrackRepositoryItem Deserialise(IStream* stream) const override - { - TrackRepositoryItem item; - item.Name = stream->ReadStdString(); - item.Path = stream->ReadStdString(); - item.RideType = stream->ReadValue(); - item.ObjectEntry = stream->ReadStdString(); - item.Flags = stream->ReadValue(); - return item; + ds << item.Name; + ds << item.Path; + ds << item.RideType; + ds << item.ObjectEntry; + ds << item.Flags; } private: diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index 1c8e496c52..807b734e3d 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -129,7 +129,7 @@ class ScenarioFileIndex final : public FileIndex { private: static constexpr uint32_t MAGIC_NUMBER = 0x58444953; // SIDX - static constexpr uint16_t VERSION = 3; + static constexpr uint16_t VERSION = 4; static constexpr auto PATTERN = "*.sc4;*.sc6;*.sea"; public: @@ -159,49 +159,22 @@ protected: } } - void Serialise(IStream* stream, const scenario_index_entry& item) const override + void Serialise(DataSerialiser& ds, scenario_index_entry& item) const override { - stream->Write(item.path, sizeof(item.path)); - stream->WriteValue(item.timestamp); + ds << item.path; + ds << item.timestamp; + ds << item.category; + ds << item.source_game; + ds << item.source_index; + ds << item.sc_id; + ds << item.objective_type; + ds << item.objective_arg_1; + ds << item.objective_arg_2; + ds << item.objective_arg_3; - stream->WriteValue(item.category); - stream->WriteValue(item.source_game); - stream->WriteValue(item.source_index); - stream->WriteValue(item.sc_id); - - stream->WriteValue(item.objective_type); - stream->WriteValue(item.objective_arg_1); - stream->WriteValue(item.objective_arg_2); - stream->WriteValue(item.objective_arg_3); - - stream->Write(item.internal_name, sizeof(item.internal_name)); - stream->Write(item.name, sizeof(item.name)); - stream->Write(item.details, sizeof(item.details)); - } - - scenario_index_entry Deserialise(IStream* stream) const override - { - scenario_index_entry item; - - stream->Read(item.path, sizeof(item.path)); - item.timestamp = stream->ReadValue(); - - item.category = stream->ReadValue(); - item.source_game = ScenarioSource{ stream->ReadValue() }; - item.source_index = stream->ReadValue(); - item.sc_id = stream->ReadValue(); - - item.objective_type = stream->ReadValue(); - item.objective_arg_1 = stream->ReadValue(); - item.objective_arg_2 = stream->ReadValue(); - item.objective_arg_3 = stream->ReadValue(); - item.highscore = nullptr; - - stream->Read(item.internal_name, sizeof(item.internal_name)); - stream->Read(item.name, sizeof(item.name)); - stream->Read(item.details, sizeof(item.details)); - - return item; + ds << item.internal_name; + ds << item.name; + ds << item.details; } private: