C++: serialization: add version-dependent serialization support

The code always tries to serialize with the lowest possible version,
but will use the minimum version required to satisfy all settings
used in the file description.
backup
Christian Seiler 2 weeks ago
parent efc4ed8de4
commit ecf835175c
  1. 92
      cpp/src/monoformat_structured.cpp
  2. 39
      cpp/src/monoformat_structured.hpp

@ -61,7 +61,11 @@ ElementType ImageElement::elementType() const {
return ElementType::Image;
}
std::size_t ImageElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t ImageElement::minimumFormatVersion() const {
return 1;
}
std::size_t ImageElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::Image));
pos = writeU16LE(target, pos, m_x);
@ -211,7 +215,11 @@ ElementType AnimationElement::elementType() const {
return ElementType::Animation;
}
std::size_t AnimationElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t AnimationElement::minimumFormatVersion() const {
return 1;
}
std::size_t AnimationElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::Animation));
pos = writeU16LE(target, pos, m_x);
@ -367,7 +375,11 @@ ElementType HScrollImageElement::elementType() const {
return ElementType::HScrollImage;
}
std::size_t HScrollImageElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t HScrollImageElement::minimumFormatVersion() const {
return 1;
}
std::size_t HScrollImageElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::HScrollImage));
pos = writeU16LE(target, pos, m_x);
@ -613,7 +625,11 @@ ElementType VScrollImageElement::elementType() const {
return ElementType::VScrollImage;
}
std::size_t VScrollImageElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t VScrollImageElement::minimumFormatVersion() const {
return 1;
}
std::size_t VScrollImageElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::VScrollImage));
pos = writeU16LE(target, pos, m_x);
@ -831,7 +847,11 @@ ElementType LineElement::elementType() const {
return ElementType::Line;
}
std::size_t LineElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t LineElement::minimumFormatVersion() const {
return 1;
}
std::size_t LineElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::Line));
pos = writeU16LE(target, pos, m_originX);
@ -951,7 +971,11 @@ ElementType ClippedTextElement::elementType() const {
return ElementType::ClippedText;
}
std::size_t ClippedTextElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t ClippedTextElement::minimumFormatVersion() const {
return 1;
}
std::size_t ClippedTextElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::ClippedText));
pos = writeU16LE(target, pos, m_x);
@ -1083,7 +1107,11 @@ ElementType HScrollTextElement::elementType() const {
return ElementType::HScrollText;
}
std::size_t HScrollTextElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t HScrollTextElement::minimumFormatVersion() const {
return 1;
}
std::size_t HScrollTextElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::HScrollText));
pos = writeU16LE(target, pos, m_x);
@ -1300,7 +1328,11 @@ ElementType CurrentTimeElement::elementType() const {
return ElementType::CurrentTime;
}
std::size_t CurrentTimeElement::serializeTo(std::span<std::byte> target) const {
std::uint32_t CurrentTimeElement::minimumFormatVersion() const {
return 1;
}
std::size_t CurrentTimeElement::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU16LE(target, pos, static_cast<std::uint16_t>(ElementType::CurrentTime));
pos = writeU16LE(target, pos, m_x);
@ -1485,7 +1517,15 @@ SectionType AlwaysDrawnSection::sectionType() const {
return SectionType::AlwaysDrawn;
}
std::size_t AlwaysDrawnSection::serializeTo(std::span<std::byte> target) const {
std::uint32_t AlwaysDrawnSection::minimumFormatVersion() const {
std::uint32_t result = 1;
for (auto const& element : m_elements) {
result = std::max(result, element->minimumFormatVersion());
}
return result;
}
std::size_t AlwaysDrawnSection::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU8LE(target, pos, static_cast<std::uint16_t>(SectionType::AlwaysDrawn));
// Will be replaced later
@ -1498,9 +1538,9 @@ std::size_t AlwaysDrawnSection::serializeTo(std::span<std::byte> target) const {
pos = writeU16LE(target, pos, m_elements.size());
for (auto const& element : m_elements) {
if (pos < target.size()) {
pos += element->serializeTo(target.subspan(pos));
pos += element->serializeTo(target.subspan(pos), formatVersion);
} else {
pos += element->serializeTo({});
pos += element->serializeTo({}, formatVersion);
}
}
pos = alignNextWrite(target, pos, 4);
@ -1655,7 +1695,15 @@ SectionType TimeBasedDrawnSection::sectionType() const {
return SectionType::TimeBasedDrawn;
}
std::size_t TimeBasedDrawnSection::serializeTo(std::span<std::byte> target) const {
std::uint32_t TimeBasedDrawnSection::minimumFormatVersion() const {
std::uint32_t result = 1;
for (auto const& element : m_elements) {
result = std::max(result, element->minimumFormatVersion());
}
return result;
}
std::size_t TimeBasedDrawnSection::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU8LE(target, pos, static_cast<std::uint16_t>(SectionType::AlwaysDrawn));
// Will be replaced later
@ -1670,9 +1718,9 @@ std::size_t TimeBasedDrawnSection::serializeTo(std::span<std::byte> target) cons
pos = writeU64LE(target, pos, std::bit_cast<std::uint64_t>(m_endTimestamp));
for (auto const& element : m_elements) {
if (pos < target.size()) {
pos += element->serializeTo(target.subspan(pos));
pos += element->serializeTo(target.subspan(pos), formatVersion);
} else {
pos += element->serializeTo({});
pos += element->serializeTo({}, formatVersion);
}
}
pos = alignNextWrite(target, pos, 4);
@ -1764,7 +1812,11 @@ SectionType CustomFontSection::sectionType() const {
return SectionType::CustomFont;
}
std::size_t CustomFontSection::serializeTo(std::span<std::byte> target) const {
std::uint32_t CustomFontSection::minimumFormatVersion() const {
return 1;
}
std::size_t CustomFontSection::serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const {
std::size_t pos = 0;
pos = writeU8LE(target, pos, static_cast<std::uint16_t>(SectionType::AlwaysDrawn));
// Will be replaced later
@ -1817,19 +1869,23 @@ std::expected<std::unique_ptr<CustomFontSection>, ParseError> CustomFontSection:
std::size_t serializeFile(std::span<std::byte>& buffer, File const& file) {
std::size_t pos = 0;
std::uint32_t formatVersion = 1;
for (auto const& section : file.sections) {
formatVersion = std::max(formatVersion, section->minimumFormatVersion());
}
pos = writeU8LE(buffer, pos, 0xAF);
pos = writeU8LE(buffer, pos, 0x7E);
pos = writeU8LE(buffer, pos, 0x2B);
pos = writeU8LE(buffer, pos, 0x63);
pos = writeU32LE(buffer, pos, 1);
pos = writeU32LE(buffer, pos, formatVersion);
pos = writeU16LE(buffer, pos, file.sections.size());
pos = writeU16LE(buffer, pos, 0);
pos = alignNextWrite(buffer, pos, 4);
for (auto const& section : file.sections) {
if (pos < buffer.size()) {
pos += section->serializeTo(buffer.subspan(pos));
pos += section->serializeTo(buffer.subspan(pos), formatVersion);
} else {
pos += section->serializeTo({});
pos += section->serializeTo({}, formatVersion);
}
}
return pos;

@ -15,7 +15,8 @@ namespace monoformat {
struct Section {
virtual ~Section() = default;
virtual SectionType sectionType() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target) const = 0;
virtual std::uint32_t minimumFormatVersion() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const = 0;
protected:
Section() = default;
@ -26,7 +27,8 @@ class CustomFontSection;
struct Element {
virtual ~Element() = default;
virtual ElementType elementType() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target) const = 0;
virtual std::uint32_t minimumFormatVersion() const = 0;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const = 0;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) = 0;
protected:
@ -48,7 +50,8 @@ struct ImageElement : public Element {
virtual ~ImageElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<ImageElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -80,7 +83,8 @@ struct AnimationElement : public Element {
virtual ~AnimationElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<AnimationElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -113,7 +117,8 @@ struct HScrollImageElement : public Element {
virtual ~HScrollImageElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<HScrollImageElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -147,7 +152,8 @@ struct VScrollImageElement : public Element {
virtual ~VScrollImageElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<VScrollImageElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -175,7 +181,8 @@ struct LineElement : public Element {
virtual ~LineElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<LineElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -201,7 +208,8 @@ struct ClippedTextElement : public Element {
virtual ~ClippedTextElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<ClippedTextElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -229,7 +237,8 @@ struct HScrollTextElement : public Element {
virtual ~HScrollTextElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<HScrollTextElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -258,7 +267,8 @@ struct CurrentTimeElement : public Element {
virtual ~CurrentTimeElement() override;
virtual ElementType elementType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
virtual void drawTo(OneBitBufferInterface* imageBuffer, std::size_t animationTick, std::int64_t currentTimestamp, std::span<CustomFontSection const*> customFonts) override;
static std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -294,7 +304,8 @@ struct AlwaysDrawnSection : public Section {
std::unique_ptr<Element> eraseElement(std::size_t index);
virtual SectionType sectionType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
static std::expected<std::unique_ptr<AlwaysDrawnSection>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -331,7 +342,8 @@ struct TimeBasedDrawnSection : public Section {
void setEndTimestamp(std::int64_t value);
virtual SectionType sectionType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
static std::expected<std::unique_ptr<TimeBasedDrawnSection>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);
@ -352,7 +364,8 @@ struct CustomFontSection : public Section {
void setFontData(std::span<std::byte const> fontData);
virtual SectionType sectionType() const override;
virtual std::size_t serializeTo(std::span<std::byte> target) const override;
virtual std::uint32_t minimumFormatVersion() const override;
virtual std::size_t serializeTo(std::span<std::byte> target, std::uint32_t formatVersion) const override;
static std::expected<std::unique_ptr<CustomFontSection>, ParseError> parse(std::span<std::byte const>& buffer, std::uint32_t formatVersion);

Loading…
Cancel
Save