mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-25 01:19:45 +00:00
Previously, ChunkID's from_big_endian_number() and
as_big_endian_number() weren't inverses of each other.
ChunkID::from_big_endian_number() used to take an u32 that contained
`('f' << 24) | ('t' << 16) | ('y' << 8) | 'p'`, that is
'f', 't', 'y', 'p' in memory on big-endian and 'p', 'y', 't', 'f'
on little-endian, and return a ChunkID for 'f', 't', 'y', 'p'.
ChunkID::as_big_endian_number() used to return an u32 that for a
ChunkID storing 'f', 't', 'y', 'p' was always 'f', 't', 'y', 'p'
in memory on both little-endian and big-endian, that is it stored
`('f' << 24) | ('t' << 16) | ('y' << 8) | 'p'` on big-endian and
`('p' << 24) | ('y' << 16) | ('t' << 8) | 'f'` on little-endian.
`ChunkID::from_big_endian_number(0x11223344).as_big_endian_number()`
returned 0x44332211.
This change makes the two methods self-consistent: they now take
and return a u32 that always has the first ChunkID part in the
highest bits of the u32 (`'f' << 24`), and so on. That also means
they return a u32 that in-memory looks differently on big-endian
and little-endian. Since that's normal for numbers, this also
renames the two methods to just `from_number()` and `to_number()`.
With the semantics cleared up, change the one use in ISOBMFF to read a
BigEndian for chunk headers and brand codes. This has the effect of
tags now being printed in the right order.
Before:
```sh
% Build/lagom/bin/isobmff ~/Downloads/sample1.jp2
Unknown Box (' Pj')
[ 4 bytes ]
('pytf') (version = 0, flags = 0x0)
- major_brand = ' 2pj'
- minor_version = 0
- compatible_brands = { ' 2pj' }
Unknown Box ('h2pj')
[ 37 bytes ]
Unknown Box ('fniu')
[ 92 bytes ]
Unknown Box (' lmx')
[ 2736 bytes ]
Unknown Box ('c2pj')
[ 667336 bytes ]
```
After:
```sh
% Build/lagom/bin/isobmff ~/Downloads/sample1.jp2
hmm 0x11223344 0x11223344
Unknown Box ('jP ')
[ 4 bytes ]
('ftyp' ) (version = 0, flags = 0x0)
- major_brand = 'jp2 '
- minor_version = 0
- compatible_brands = { 'jp2 ' }
Unknown Box ('jp2h')
[ 37 bytes ]
Unknown Box ('uinf')
[ 92 bytes ]
Unknown Box ('xml ')
[ 2736 bytes ]
Unknown Box ('jp2c')
[ 667336 bytes ]
```
71 lines
2 KiB
C++
71 lines
2 KiB
C++
/*
|
|
* Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Array.h>
|
|
#include <AK/Endian.h>
|
|
#include <AK/Format.h>
|
|
#include <AK/StringView.h>
|
|
#include <AK/Types.h>
|
|
|
|
namespace RIFF {
|
|
|
|
static constexpr size_t const chunk_id_size = 4;
|
|
|
|
// Also referred to as "FourCC" (four character code) in the context of some formats.
|
|
struct ChunkID {
|
|
constexpr ChunkID(char const name[4])
|
|
{
|
|
id_data[0] = static_cast<u8>(name[0]);
|
|
id_data[1] = static_cast<u8>(name[1]);
|
|
id_data[2] = static_cast<u8>(name[2]);
|
|
id_data[3] = static_cast<u8>(name[3]);
|
|
}
|
|
constexpr ChunkID(Array<u8, chunk_id_size> data)
|
|
: id_data(data)
|
|
{
|
|
}
|
|
constexpr ChunkID(ChunkID const&) = default;
|
|
constexpr ChunkID(ChunkID&&) = default;
|
|
constexpr ChunkID& operator=(ChunkID const&) = default;
|
|
static constexpr ChunkID from_number(u32 number)
|
|
{
|
|
return Array<u8, chunk_id_size> { {
|
|
static_cast<u8>((number >> 24) & 0xff),
|
|
static_cast<u8>((number >> 16) & 0xff),
|
|
static_cast<u8>((number >> 8) & 0xff),
|
|
static_cast<u8>(number & 0xff),
|
|
} };
|
|
}
|
|
|
|
static ErrorOr<ChunkID> read_from_stream(Stream& stream);
|
|
|
|
StringView as_ascii_string() const;
|
|
constexpr u32 as_number() const
|
|
{
|
|
return (id_data[0] << 24) | (id_data[1] << 16) | (id_data[2] << 8) | id_data[3];
|
|
}
|
|
|
|
bool operator==(ChunkID const&) const = default;
|
|
bool operator==(StringView) const;
|
|
|
|
Array<u8, chunk_id_size> id_data;
|
|
};
|
|
static_assert(AssertSize<ChunkID, chunk_id_size>());
|
|
|
|
}
|
|
|
|
template<>
|
|
struct AK::Formatter<RIFF::ChunkID> : StandardFormatter {
|
|
ErrorOr<void> format(FormatBuilder& builder, RIFF::ChunkID const& chunk_id)
|
|
{
|
|
TRY(builder.put_padding('\'', 1));
|
|
TRY(builder.put_literal(chunk_id.as_ascii_string()));
|
|
TRY(builder.put_padding('\'', 1));
|
|
return {};
|
|
}
|
|
};
|