refactor(pcmaudio): use a chunk policy in iff_parser

This commit is contained in:
Marcus Holland-Moritz 2024-01-12 09:23:14 +01:00
parent 5d2189d629
commit 45498c0eb7

View File

@ -257,9 +257,36 @@ struct Wav64Policy {
"data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a", id_size}; "data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a", id_size};
}; };
template <typename LoggerPolicy, typename ChunkHeaderType, struct AiffChunkPolicy {
endianness Endianness, bool IsCaf = false, static constexpr std::string_view const format_name{"AIFF"};
bool SizeIncludesHeader = false> static constexpr endianness const endian{endianness::BIG};
static constexpr bool const size_includes_header{false};
static void preprocess(auto&, std::span<uint8_t const>) {}
};
struct CafChunkPolicy {
static constexpr std::string_view const format_name{"CAF"};
static constexpr endianness const endian{endianness::BIG};
static constexpr bool const size_includes_header{false};
static void preprocess(auto& c, std::span<uint8_t const> data) {
if (c.header.size == std::numeric_limits<decltype(c.header.size)>::max() &&
c.is("data")) {
c.header.size = data.size() - (c.pos + sizeof(c.header));
}
}
};
template <typename FormatPolicy>
struct WavChunkPolicy {
static constexpr std::string_view const format_name{
FormatPolicy::format_name};
static constexpr endianness const endian{endianness::LITTLE};
static constexpr bool const size_includes_header{
FormatPolicy::size_includes_header};
static void preprocess(auto&, std::span<uint8_t const>) {}
};
template <typename LoggerPolicy, typename ChunkPolicy, typename ChunkHeaderType>
class iff_parser final { class iff_parser final {
public: public:
struct chunk { struct chunk {
@ -283,11 +310,10 @@ class iff_parser final {
size_t size() const { return header.size; } size_t size() const { return header.size; }
}; };
iff_parser(logger& lgr, std::string_view name, fs::path const& path, iff_parser(logger& lgr, fs::path const& path, std::span<uint8_t const> data,
std::span<uint8_t const> data, size_t pos) size_t pos)
: LOG_PROXY_INIT(lgr) : LOG_PROXY_INIT(lgr)
, data_{data} , data_{data}
, name_{name}
, path_{path} , path_{path}
, pos_{pos} {} , pos_{pos} {}
@ -298,20 +324,14 @@ class iff_parser final {
c.emplace(); c.emplace();
DWARFS_CHECK(read(c->header, pos_), "iff_parser::read failed"); DWARFS_CHECK(read(c->header, pos_), "iff_parser::read failed");
c->header.size = endian<Endianness>::convert(c->header.size); c->header.size = endian<ChunkPolicy::endian>::convert(c->header.size);
c->pos = pos_; c->pos = pos_;
if constexpr (IsCaf) { ChunkPolicy::preprocess(*c, data_);
if (c->header.size ==
std::numeric_limits<decltype(c->header.size)>::max() &&
c->is("data")) {
c->header.size = data_.size() - (pos_ + sizeof(ChunkHeaderType));
}
}
if constexpr (SizeIncludesHeader) { if constexpr (ChunkPolicy::size_includes_header) {
if (c->header.size < sizeof(ChunkHeaderType)) { if (c->header.size < sizeof(ChunkHeaderType)) {
LOG_WARN << "[" << name_ << "] " << path_ LOG_WARN << "[" << ChunkPolicy::format_name << "] " << path_
<< ": invalid chunk size: " << c->header.size; << ": invalid chunk size: " << c->header.size;
c.reset(); c.reset();
return c; return c;
@ -324,7 +344,7 @@ class iff_parser final {
} }
if (pos_ > data_.size()) { if (pos_ > data_.size()) {
LOG_WARN << "[" << name_ << "] " << path_ LOG_WARN << "[" << ChunkPolicy::format_name << "] " << path_
<< ": unexpected end of file (pos=" << pos_ << ": unexpected end of file (pos=" << pos_
<< ", hdr.size=" << c->header.size << ", end=" << data_.size() << ", hdr.size=" << c->header.size << ", end=" << data_.size()
<< ")"; << ")";
@ -332,8 +352,8 @@ class iff_parser final {
return c; return c;
} }
LOG_TRACE << "[" << name_ << "] " << path_ << ": `" << c->fourcc() LOG_TRACE << "[" << ChunkPolicy::format_name << "] " << path_ << ": `"
<< "` (len=" << c->size() << ")"; << c->fourcc() << "` (len=" << c->size() << ")";
} }
return c; return c;
@ -360,9 +380,10 @@ class iff_parser final {
return true; return true;
} }
LOG_WARN << "[" << name_ << "] " << path_ << ": unexpected size for `" LOG_WARN << "[" << ChunkPolicy::format_name << "] " << path_
<< c.fourcc() << "` chunk: " << c.size() << " (expected " << ": unexpected size for `" << c.fourcc()
<< expected_size << ")"; << "` chunk: " << c.size() << " (expected " << expected_size
<< ")";
return false; return false;
} }
@ -382,14 +403,14 @@ class iff_parser final {
return true; return true;
} }
LOG_WARN << "[" << name_ << "] " << path_ << ": unexpected end of file"; LOG_WARN << "[" << ChunkPolicy::format_name << "] " << path_
<< ": unexpected end of file";
return false; return false;
} }
LOG_PROXY_DECL(LoggerPolicy); LOG_PROXY_DECL(LoggerPolicy);
std::span<uint8_t const> data_; std::span<uint8_t const> data_;
std::string_view name_;
fs::path const& path_; fs::path const& path_;
size_t pos_; size_t pos_;
}; };
@ -573,8 +594,8 @@ bool pcmaudio_categorizer_<LoggerPolicy>::check_aiff(
static_assert(sizeof(comm_chk_t) == 8); static_assert(sizeof(comm_chk_t) == 8);
static_assert(sizeof(ssnd_chk_t) == 8); static_assert(sizeof(ssnd_chk_t) == 8);
iff_parser<LoggerPolicy, chunk_hdr_t, endianness::BIG> parser( iff_parser<LoggerPolicy, AiffChunkPolicy, chunk_hdr_t> parser(
LOG_GET_LOGGER, "AIFF", path, data, sizeof(file_hdr_t)); LOG_GET_LOGGER, path, data, sizeof(file_hdr_t));
file_hdr_t file_header; file_hdr_t file_header;
if (!parser.read_file_header(file_header)) { if (!parser.read_file_header(file_header)) {
@ -707,8 +728,8 @@ bool pcmaudio_categorizer_<LoggerPolicy>::check_caf(
static constexpr uint32_t const kCAFLinearPCMFormatFlagIsLittleEndian{1L static constexpr uint32_t const kCAFLinearPCMFormatFlagIsLittleEndian{1L
<< 1}; << 1};
iff_parser<LoggerPolicy, chunk_hdr_t, endianness::BIG, true> parser( iff_parser<LoggerPolicy, CafChunkPolicy, chunk_hdr_t> parser(
LOG_GET_LOGGER, "CAF", path, data, sizeof(caff_hdr_t)); LOG_GET_LOGGER, path, data, sizeof(caff_hdr_t));
caff_hdr_t caff_hdr; caff_hdr_t caff_hdr;
if (!parser.read_file_header(caff_hdr)) { if (!parser.read_file_header(caff_hdr)) {
@ -882,10 +903,8 @@ bool pcmaudio_categorizer_<LoggerPolicy>::check_wav_like(
static constexpr uint16_t const WAVE_FORMAT_PCM{0x0001}; static constexpr uint16_t const WAVE_FORMAT_PCM{0x0001};
static constexpr uint16_t const WAVE_FORMAT_EXTENSIBLE{0xFFFE}; static constexpr uint16_t const WAVE_FORMAT_EXTENSIBLE{0xFFFE};
iff_parser<LoggerPolicy, chunk_hdr_t, endianness::LITTLE, false, iff_parser<LoggerPolicy, WavChunkPolicy<FormatPolicy>, chunk_hdr_t> parser(
FormatPolicy::size_includes_header> LOG_GET_LOGGER, path, data, sizeof(file_hdr_t));
parser(LOG_GET_LOGGER, FormatPolicy::format_name, path, data,
sizeof(file_hdr_t));
file_hdr_t file_header; file_hdr_t file_header;
if (!parser.read_file_header(file_header)) { if (!parser.read_file_header(file_header)) {