4 #include "../diagnostics.h"
5 #include "../exceptions.h"
7 #include <c++utilities/conversion/binaryconversion.h>
8 #include <c++utilities/conversion/stringbuilder.h>
25 void MatroskaSeekInfo::shift(std::uint64_t start, std::int64_t amount)
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;
58 seekElement = seekElement->nextSibling()) {
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()) {
68 diag.emplace_back(DiagLevel::Warning,
69 "The \"Seek\"-element contains multiple \"SeekID\"-elements. Surplus elements will be ignored.", context);
71 seekIdElement = seekElementChild;
74 if (seekPositionElement) {
75 diag.emplace_back(DiagLevel::Warning,
76 "The \"Seek\"-element contains multiple \"SeekPosition\"-elements. Surplus elements will be ignored.", context);
78 seekPositionElement = seekElementChild;
84 diag.emplace_back(DiagLevel::Warning,
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) {
102 diag.emplace_back(DiagLevel::Warning,
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) {
112 diag.emplace_back(DiagLevel::Warning,
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()) {
137 diag.emplace_back(DiagLevel::Warning,
"No seek information found.", context);
149 CPP_UTILITIES_UNUSED(diag)
151 std::uint64_t totalSize = 0;
155 std::uint8_t sizeLength0, sizeLength1;
157 for (
const auto &info : m_info) {
159 totalSize += 2 + 1 + (2 + 1 + EbmlElement::calculateIdLength(get<0>(info))) + (2 + 1 + EbmlElement::calculateUIntegerLength(get<1>(info)));
163 stream.write(buff0, 4);
164 sizeLength0 = EbmlElement::makeSizeDenotation(totalSize, buff0);
165 stream.write(buff0, sizeLength0);
167 for (
const auto &info : m_info) {
169 sizeLength0 = EbmlElement::makeId(get<0>(info), buff0);
170 sizeLength1 = EbmlElement::makeUInteger(get<1>(info), buff1);
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);
192 std::uint64_t MatroskaSeekInfo::minSize()
const
194 std::uint64_t maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 1 + 2 + 1 + 1);
195 return 4 + EbmlElement::calculateSizeDenotationLength(maxTotalSize) + maxTotalSize;
202 std::uint64_t MatroskaSeekInfo::maxSize()
const
204 std::uint64_t maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 4 + 2 + 1 + 8);
205 return 4 + EbmlElement::calculateSizeDenotationLength(maxTotalSize) + maxTotalSize;
212 std::uint64_t MatroskaSeekInfo::actualSize()
const
214 std::uint64_t totalSize = 0;
215 for (
const auto &info : m_info) {
217 totalSize += 2 + 1 + (2 + 1 + EbmlElement::calculateIdLength(get<0>(info))) + (2 + 1 + EbmlElement::calculateUIntegerLength(get<1>(info)));
219 return totalSize += 4 + EbmlElement::calculateSizeDenotationLength(totalSize);
232 unsigned int currentIndex = 0;
233 for (
auto &entry : info()) {
234 if (get<0>(entry) ==
id) {
235 if (index == currentIndex) {
236 bool sizeUpdated = EbmlElement::calculateUIntegerLength(get<1>(entry)) != EbmlElement::calculateUIntegerLength(offset);
237 get<1>(entry) = offset;
243 info().emplace_back(
id, offset);
250 void MatroskaSeekInfo::clear()
252 m_seekHeadElements.clear();
253 m_additionalSeekHeadElements.clear();