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());
161 diag.emplace_back(
DiagLevel::Critical,
"EBML size length is not supported.", parsingContext());
176 m_dataSize = ConversionUtilities::BE::toUInt64(buf);
181 diag.emplace_back(
DiagLevel::Critical,
"EBML header seems to be truncated.", parsingContext());
185 diag.emplace_back(
DiagLevel::Warning,
"Data of EBML element seems to be truncated; unable to parse siblings of that element.",
214 diag.emplace_back(
DiagLevel::Warning, argsToString(skipped,
" bytes have been skipped"), parsingContext());
242 char buff[maxBytesToRead] = { 0 };
243 const auto bytesToSkip = maxBytesToRead - min(
dataSize(), maxBytesToRead);
245 stream().read(buff + bytesToSkip, static_cast<streamoff>(
sizeof(buff) - bytesToSkip));
246 return BE::toUInt64(buff);
257 case sizeof(float32):
258 return static_cast<float64>(
reader().readFloat32BE());
259 case sizeof(float64):
260 return reader().readFloat64BE();
274 }
else if (
id <= 0x7FFF) {
276 }
else if (
id <= 0x3FFFFF) {
278 }
else if (
id <= 0x1FFFFFFF) {
293 }
else if (size <= 16382ul) {
295 }
else if (size <= 2097150ul) {
297 }
else if (size <= 268435454ul) {
299 }
else if (size <= 34359738366ul) {
301 }
else if (size <= 4398046511102ul) {
303 }
else if (size <= 562949953421310ul) {
305 }
else if (size <= 72057594037927934ul) {
321 *buff =
static_cast<char>(
id);
323 }
else if (
id <= 0x7FFF) {
324 BE::getBytes(static_cast<uint16>(
id), buff);
326 }
else if (
id <= 0x3FFFFF) {
327 BE::getBytes(static_cast<uint32>(
id << 0x8), buff);
329 }
else if (
id <= 0x1FFFFFFF) {
330 BE::getBytes(static_cast<uint32>(
id), buff);
347 *buff =
static_cast<char>(size | 0x80);
349 }
else if (size <= 16382ul) {
350 BE::getBytes(static_cast<uint16>(size | 0x4000), buff);
352 }
else if (size <= 2097150ul) {
353 BE::getBytes(static_cast<uint32>((size | 0x200000) << 0x08), buff);
355 }
else if (size <= 268435454ul) {
356 BE::getBytes(static_cast<uint32>(size | 0x10000000), buff);
358 }
else if (size <= 34359738366ul) {
359 BE::getBytes(static_cast<uint64>((size | 0x800000000) << 0x18), buff);
361 }
else if (size <= 4398046511102ul) {
362 BE::getBytes(static_cast<uint64>((size | 0x40000000000) << 0x10), buff);
364 }
else if (size <= 562949953421310ul) {
365 BE::getBytes(static_cast<uint64>((size | 0x2000000000000) << 0x08), buff);
367 }
else if (size <= 72057594037927934ul) {
368 BE::getBytes(static_cast<uint64>(size | 0x100000000000000), buff);
384 if (minBytes <= 1 && size < 126) {
385 *buff =
static_cast<char>(size | 0x80);
387 }
else if (minBytes <= 2 && size <= 16382ul) {
388 BE::getBytes(static_cast<uint16>(size | 0x4000), buff);
390 }
else if (minBytes <= 3 && size <= 2097150ul) {
391 BE::getBytes(static_cast<uint32>((size | 0x200000) << 0x08), buff);
393 }
else if (minBytes <= 4 && size <= 268435454ul) {
394 BE::getBytes(static_cast<uint32>(size | 0x10000000), buff);
396 }
else if (minBytes <= 5 && size <= 34359738366ul) {
397 BE::getBytes(static_cast<uint64>((size | 0x800000000) << 0x18), buff);
399 }
else if (minBytes <= 6 && size <= 4398046511102ul) {
400 BE::getBytes(static_cast<uint64>((size | 0x40000000000) << 0x10), buff);
402 }
else if (minBytes <= 7 && size <= 562949953421310ul) {
403 BE::getBytes(static_cast<uint64>((size | 0x2000000000000) << 0x08), buff);
405 }
else if (minBytes <= 8 && size <= 72057594037927934ul) {
406 BE::getBytes(static_cast<uint64>(size | 0x100000000000000), buff);
418 if (integer <= 0xFFul) {
420 }
else if (integer <= 0xFFFFul) {
422 }
else if (integer <= 0xFFFFFFul) {
424 }
else if (integer <= 0xFFFFFFFFul) {
426 }
else if (integer <= 0xFFFFFFFFFFul) {
428 }
else if (integer <= 0xFFFFFFFFFFFFul) {
430 }
else if (integer <= 0xFFFFFFFFFFFFFFul) {
443 if (value <= 0xFFul) {
444 *buff =
static_cast<char>(value);
446 }
else if (value <= 0xFFFFul) {
447 BE::getBytes(static_cast<uint16>(value), buff);
449 }
else if (value <= 0xFFFFFFul) {
450 BE::getBytes(static_cast<uint32>(value << 0x08), buff);
452 }
else if (value <= 0xFFFFFFFFul) {
453 BE::getBytes(static_cast<uint32>(value), buff);
455 }
else if (value <= 0xFFFFFFFFFFul) {
456 BE::getBytes(static_cast<uint64>(value << 0x18), buff);
458 }
else if (value <= 0xFFFFFFFFFFFFul) {
459 BE::getBytes(static_cast<uint64>(value << 0x10), buff);
461 }
else if (value <= 0xFFFFFFFFFFFFFFul) {
462 BE::getBytes(static_cast<uint64>(value << 0x08), buff);
465 BE::getBytes(static_cast<uint64>(value), buff);
481 if (minBytes <= 1 && value <= 0xFFul) {
482 *buff =
static_cast<char>(value);
484 }
else if (minBytes <= 2 && value <= 0xFFFFul) {
485 BE::getBytes(static_cast<uint16>(value), buff);
487 }
else if (minBytes <= 3 && value <= 0xFFFFFFul) {
488 BE::getBytes(static_cast<uint32>(value << 0x08), buff);
490 }
else if (minBytes <= 4 && value <= 0xFFFFFFFFul) {
491 BE::getBytes(static_cast<uint32>(value), buff);
493 }
else if (minBytes <= 5 && value <= 0xFFFFFFFFFFul) {
494 BE::getBytes(static_cast<uint64>(value << 0x18), buff);
496 }
else if (minBytes <= 6 && value <= 0xFFFFFFFFFFFFul) {
497 BE::getBytes(static_cast<uint64>(value << 0x10), buff);
499 }
else if (minBytes <= 7 && value <= 0xFFFFFFFFFFFFFFul) {
500 BE::getBytes(static_cast<uint64>(value << 0x08), buff);
503 BE::getBytes(static_cast<uint64>(value), buff);
523 stream.write(buff2, elementSize);
539 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.
The exception that is thrown when the data to be parsed is truncated and therefore can not be parsed ...
static void makeSimpleElement(std::ostream &stream, IdentifierType id, uint64 content)
Makes a simple EBML element.
std::unique_ptr< ImplementationType > m_firstChild
Implementation of GenericContainer<MediaFileInfo, MatroskaTag, MatroskaTrack, EbmlElement>.
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.
The EbmlElement class helps to parse EBML files such as Matroska files.
uint64 totalSize() const
Returns the total size of the element.
The GenericFileElement class helps to parse binary files which consist of an arboreal element strucut...
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.
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
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.
Contains all classes and functions of the TagInfo library.
byte level() const
Returns how deep the element is nested (0 for top-level elements, 1 for children of top-level element...
The Diagnostics class is a container for DiagMessage.
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.