6 #include "../exceptions.h" 7 #include "../mediafileinfo.h" 9 #include <c++utilities/conversion/binaryconversion.h> 10 #include <c++utilities/conversion/types.h> 11 #include <c++utilities/io/binaryreader.h> 12 #include <c++utilities/io/binarywriter.h> 33 uint64 EbmlElement::bytesToBeSkipped = 0x4000;
62 string EbmlElement::parsingContext()
const 72 static const string context(
"parsing EBML element header");
84 byte beg =
static_cast<byte
>(
stream().peek()), mask = 0x80;
104 m_id = BE::toUInt32(buf);
112 const byte actualLevel =
level();
113 if (actualLevel > supposedLevel) {
115 if (
EbmlElement *betterParent =
m_parent->parent(actualLevel - static_cast<byte>(supposedLevel))) {
120 if (
m_parent->firstChild() ==
this) {
126 for (
EbmlElement *sibling =
m_parent->firstChild(); sibling; sibling = sibling->nextSibling()) {
127 if (sibling->nextSibling() ==
this) {
128 sibling->m_nextSibling.release();
136 previousSibling->m_nextSibling.reset(
this);
138 betterParent->m_firstChild.reset(
this);
147 beg =
static_cast<byte
>(
stream().peek()), mask = 0x80;
160 diag.emplace_back(
DiagLevel::Critical,
"EBML size length is not supported.", parsingContext());
175 m_dataSize = ConversionUtilities::BE::toUInt64(buf);
180 diag.emplace_back(
DiagLevel::Critical,
"EBML header seems to be truncated.", parsingContext());
184 diag.emplace_back(
DiagLevel::Warning,
"Data of EBML element seems to be truncated; unable to parse siblings of that element.",
213 diag.emplace_back(
DiagLevel::Warning, argsToString(skipped,
" bytes have been skipped"), parsingContext());
240 char buff[
sizeof(uint64)] = { 0 };
241 int i =
static_cast<int>(
sizeof(buff)) -
dataSize();
246 stream().read(buff + i,
sizeof(buff) - i);
247 return BE::toUInt64(buff);
258 case sizeof(float32):
259 return reader().readFloat32BE();
260 case sizeof(float64):
261 return reader().readFloat64BE();
275 }
else if (
id <= 0x7FFF) {
277 }
else if (
id <= 0x3FFFFF) {
279 }
else if (
id <= 0x1FFFFFFF) {
294 }
else if (size <= 16382ul) {
296 }
else if (size <= 2097150ul) {
298 }
else if (size <= 268435454ul) {
300 }
else if (size <= 34359738366ul) {
302 }
else if (size <= 4398046511102ul) {
304 }
else if (size <= 562949953421310ul) {
306 }
else if (size <= 72057594037927934ul) {
322 *buff =
static_cast<byte
>(
id);
324 }
else if (
id <= 0x7FFF) {
325 BE::getBytes(static_cast<uint16>(
id), buff);
327 }
else if (
id <= 0x3FFFFF) {
328 BE::getBytes(static_cast<uint32>(
id << 0x8), buff);
330 }
else if (
id <= 0x1FFFFFFF) {
331 BE::getBytes(static_cast<uint32>(
id), buff);
348 *buff =
static_cast<byte
>(size | 0x80);
350 }
else if (size <= 16382ul) {
351 BE::getBytes(static_cast<uint16>(size | 0x4000), buff);
353 }
else if (size <= 2097150ul) {
354 BE::getBytes(static_cast<uint32>((size | 0x200000) << 0x08), buff);
356 }
else if (size <= 268435454ul) {
357 BE::getBytes(static_cast<uint32>(size | 0x10000000), buff);
359 }
else if (size <= 34359738366ul) {
360 BE::getBytes(static_cast<uint64>((size | 0x800000000) << 0x18), buff);
362 }
else if (size <= 4398046511102ul) {
363 BE::getBytes(static_cast<uint64>((size | 0x40000000000) << 0x10), buff);
365 }
else if (size <= 562949953421310ul) {
366 BE::getBytes(static_cast<uint64>((size | 0x2000000000000) << 0x08), buff);
368 }
else if (size <= 72057594037927934ul) {
369 BE::getBytes(static_cast<uint64>(size | 0x100000000000000), buff);
385 if (minBytes <= 1 && size < 126) {
386 *buff =
static_cast<byte
>(size | 0x80);
388 }
else if (minBytes <= 2 && size <= 16382ul) {
389 BE::getBytes(static_cast<uint16>(size | 0x4000), buff);
391 }
else if (minBytes <= 3 && size <= 2097150ul) {
392 BE::getBytes(static_cast<uint32>((size | 0x200000) << 0x08), buff);
394 }
else if (minBytes <= 4 && size <= 268435454ul) {
395 BE::getBytes(static_cast<uint32>(size | 0x10000000), buff);
397 }
else if (minBytes <= 5 && size <= 34359738366ul) {
398 BE::getBytes(static_cast<uint64>((size | 0x800000000) << 0x18), buff);
400 }
else if (minBytes <= 6 && size <= 4398046511102ul) {
401 BE::getBytes(static_cast<uint64>((size | 0x40000000000) << 0x10), buff);
403 }
else if (minBytes <= 7 && size <= 562949953421310ul) {
404 BE::getBytes(static_cast<uint64>((size | 0x2000000000000) << 0x08), buff);
406 }
else if (minBytes <= 8 && size <= 72057594037927934ul) {
407 BE::getBytes(static_cast<uint64>(size | 0x100000000000000), buff);
419 if (integer <= 0xFFul) {
421 }
else if (integer <= 0xFFFFul) {
423 }
else if (integer <= 0xFFFFFFul) {
425 }
else if (integer <= 0xFFFFFFFFul) {
427 }
else if (integer <= 0xFFFFFFFFFFul) {
429 }
else if (integer <= 0xFFFFFFFFFFFFul) {
431 }
else if (integer <= 0xFFFFFFFFFFFFFFul) {
444 if (value <= 0xFFul) {
445 *buff =
static_cast<char>(value);
447 }
else if (value <= 0xFFFFul) {
448 BE::getBytes(static_cast<uint16>(value), buff);
450 }
else if (value <= 0xFFFFFFul) {
451 BE::getBytes(static_cast<uint32>(value << 0x08), buff);
453 }
else if (value <= 0xFFFFFFFFul) {
454 BE::getBytes(static_cast<uint32>(value), buff);
456 }
else if (value <= 0xFFFFFFFFFFul) {
457 BE::getBytes(static_cast<uint64>(value << 0x18), buff);
459 }
else if (value <= 0xFFFFFFFFFFFFul) {
460 BE::getBytes(static_cast<uint64>(value << 0x10), buff);
462 }
else if (value <= 0xFFFFFFFFFFFFFFul) {
463 BE::getBytes(static_cast<uint64>(value << 0x08), buff);
466 BE::getBytes(static_cast<uint64>(value), buff);
480 if (minBytes <= 1 && value <= 0xFFul) {
481 *buff =
static_cast<char>(value);
483 }
else if (minBytes <= 2 && value <= 0xFFFFul) {
484 BE::getBytes(static_cast<uint16>(value), buff);
486 }
else if (minBytes <= 3 && value <= 0xFFFFFFul) {
487 BE::getBytes(static_cast<uint32>(value << 0x08), buff);
489 }
else if (minBytes <= 4 && value <= 0xFFFFFFFFul) {
490 BE::getBytes(static_cast<uint32>(value), buff);
492 }
else if (minBytes <= 5 && value <= 0xFFFFFFFFFFul) {
493 BE::getBytes(static_cast<uint64>(value << 0x18), buff);
495 }
else if (minBytes <= 6 && value <= 0xFFFFFFFFFFFFul) {
496 BE::getBytes(static_cast<uint64>(value << 0x10), buff);
498 }
else if (minBytes <= 7 && value <= 0xFFFFFFFFFFFFFFul) {
499 BE::getBytes(static_cast<uint64>(value << 0x08), buff);
502 BE::getBytes(static_cast<uint64>(value), buff);
522 stream.write(buff2, elementSize);
538 stream.write(content.c_str(), content.size());
TAG_PARSER_EXPORT MatroskaElementLevel matroskaIdLevel(uint32 matroskaId)
Returns the level at which elements with the specified matroskaId are supposed to occur in a Matroska...
static byte makeId(IdentifierType id, char *buff)
Stores the specified id in the specified buffer which must be at least 8 bytes long.
static void makeSimpleElement(std::ostream &stream, IdentifierType id, uint64 content)
Makes a simple EBML element.
std::unique_ptr< ImplementationType > m_firstChild
uint32 sizeLength() const
Returns the length of the size denotation of the element in byte.
static byte calculateSizeDenotationLength(uint64 size)
Returns the length of the size denotation for the specified size in byte.
static constexpr uint32 maximumIdLengthSupported()
Returns the maximum id length supported by the class in byte.
std::string readString()
Reads the content of the element as string.
std::unique_ptr< ImplementationType > m_nextSibling
DataSizeType dataSize() const
Returns the data size of the element in byte.
uint64 startOffset() const
Returns the start offset in the related stream.
static byte calculateUIntegerLength(uint64 integer)
Returns the length of the specified unsigned integer in byte.
uint64 totalSize() const
Returns the total size of the element.
std::string idToString() const
Converts the specified EBML ID to a printable string.
uint64 dataOffset() const
Returns the data offset of the element in the related stream.
IoUtilities::BinaryReader & reader()
Returns the related BinaryReader.
uint64 firstChildOffset() const
Returns the offset of the first child of the element.
Contains utility classes helping to read and write streams.
ImplementationType * m_parent
ContainerType & container()
Returns the related container.
static byte makeUInteger(uint64 value, char *buff)
Writes value to buff.
static byte makeSizeDenotation(uint64 size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
uint64 readUInteger()
Reads the content of the element as unsigned integer.
uint32 headerSize() const
Returns the header size of the element in byte.
ImplementationType * lastChild()
Returns the last child of the element.
void internalParse(Diagnostics &diag)
Parses the EBML element.
uint64 maxTotalSize() const
Returns maximum total size.
static byte calculateIdLength(IdentifierType id)
Returns the length of the specified id in byte.
float64 readFloat()
Reads the content of the element as float.
static uint64 bytesToBeSkipped
Specifies the number of bytes to be skipped till a valid EBML element is found in the stream...
std::iostream & stream()
Returns the related stream.
static constexpr uint32 maximumSizeLengthSupported()
Returns the maximum size length supported by the class in byte.
const IdentifierType & id() const
Returns the element ID.
FileElementTraits< ImplementationType >::IdentifierType IdentifierType
Specifies the type used to store identifiers.
byte level() const
Returns how deep the element is nested (0 for top-level elements, 1 for children of top-level element...
FileElementTraits< ImplementationType >::DataSizeType DataSizeType
Specifies the type used to store data sizes.
ImplementationType * parent()
Returns the parent of the element.
EbmlElement(MatroskaContainer &container, uint64 startOffset)
Constructs a new top level element with the specified container at the specified startOffset.