Details.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Details.h"
  7. #include <AK/TypeCasts.h>
  8. #include <LibRIFF/IFF.h>
  9. #include <LibRIFF/RIFF.h>
  10. namespace RIFF {
  11. StringView ChunkID::as_ascii_string() const
  12. {
  13. return StringView { id_data.span() };
  14. }
  15. bool ChunkID::operator==(StringView other_string) const
  16. {
  17. return as_ascii_string() == other_string;
  18. }
  19. namespace Detail {
  20. template<typename WordType>
  21. auto ChunkHeader<WordType>::read_from_stream(Stream& stream) -> ErrorOr<ChunkHeader>
  22. {
  23. auto id = TRY(stream.read_value<RIFF::ChunkID>());
  24. u32 size = TRY(stream.read_value<WordType>());
  25. return ChunkHeader { id, size };
  26. }
  27. template<typename HeaderType>
  28. auto FileHeader<HeaderType>::read_from_stream(Stream& stream) -> ErrorOr<FileHeader>
  29. {
  30. auto header = TRY(stream.read_value<HeaderType>());
  31. auto subformat = TRY(stream.read_value<RIFF::ChunkID>());
  32. return FileHeader { header, subformat };
  33. }
  34. template<typename HeaderType>
  35. Chunk<HeaderType>::Chunk(HeaderType header, ReadonlyBytes data)
  36. : m_header(header)
  37. , m_data(data)
  38. {
  39. VERIFY(data.size() == header.size);
  40. }
  41. template<typename HeaderType>
  42. FixedMemoryStream Chunk<HeaderType>::data_stream() const
  43. {
  44. return FixedMemoryStream { m_data };
  45. }
  46. template<typename HeaderType>
  47. auto Chunk<HeaderType>::decode(ReadonlyBytes data) -> ErrorOr<Chunk>
  48. {
  49. auto data_stream = FixedMemoryStream { data };
  50. auto header = TRY(HeaderType::read_from_stream(data_stream));
  51. if (data.size() < sizeof(HeaderType) + header.size)
  52. return Error::from_string_literal("Not enough data for IFF/RIFF chunk");
  53. return Chunk { header, data.slice(sizeof(HeaderType), header.size) };
  54. }
  55. template<typename HeaderType>
  56. auto Chunk<HeaderType>::decode_and_advance(ReadonlyBytes& data) -> ErrorOr<Chunk>
  57. {
  58. auto chunk = TRY(decode(data));
  59. data = data.slice(sizeof(HeaderType) + chunk.size());
  60. // add padding if needed
  61. if (chunk.size() % 2 != 0) {
  62. if (data.is_empty())
  63. return Error::from_string_literal("Missing data for padding byte");
  64. if (*data.data() != 0)
  65. return Error::from_string_literal("Padding byte is not 0");
  66. data = data.slice(1);
  67. }
  68. return chunk;
  69. }
  70. template<typename HeaderType>
  71. OwnedChunk<HeaderType>::OwnedChunk(HeaderType header, Buffer backing_data)
  72. : Chunk<HeaderType>(header, backing_data.span())
  73. , m_backing_data(move(backing_data))
  74. {
  75. }
  76. template<typename HeaderType>
  77. auto OwnedChunk<HeaderType>::read_from_stream(Stream& stream) -> ErrorOr<OwnedChunk>
  78. {
  79. auto header = TRY(stream.read_value<HeaderType>());
  80. auto data = TRY(Buffer::create_uninitialized(header.size));
  81. TRY(stream.read_until_filled(data.span()));
  82. // RIFF chunks may have trailing padding to align to x86 "words" (i.e. 2 bytes).
  83. if (is<SeekableStream>(stream)) {
  84. if (!stream.is_eof()) {
  85. auto stream_position = TRY(static_cast<SeekableStream&>(stream).tell());
  86. if (stream_position % 2 != 0)
  87. TRY(static_cast<SeekableStream&>(stream).seek(1, SeekMode::FromCurrentPosition));
  88. }
  89. } else {
  90. dbgln("RIFF Warning: Cannot align stream to 2-byte boundary, next chunk may be bogus!");
  91. }
  92. return OwnedChunk { header, data };
  93. }
  94. template class Chunk<IFF::ChunkHeader>;
  95. template class Chunk<RIFF::ChunkHeader>;
  96. template class OwnedChunk<IFF::ChunkHeader>;
  97. template class OwnedChunk<RIFF::ChunkHeader>;
  98. template struct ChunkHeader<IFF::WordType>;
  99. template struct ChunkHeader<RIFF::WordType>;
  100. template struct FileHeader<IFF::ChunkHeader>;
  101. template struct FileHeader<RIFF::ChunkHeader>;
  102. }
  103. }