C++/Structured: implement parsing logic

pull/1/head^2
Christian Seiler 4 weeks ago
parent 51f60eb817
commit 41738b4a3b
  1. 1
      cpp/src/monoformat_parsehelpers.hpp
  2. 581
      cpp/src/monoformat_structured.cpp
  3. 4
      cpp/src/monoformat_structured.hpp

@ -11,6 +11,7 @@ namespace monoformat {
enum class ParseError { enum class ParseError {
BufferSizeMismatch = 1, BufferSizeMismatch = 1,
InvalidValue = 2,
}; };
inline std::expected<std::uint8_t, ParseError> peekU8LE(std::span<std::byte const> buffer) { inline std::expected<std::uint8_t, ParseError> peekU8LE(std::span<std::byte const> buffer) {

@ -114,6 +114,12 @@ ConstMemoryOneBitBuffer ImageElement::image() const noexcept {
return ConstMemoryOneBitBuffer{m_buffer, m_width, m_height}; return ConstMemoryOneBitBuffer{m_buffer, m_width, m_height};
} }
void ImageElement::updateBuffer(std::span<std::byte const> newBufferData) {
std::size_t n = std::min(m_buffer.size(), newBufferData.size());
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin());
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{});
}
ImageElement::~ImageElement() { ImageElement::~ImageElement() {
} }
@ -138,7 +144,46 @@ void ImageElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t animat
} }
std::expected<std::unique_ptr<ImageElement>, ParseError> ImageElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<ImageElement>, ParseError> ImageElement::parse(std::span<std::byte const>& buffer) {
// FIXME: parse auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::Image)) {
return std::unexpected(ParseError::InvalidValue);
}
auto x = readU16LE(buffer);
if (!x) {
return std::unexpected(x.error());
}
auto y = readU16LE(buffer);
if (!y) {
return std::unexpected(y.error());
}
auto width = readU16LE(buffer);
if (!width) {
return std::unexpected(width.error());
}
auto height = readU16LE(buffer);
if (!height) {
return std::unexpected(height.error());
}
auto reserved_ = readU16LE(buffer);
if (!reserved_) {
return std::unexpected(reserved_.error());
}
std::size_t imageSize = ((*width) * (*height) + 8 - 1) / 8;
auto imageData = readBuffer(buffer, imageSize);
if (!imageData) {
return std::unexpected(reserved_.error());
}
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4;
if (imageSize < rounded) {
buffer = buffer.subspan(rounded - imageSize);
}
auto result = std::make_unique<ImageElement>(*x, *y, *width, *height);
result->updateBuffer(*imageData);
return result;
} }
AnimationElement::AnimationElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t numberOfFrames, std::uint16_t updateInterval) AnimationElement::AnimationElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t numberOfFrames, std::uint16_t updateInterval)
@ -209,6 +254,12 @@ ConstMemoryOneBitBuffer AnimationElement::image(std::uint16_t frameIndex) const
return ConstMemoryOneBitBuffer{buffer(frameIndex), m_width, m_height}; return ConstMemoryOneBitBuffer{buffer(frameIndex), m_width, m_height};
} }
void AnimationElement::updateBuffer(std::span<std::byte const> newBufferData) {
std::size_t n = std::min(m_buffer.size(), newBufferData.size());
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin());
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{});
}
AnimationElement::~AnimationElement() { AnimationElement::~AnimationElement() {
} }
@ -235,7 +286,54 @@ void AnimationElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t an
} }
std::expected<std::unique_ptr<AnimationElement>, ParseError> AnimationElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<AnimationElement>, ParseError> AnimationElement::parse(std::span<std::byte const>& buffer) {
// FIXME: implement this auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::Animation)) {
return std::unexpected(ParseError::InvalidValue);
}
auto x = readU16LE(buffer);
if (!x) {
return std::unexpected(x.error());
}
auto y = readU16LE(buffer);
if (!y) {
return std::unexpected(y.error());
}
auto width = readU16LE(buffer);
if (!width) {
return std::unexpected(width.error());
}
auto height = readU16LE(buffer);
if (!height) {
return std::unexpected(height.error());
}
auto numberOfFrames = readU16LE(buffer);
if (!numberOfFrames) {
return std::unexpected(numberOfFrames.error());
}
auto updateInterval = readU16LE(buffer);
if (!updateInterval) {
return std::unexpected(updateInterval.error());
}
auto reserved_ = readU16LE(buffer);
if (!reserved_) {
return std::unexpected(reserved_.error());
}
std::size_t imageSize = ((*width) * (*height) + 8 - 1) / 8;
auto imageData = readBuffer(buffer, imageSize);
if (!imageData) {
return std::unexpected(reserved_.error());
}
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4;
if (imageSize < rounded) {
buffer = buffer.subspan(rounded - imageSize);
}
auto result = std::make_unique<AnimationElement>(*x, *y, *width, *height, *numberOfFrames, *updateInterval);
result->updateBuffer(*imageData);
return result;
} }
HScrollImageElement::HScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentWidth, std::uint8_t flags, std::uint8_t scrollSpeed) HScrollImageElement::HScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentWidth, std::uint8_t flags, std::uint8_t scrollSpeed)
@ -295,6 +393,12 @@ ConstMemoryOneBitBuffer HScrollImageElement::image() const noexcept {
return ConstMemoryOneBitBuffer{m_buffer, m_contentWidth, m_height}; return ConstMemoryOneBitBuffer{m_buffer, m_contentWidth, m_height};
} }
void HScrollImageElement::updateBuffer(std::span<std::byte const> newBufferData) {
std::size_t n = std::min(m_buffer.size(), newBufferData.size());
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin());
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{});
}
HScrollImageElement::~HScrollImageElement() { HScrollImageElement::~HScrollImageElement() {
} }
@ -322,7 +426,58 @@ void HScrollImageElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
} }
std::expected<std::unique_ptr<HScrollImageElement>, ParseError> HScrollImageElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<HScrollImageElement>, ParseError> HScrollImageElement::parse(std::span<std::byte const>& buffer) {
// FIXME parse auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::HScrollImage)) {
return std::unexpected(ParseError::InvalidValue);
}
auto x = readU16LE(buffer);
if (!x) {
return std::unexpected(x.error());
}
auto y = readU16LE(buffer);
if (!y) {
return std::unexpected(y.error());
}
auto width = readU16LE(buffer);
if (!width) {
return std::unexpected(width.error());
}
auto height = readU16LE(buffer);
if (!height) {
return std::unexpected(height.error());
}
auto contentWidth = readU16LE(buffer);
if (!contentWidth) {
return std::unexpected(contentWidth.error());
}
auto flags = readU8LE(buffer);
if (!flags) {
return std::unexpected(flags.error());
}
auto scrollSpeed = readU8LE(buffer);
if (!scrollSpeed) {
return std::unexpected(scrollSpeed.error());
}
auto reserved_ = readU16LE(buffer);
if (!reserved_) {
return std::unexpected(reserved_.error());
}
std::size_t imageSize = ((*contentWidth) * (*height) + 8 - 1) / 8;
auto imageData = readBuffer(buffer, imageSize);
if (!imageData) {
return std::unexpected(reserved_.error());
}
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4;
if (imageSize < rounded) {
buffer = buffer.subspan(rounded - imageSize);
}
auto result = std::make_unique<HScrollImageElement>(*x, *y, *width, *height, *contentWidth, *flags, *scrollSpeed);
result->updateBuffer(*imageData);
return result;
} }
VScrollImageElement::VScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentHeight, std::uint8_t flags, std::uint8_t scrollSpeed) VScrollImageElement::VScrollImageElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t contentHeight, std::uint8_t flags, std::uint8_t scrollSpeed)
@ -382,6 +537,12 @@ ConstMemoryOneBitBuffer VScrollImageElement::image() const noexcept {
return ConstMemoryOneBitBuffer{m_buffer, m_width, m_contentHeight}; return ConstMemoryOneBitBuffer{m_buffer, m_width, m_contentHeight};
} }
void VScrollImageElement::updateBuffer(std::span<std::byte const> newBufferData) {
std::size_t n = std::min(m_buffer.size(), newBufferData.size());
std::copy(newBufferData.begin(), newBufferData.begin() + n, m_buffer.begin());
std::fill(m_buffer.begin() + n, m_buffer.end(), std::byte{});
}
VScrollImageElement::~VScrollImageElement() { VScrollImageElement::~VScrollImageElement() {
} }
@ -409,7 +570,58 @@ void VScrollImageElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
} }
std::expected<std::unique_ptr<VScrollImageElement>, ParseError> VScrollImageElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<VScrollImageElement>, ParseError> VScrollImageElement::parse(std::span<std::byte const>& buffer) {
// FIXME parse auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::VScrollImage)) {
return std::unexpected(ParseError::InvalidValue);
}
auto x = readU16LE(buffer);
if (!x) {
return std::unexpected(x.error());
}
auto y = readU16LE(buffer);
if (!y) {
return std::unexpected(y.error());
}
auto width = readU16LE(buffer);
if (!width) {
return std::unexpected(width.error());
}
auto height = readU16LE(buffer);
if (!height) {
return std::unexpected(height.error());
}
auto contentHeight = readU16LE(buffer);
if (!contentHeight) {
return std::unexpected(contentHeight.error());
}
auto flags = readU8LE(buffer);
if (!flags) {
return std::unexpected(flags.error());
}
auto scrollSpeed = readU8LE(buffer);
if (!scrollSpeed) {
return std::unexpected(scrollSpeed.error());
}
auto reserved_ = readU16LE(buffer);
if (!reserved_) {
return std::unexpected(reserved_.error());
}
std::size_t imageSize = ((*width) * (*contentHeight) + 8 - 1) / 8;
auto imageData = readBuffer(buffer, imageSize);
if (!imageData) {
return std::unexpected(reserved_.error());
}
std::size_t rounded = (imageSize + 4 - 1) / 4 * 4;
if (imageSize < rounded) {
buffer = buffer.subspan(rounded - imageSize);
}
auto result = std::make_unique<VScrollImageElement>(*x, *y, *width, *height, *contentHeight, *flags, *scrollSpeed);
result->updateBuffer(*imageData);
return result;
} }
@ -471,7 +683,42 @@ void LineElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t animati
} }
std::expected<std::unique_ptr<LineElement>, ParseError> LineElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<LineElement>, ParseError> LineElement::parse(std::span<std::byte const>& buffer) {
// FIXME: parse auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::Line)) {
return std::unexpected(ParseError::InvalidValue);
}
auto originX = readU16LE(buffer);
if (!originX) {
return std::unexpected(originX.error());
}
auto originY = readU16LE(buffer);
if (!originY) {
return std::unexpected(originY.error());
}
auto targetX = readU16LE(buffer);
if (!targetX) {
return std::unexpected(targetX.error());
}
auto targetY = readU16LE(buffer);
if (!targetY) {
return std::unexpected(targetY.error());
}
auto lineStyle = readU8LE(buffer);
if (!lineStyle) {
return std::unexpected(lineStyle.error());
}
if (*lineStyle != static_cast<std::uint8_t>(LineStyle::Solid)) {
return std::unexpected(ParseError::InvalidValue);
}
auto flags = readU8LE(buffer);
if (!flags) {
return std::unexpected(flags.error());
}
auto result = std::make_unique<LineElement>(*originX, *originY, *targetX, *targetY, static_cast<LineStyle>(*lineStyle), *flags);
return result;
} }
ClippedTextElement::ClippedTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::string text) ClippedTextElement::ClippedTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::string text)
@ -533,7 +780,45 @@ void ClippedTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
} }
std::expected<std::unique_ptr<ClippedTextElement>, ParseError> ClippedTextElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<ClippedTextElement>, ParseError> ClippedTextElement::parse(std::span<std::byte const>& buffer) {
// FIXME: parse auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::ClippedText)) {
return std::unexpected(ParseError::InvalidValue);
}
auto x = readU16LE(buffer);
if (!x) {
return std::unexpected(x.error());
}
auto y = readU16LE(buffer);
if (!y) {
return std::unexpected(y.error());
}
auto width = readU16LE(buffer);
if (!width) {
return std::unexpected(width.error());
}
auto height = readU16LE(buffer);
if (!height) {
return std::unexpected(height.error());
}
auto fontIndex = readU16LE(buffer);
if (!fontIndex) {
return std::unexpected(fontIndex.error());
}
auto textLength = readU16LE(buffer);
if (!textLength) {
return std::unexpected(textLength.error());
}
std::size_t alignedRoundedUp = (*textLength + 2 + 4 - 1) / 4 * 4 - 2;
auto textData = readBuffer(buffer, alignedRoundedUp);
if (!textData) {
return std::unexpected(textData.error());
}
std::string_view text{reinterpret_cast<char const*>(textData->data()), *textLength};
auto result = std::make_unique<ClippedTextElement>(*x, *y, *width, *height, *fontIndex, std::string{text});
return result;
} }
HScrollTextElement::HScrollTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint8_t flags, std::uint8_t scrollSpeed, std::uint16_t fontIndex, std::string text) HScrollTextElement::HScrollTextElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint8_t flags, std::uint8_t scrollSpeed, std::uint16_t fontIndex, std::string text)
@ -607,7 +892,53 @@ void HScrollTextElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
} }
std::expected<std::unique_ptr<HScrollTextElement>, ParseError> HScrollTextElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<HScrollTextElement>, ParseError> HScrollTextElement::parse(std::span<std::byte const>& buffer) {
// FIXME: parse auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::HScrollText)) {
return std::unexpected(ParseError::InvalidValue);
}
auto x = readU16LE(buffer);
if (!x) {
return std::unexpected(x.error());
}
auto y = readU16LE(buffer);
if (!y) {
return std::unexpected(y.error());
}
auto width = readU16LE(buffer);
if (!width) {
return std::unexpected(width.error());
}
auto height = readU16LE(buffer);
if (!height) {
return std::unexpected(height.error());
}
auto flags = readU8LE(buffer);
if (!flags) {
return std::unexpected(flags.error());
}
auto scrollSpeed = readU8LE(buffer);
if (!scrollSpeed) {
return std::unexpected(scrollSpeed.error());
}
auto fontIndex = readU16LE(buffer);
if (!fontIndex) {
return std::unexpected(fontIndex.error());
}
auto textLength = readU16LE(buffer);
if (!textLength) {
return std::unexpected(textLength.error());
}
std::size_t alignedRoundedUp = (*textLength + 4 - 1) / 4 * 4;
auto textData = readBuffer(buffer, alignedRoundedUp);
if (!textData) {
return std::unexpected(textData.error());
}
std::string_view text{reinterpret_cast<char const*>(textData->data()), *textLength};
auto result = std::make_unique<HScrollTextElement>(*x, *y, *width, *height, *flags, *scrollSpeed, *fontIndex, std::string{text});
return result;
} }
CurrentTimeElement::CurrentTimeElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::uint16_t utcOffset, std::uint16_t flags) CurrentTimeElement::CurrentTimeElement(std::uint16_t x, std::uint16_t y, std::uint16_t width, std::uint16_t height, std::uint16_t fontIndex, std::uint16_t utcOffset, std::uint16_t flags)
@ -674,7 +1005,43 @@ void CurrentTimeElement::drawTo(OneBitBufferInterface* imageBuffer, std::size_t
} }
std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> CurrentTimeElement::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<CurrentTimeElement>, ParseError> CurrentTimeElement::parse(std::span<std::byte const>& buffer) {
// FIXME: current time auto type = readU16LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint16_t>(ElementType::CurrentTime)) {
return std::unexpected(ParseError::InvalidValue);
}
auto x = readU16LE(buffer);
if (!x) {
return std::unexpected(x.error());
}
auto y = readU16LE(buffer);
if (!y) {
return std::unexpected(y.error());
}
auto width = readU16LE(buffer);
if (!width) {
return std::unexpected(width.error());
}
auto height = readU16LE(buffer);
if (!height) {
return std::unexpected(height.error());
}
auto fontIndex = readU16LE(buffer);
if (!fontIndex) {
return std::unexpected(fontIndex.error());
}
auto utcOffset = readU16LE(buffer);
if (!utcOffset) {
return std::unexpected(utcOffset.error());
}
auto flags = readU16LE(buffer);
if (!flags) {
return std::unexpected(flags.error());
}
auto result = std::make_unique<CurrentTimeElement>(*x, *y, *width, *height, *fontIndex, *utcOffset, *flags);
return result;
} }
AlwaysDrawnSection::~AlwaysDrawnSection() { AlwaysDrawnSection::~AlwaysDrawnSection() {
@ -780,7 +1147,59 @@ std::size_t AlwaysDrawnSection::serializeTo(std::span<std::byte> target) const {
} }
std::expected<std::unique_ptr<AlwaysDrawnSection>, ParseError> AlwaysDrawnSection::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<AlwaysDrawnSection>, ParseError> AlwaysDrawnSection::parse(std::span<std::byte const>& buffer) {
// FIXME: parse auto type = readU8LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint8_t>(SectionType::AlwaysDrawn)) {
return std::unexpected(ParseError::InvalidValue);
}
auto size = readU24LE(buffer);
if (!size) {
return std::unexpected(size.error());
}
if (*size < 8) {
return std::unexpected(ParseError::InvalidValue);
}
auto flags = readU16LE(buffer);
if (!flags) {
return std::unexpected(flags.error());
}
auto elementCount = readU16LE(buffer);
if (!elementCount) {
return std::unexpected(elementCount.error());
}
auto sectionData = buffer.subspan(0, *size - 8);
buffer = buffer.subspan(*size - 8);
auto section = std::make_unique<AlwaysDrawnSection>();
section->setDrawOnFront(((*flags) >> 0u) & 0x01u == 0x01u);
section->setDrawOnBack(((*flags) >> 1u) & 0x01u == 0x01u);
section->setClearBeforeDrawing(((*flags) >> 2u) & 0x01u == 0x01u);
section->m_elements.reserve(*elementCount);
for (std::size_t i = 0; i < *elementCount; ++i) {
auto type = peekU16LE(sectionData);
if (!type) {
return std::unexpected(type.error());
}
std::expected<std::unique_ptr<Element>, ParseError> element;
switch (static_cast<ElementType>(*type)) {
case ElementType::Image: element = ImageElement::parse(sectionData); break;
case ElementType::Animation: element = AnimationElement::parse(sectionData); break;
case ElementType::HScrollImage: element = HScrollImageElement::parse(sectionData); break;
case ElementType::VScrollImage: element = VScrollImageElement::parse(sectionData); break;
case ElementType::Line: element = LineElement::parse(sectionData); break;
case ElementType::ClippedText: element = ClippedTextElement::parse(sectionData); break;
case ElementType::HScrollText: element = HScrollTextElement::parse(sectionData); break;
case ElementType::CurrentTime: element = CurrentTimeElement::parse(sectionData); break;
default:
return std::unexpected(ParseError::InvalidValue);
}
if (!element) {
return std::unexpected(element.error());
}
section->m_elements.push_back(std::move(*element));
}
return section;
} }
TimeBasedDrawnSection::~TimeBasedDrawnSection() { TimeBasedDrawnSection::~TimeBasedDrawnSection() {
@ -904,7 +1323,69 @@ std::size_t TimeBasedDrawnSection::serializeTo(std::span<std::byte> target) cons
} }
std::expected<std::unique_ptr<TimeBasedDrawnSection>, ParseError> TimeBasedDrawnSection::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<TimeBasedDrawnSection>, ParseError> TimeBasedDrawnSection::parse(std::span<std::byte const>& buffer) {
// FIXME: parse auto type = readU8LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint8_t>(SectionType::TimeBasedDrawn)) {
return std::unexpected(ParseError::InvalidValue);
}
auto size = readU24LE(buffer);
if (!size) {
return std::unexpected(size.error());
}
if (*size < 24) {
return std::unexpected(ParseError::InvalidValue);
}
auto flags = readU16LE(buffer);
if (!flags) {
return std::unexpected(flags.error());
}
auto elementCount = readU16LE(buffer);
if (!elementCount) {
return std::unexpected(elementCount.error());
}
auto startTimestamp = readU64LE(buffer);
if (!startTimestamp) {
return std::unexpected(startTimestamp.error());
}
auto endTimestamp = readU64LE(buffer);
if (!endTimestamp) {
return std::unexpected(endTimestamp.error());
}
auto sectionData = buffer.subspan(0, *size - 24);
buffer = buffer.subspan(*size - 24);
auto section = std::make_unique<TimeBasedDrawnSection>();
section->setDrawOnFront(((*flags) >> 0u) & 0x01u == 0x01u);
section->setDrawOnBack(((*flags) >> 1u) & 0x01u == 0x01u);
section->setClearBeforeDrawing(((*flags) >> 2u) & 0x01u == 0x01u);
section->setStartTimestamp(std::bit_cast<std::int64_t>(*startTimestamp));
section->setEndTimestamp(std::bit_cast<std::int64_t>(*endTimestamp));
section->m_elements.reserve(*elementCount);
for (std::size_t i = 0; i < *elementCount; ++i) {
auto type = peekU16LE(sectionData);
if (!type) {
return std::unexpected(type.error());
}
std::expected<std::unique_ptr<Element>, ParseError> element;
switch (static_cast<ElementType>(*type)) {
case ElementType::Image: element = ImageElement::parse(sectionData); break;
case ElementType::Animation: element = AnimationElement::parse(sectionData); break;
case ElementType::HScrollImage: element = HScrollImageElement::parse(sectionData); break;
case ElementType::VScrollImage: element = VScrollImageElement::parse(sectionData); break;
case ElementType::Line: element = LineElement::parse(sectionData); break;
case ElementType::ClippedText: element = ClippedTextElement::parse(sectionData); break;
case ElementType::HScrollText: element = HScrollTextElement::parse(sectionData); break;
case ElementType::CurrentTime: element = CurrentTimeElement::parse(sectionData); break;
default:
return std::unexpected(ParseError::InvalidValue);
}
if (!element) {
return std::unexpected(element.error());
}
section->m_elements.push_back(std::move(*element));
}
return section;
} }
CustomFontSection::~CustomFontSection() { CustomFontSection::~CustomFontSection() {
@ -937,7 +1418,39 @@ std::size_t CustomFontSection::serializeTo(std::span<std::byte> target) const {
} }
std::expected<std::unique_ptr<CustomFontSection>, ParseError> CustomFontSection::parse(std::span<std::byte const>& buffer) { std::expected<std::unique_ptr<CustomFontSection>, ParseError> CustomFontSection::parse(std::span<std::byte const>& buffer) {
// FIXME: parse auto type = readU8LE(buffer);
if (!type) {
return std::unexpected(type.error());
}
if (*type != static_cast<std::uint8_t>(SectionType::CustomFont)) {
return std::unexpected(ParseError::InvalidValue);
}
auto size = readU24LE(buffer);
if (!size) {
return std::unexpected(size.error());
}
if (*size < 8) {
return std::unexpected(ParseError::InvalidValue);
}
auto actualSize = readU24LE(buffer);
if (!actualSize) {
return std::unexpected(actualSize.error());
}
auto reserved_ = readU8LE(buffer);
if (!reserved_) {
return std::unexpected(reserved_.error());
}
auto fontData = buffer.subspan(0, *size - 8);
buffer = buffer.subspan(*size - 8);
auto actualFontData = readBuffer(fontData, *actualSize);
if (!actualFontData) {
return std::unexpected(actualFontData.error());
}
auto section = std::make_unique<CustomFontSection>();
section->setFontData(*actualFontData);
return section;
} }
std::size_t serializeFile(std::span<std::byte>& buffer, File const& file) { std::size_t serializeFile(std::span<std::byte>& buffer, File const& file) {
@ -961,7 +1474,51 @@ std::size_t serializeFile(std::span<std::byte>& buffer, File const& file) {
} }
std::expected<File, ParseError> parseFile(std::span<std::byte const> data) { std::expected<File, ParseError> parseFile(std::span<std::byte const> data) {
// FIXME: parse auto magic = readU32LE(data);
if (!magic) {
return std::unexpected(magic.error());
}
if (*magic != UINT32_C(0x632B7EAF)) {
return std::unexpected(ParseError::InvalidValue);
}
auto version = readU32LE(data);
if (!version) {
return std::unexpected(version.error());
}
if (*version != 1) {
return std::unexpected(ParseError::InvalidValue);
}
auto sectionCount = readU16LE(data);
if (!sectionCount) {
return std::unexpected(sectionCount.error());
}
auto reserved_ = readU16LE(data);
if (!reserved_) {
return std::unexpected(reserved_.error());
}
File result;
result.sections.reserve(*sectionCount);
for (std::size_t i = 0; i < *sectionCount; ++i) {
auto sectionType = peekU8LE(data);
if (!sectionType) {
return std::unexpected(sectionType.error());
}
std::expected<std::unique_ptr<Section>, ParseError> section;
switch (static_cast<SectionType>(*sectionType)) {
case SectionType::AlwaysDrawn: section = AlwaysDrawnSection::parse(data); break;
case SectionType::TimeBasedDrawn: section = TimeBasedDrawnSection::parse(data); break;
case SectionType::CustomFont: section = CustomFontSection::parse(data); break;
default: return std::unexpected(ParseError::InvalidValue);
}
result.sections.push_back(std::move(*section));
}
return result;
} }
} // namespace monoformat } // namespace monoformat

@ -89,6 +89,7 @@ struct ImageElement : public Element {
std::span<std::byte const> buffer() const noexcept; std::span<std::byte const> buffer() const noexcept;
MemoryOneBitBuffer image() noexcept; MemoryOneBitBuffer image() noexcept;
ConstMemoryOneBitBuffer image() const noexcept; ConstMemoryOneBitBuffer image() const noexcept;
void updateBuffer(std::span<std::byte const> newBufferData);
virtual ~ImageElement() override; virtual ~ImageElement() override;
virtual ElementType elementType() const override; virtual ElementType elementType() const override;
@ -120,6 +121,7 @@ struct AnimationElement : public Element {
std::span<std::byte const> buffer(std::uint16_t frameIndex) const noexcept; std::span<std::byte const> buffer(std::uint16_t frameIndex) const noexcept;
MemoryOneBitBuffer image(std::uint16_t frameIndex) noexcept; MemoryOneBitBuffer image(std::uint16_t frameIndex) noexcept;
ConstMemoryOneBitBuffer image(std::uint16_t frameIndex) const noexcept; ConstMemoryOneBitBuffer image(std::uint16_t frameIndex) const noexcept;
void updateBuffer(std::span<std::byte const> newBufferData);
virtual ~AnimationElement() override; virtual ~AnimationElement() override;
virtual ElementType elementType() const override; virtual ElementType elementType() const override;
@ -152,6 +154,7 @@ struct HScrollImageElement : public Element {
std::span<std::byte const> buffer() const noexcept; std::span<std::byte const> buffer() const noexcept;
MemoryOneBitBuffer image() noexcept; MemoryOneBitBuffer image() noexcept;
ConstMemoryOneBitBuffer image() const noexcept; ConstMemoryOneBitBuffer image() const noexcept;
void updateBuffer(std::span<std::byte const> newBufferData);
virtual ~HScrollImageElement() override; virtual ~HScrollImageElement() override;
virtual ElementType elementType() const override; virtual ElementType elementType() const override;
@ -185,6 +188,7 @@ struct VScrollImageElement : public Element {
std::span<std::byte const> buffer() const noexcept; std::span<std::byte const> buffer() const noexcept;
MemoryOneBitBuffer image() noexcept; MemoryOneBitBuffer image() noexcept;
ConstMemoryOneBitBuffer image() const noexcept; ConstMemoryOneBitBuffer image() const noexcept;
void updateBuffer(std::span<std::byte const> newBufferData);
virtual ~VScrollImageElement() override; virtual ~VScrollImageElement() override;
virtual ElementType elementType() const override; virtual ElementType elementType() const override;

Loading…
Cancel
Save