7#include <c++utilities/conversion/binaryconversion.h>
8#include <c++utilities/conversion/stringbuilder.h>
27 for (
auto &
info : m_info) {
28 if (get<1>(
info) >= start) {
30 get<1>(
info) +=
static_cast<std::uint64_t
>(amount);
32 get<1>(
info) -=
static_cast<std::uint64_t
>(-amount);
53 static const string context(
"parsing \"SeekHead\"-element");
55 m_seekHeadElements.emplace_back(seekHeadElement);
57 for (
EbmlElement *seekElement = seekHeadElement->
firstChild(), *seekIdElement, *seekPositionElement; seekElement;
59 seekElement->parse(diag);
60 switch (seekElement->id()) {
62 seekIdElement = seekPositionElement =
nullptr;
63 for (
auto *seekElementChild = seekElement->firstChild(); seekElementChild; seekElementChild = seekElementChild->nextSibling()) {
64 seekElementChild->parse(diag);
65 switch (seekElementChild->id()) {
69 "The \"Seek\"-element contains multiple \"SeekID\"-elements. Surplus elements will be ignored.", context);
71 seekIdElement = seekElementChild;
74 if (seekPositionElement) {
76 "The \"Seek\"-element contains multiple \"SeekPosition\"-elements. Surplus elements will be ignored.", context);
78 seekPositionElement = seekElementChild;
85 "The element \"" % seekElementChild->idToString()
86 +
"\" within the \"Seek\" element is not a \"SeekID\"-element nor a \"SeekPosition\"-element and will be ignored.",
91 if (!seekIdElement || !seekPositionElement) {
92 diag.emplace_back(
DiagLevel::Warning,
"The \"Seek\"-element does not contain a \"SeekID\"- and a \"SeekPosition\"-element.", context);
96 m_info.emplace_back(seekIdElement->readUInteger(), seekPositionElement->readUInteger());
100 const auto startOffset = m_info.back().second;
101 if (!maxIndirection) {
103 argsToString(
"Not following reference by \"Seek\"-element at ", seekElement->startOffset(),
104 " which points to another \"SeekHead\"-element at ", startOffset,
'.'),
109 auto visited =
false;
110 for (
const auto *
const visitedSeekHeadElement : m_seekHeadElements) {
111 if (visitedSeekHeadElement->startOffset() == startOffset) {
113 argsToString(
"The \"Seek\"-element at ", seekElement->startOffset(),
" contains a loop to the \"SeekHead\"-element at ",
114 visitedSeekHeadElement->startOffset(),
'.'),
123 m_additionalSeekHeadElements.emplace_back(make_unique<EbmlElement>(seekHeadElement->
container(), startOffset));
124 parse(m_additionalSeekHeadElements.back().get(), diag, maxIndirection - 1);
133 DiagLevel::Warning,
"The element " % seekElement->idToString() +
" is not a seek element and will be ignored.", context);
136 if (m_info.empty()) {
149 CPP_UTILITIES_UNUSED(diag)
151 std::uint64_t totalSize = 0;
155 std::uint8_t sizeLength0, sizeLength1;
157 for (
const auto &
info : m_info) {
163 stream.write(buff0, 4);
165 stream.write(buff0, sizeLength0);
167 for (
const auto &
info : m_info) {
173 stream.write(buff2, 2);
174 stream.put(
static_cast<char>(0x80 | (2 + 1 + sizeLength0 + 2 + 1 + sizeLength1)));
177 stream.write(buff2, 2);
178 stream.put(
static_cast<char>(0x80 | sizeLength0));
179 stream.write(buff0, sizeLength0);
182 stream.write(buff2, 2);
183 stream.put(
static_cast<char>(0x80 | sizeLength1));
184 stream.write(buff1, sizeLength1);
194 std::uint64_t maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 1 + 2 + 1 + 1);
204 std::uint64_t maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 4 + 2 + 1 + 8);
214 std::uint64_t totalSize = 0;
215 for (
const auto &
info : m_info) {
233 unsigned int currentIndex = 0;
234 for (
auto &entry :
info()) {
235 if (get<0>(entry) ==
id) {
236 if (index == currentIndex) {
238 get<1>(entry) = offset;
244 info().emplace_back(
id, offset);
253 m_seekHeadElements.clear();
254 m_additionalSeekHeadElements.clear();
The Diagnostics class is a container for DiagMessage.
The EbmlElement class helps to parse EBML files such as Matroska files.
static std::uint8_t makeUInteger(std::uint64_t value, char *buff)
Writes value to buff.
static std::uint8_t calculateIdLength(IdentifierType id)
Returns the length of the specified id in byte.
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
static std::uint8_t makeId(IdentifierType id, char *buff)
Stores the specified id in the specified buffer which must be at least 8 bytes long.
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
static std::uint8_t calculateUIntegerLength(std::uint64_t integer)
Returns the length of the specified unsigned integer in byte.
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * firstChild()
Returns the first child of the element.
typename FileElementTraits< EbmlElement >::IdentifierType IdentifierType
ContainerType & container()
Returns the related container.
void parse(EbmlElement *seekHeadElements, Diagnostics &diag, std::size_t maxIndirection=1)
Parses the specified seekHeadElement and populates info() with the gathered information.
void shift(std::uint64_t start, std::int64_t amount)
Shifts all offsets greater or equal than start by amount bytes.
void clear()
Resets the object to its initial state.
bool push(unsigned int index, EbmlElement::IdentifierType id, std::uint64_t offset)
Pushes the specified offset of an element with the specified id to the info.
void make(std::ostream &stream, Diagnostics &diag)
Writes a "SeekHead" element for the current instance to the specified stream.
std::vector< std::pair< EbmlElement::IdentifierType, std::uint64_t > > & info()
Returns a mutable version of the seek information gathered when the parse() method was called.
std::uint64_t maxSize() const
Returns the maximal number of bytes written when calling the make() method.
std::uint64_t minSize() const
Returns the minimal number of bytes written when calling the make() method.
std::uint64_t actualSize() const
Returns the number of bytes which will be written when calling the make() method.
Contains all classes and functions of the TagInfo library.