From 78deac3dca7309047695ac59fb1864d30b4571d0 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 22 Mar 2024 14:26:56 -0400 Subject: [PATCH] LibGfx/ISOBMFF: Give Reader::read_entire_file() a factory callback This will allow creating different child boxes in different containers. --- .../LibGfx/ImageFormats/ISOBMFF/Boxes.cpp | 5 +-- .../LibGfx/ImageFormats/ISOBMFF/Boxes.h | 4 ++- .../ImageFormats/ISOBMFF/JPEG2000Boxes.cpp | 7 +++- .../LibGfx/ImageFormats/ISOBMFF/Reader.cpp | 33 ++++++++++++------- .../LibGfx/ImageFormats/ISOBMFF/Reader.h | 3 ++ 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.cpp b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.cpp index 1014c5202d1..3658dd9b085 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.cpp @@ -6,6 +6,7 @@ #include "Boxes.h" #include "Reader.h" +#include namespace Gfx::ISOBMFF { @@ -104,10 +105,10 @@ void FileTypeBox::dump(String const& prepend) const outln("{}{}", prepend, compatible_brands_string.string_view()); } -ErrorOr SuperBox::read_from_stream(BoxStream& stream) +ErrorOr SuperBox::read_from_stream(BoxStream& stream, BoxCallback box_factory) { auto reader = TRY(Gfx::ISOBMFF::Reader::create(MaybeOwned { stream })); - m_child_boxes = TRY(reader.read_entire_file()); + m_child_boxes = TRY(reader.read_entire_file(move(box_factory))); return {}; } diff --git a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.h b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.h index f2be661a453..1996c4375bc 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.h +++ b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Boxes.h @@ -95,7 +95,9 @@ struct FileTypeBox final : public Box { // A box that contains other boxes. struct SuperBox : public Box { SuperBox() = default; - ErrorOr read_from_stream(BoxStream&); + + using BoxCallback = Function>>(BoxType, BoxStream&)>; + ErrorOr read_from_stream(BoxStream&, BoxCallback); virtual void dump(String const& prepend = {}) const override; private: diff --git a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/JPEG2000Boxes.cpp b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/JPEG2000Boxes.cpp index 179476bbf79..b6dc845423d 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/JPEG2000Boxes.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/JPEG2000Boxes.cpp @@ -5,12 +5,17 @@ */ #include "JPEG2000Boxes.h" +#include namespace Gfx::ISOBMFF { ErrorOr JPEG2000HeaderBox::read_from_stream(BoxStream& stream) { - TRY(SuperBox::read_from_stream(stream)); + auto make_subbox = [](BoxType, BoxStream&) -> ErrorOr>> { + return OptionalNone {}; + }; + + TRY(SuperBox::read_from_stream(stream, move(make_subbox))); return {}; } diff --git a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.cpp b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.cpp index 3e6f3cb54ee..78c14997d88 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.cpp @@ -22,6 +22,23 @@ ErrorOr Reader::create(MaybeOwned stream) } ErrorOr Reader::read_entire_file() +{ + auto make_top_level_box = [](BoxType type, BoxStream& stream) -> ErrorOr>> { + switch (type) { + case BoxType::FileTypeBox: + return TRY(FileTypeBox::create_from_stream(stream)); + case BoxType::JPEG2000HeaderBox: + return TRY(JPEG2000HeaderBox::create_from_stream(stream)); + case BoxType::JPEG2000SignatureBox: + return TRY(JPEG2000SignatureBox::create_from_stream(stream)); + default: + return OptionalNone {}; + } + }; + return read_entire_file((ErrorOr>>(*)(BoxType, BoxStream&))(make_top_level_box)); +} + +ErrorOr Reader::read_entire_file(BoxCallback box_factory) { BoxList top_level_boxes; @@ -29,19 +46,11 @@ ErrorOr Reader::read_entire_file() auto box_header = TRY(read_box_header(*m_box_stream)); BoxStream box_stream { MaybeOwned { *m_box_stream }, static_cast(box_header.contents_size) }; - switch (box_header.type) { - case BoxType::FileTypeBox: - TRY(top_level_boxes.try_append(TRY(FileTypeBox::create_from_stream(box_stream)))); - break; - case BoxType::JPEG2000HeaderBox: - TRY(top_level_boxes.try_append(TRY(JPEG2000HeaderBox::create_from_stream(box_stream)))); - break; - case BoxType::JPEG2000SignatureBox: - TRY(top_level_boxes.try_append(TRY(JPEG2000SignatureBox::create_from_stream(box_stream)))); - break; - default: + auto maybe_box = TRY(box_factory(box_header.type, box_stream)); + if (maybe_box.has_value()) { + TRY(top_level_boxes.try_append(move(maybe_box.value()))); + } else { TRY(top_level_boxes.try_append(TRY(UnknownBox::create_from_stream(box_header.type, box_stream)))); - break; } if (!box_stream.is_eof()) diff --git a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.h b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.h index aa313e25ac0..5b03a8758ee 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.h +++ b/Userland/Libraries/LibGfx/ImageFormats/ISOBMFF/Reader.h @@ -20,6 +20,9 @@ public: ErrorOr read_entire_file(); + using BoxCallback = Function>>(BoxType, BoxStream&)>; + ErrorOr read_entire_file(BoxCallback); + private: Reader(MaybeOwned stream) : m_box_stream(move(stream))