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(uint64 start, int64 amount)
27 for (
auto &info : m_info) {
28 if (get<1>(info) >= start) {
29 get<1>(info) += amount;
42 static const string context(
"parsing \"SeekHead\"-element");
43 m_seekHeadElement = seekHeadElement;
46 EbmlElement *seekElementChild, *seekIdElement, *seekPositionElement;
48 seekElement->
parse(diag);
49 switch (seekElement->
id()) {
52 seekIdElement = seekPositionElement =
nullptr;
53 while (seekElementChild) {
54 seekElementChild->
parse(diag);
55 switch (seekElementChild->
id()) {
58 diag.emplace_back(DiagLevel::Warning,
59 "The \"Seek\"-element contains multiple \"SeekID\"-elements. Surplus elements will be ignored.", context);
61 seekIdElement = seekElementChild;
64 if (seekPositionElement) {
65 diag.emplace_back(DiagLevel::Warning,
66 "The \"Seek\"-element contains multiple \"SeekPosition\"-elements. Surplus elements will be ignored.", context);
68 seekPositionElement = seekElementChild;
74 diag.emplace_back(DiagLevel::Warning,
75 "The element \"" % seekElementChild->
idToString()
76 +
"\" within the \"Seek\" element is not a \"SeekID\"-element nor a \"SeekPosition\"-element and will be ignored.",
81 if (seekIdElement && seekPositionElement) {
84 diag.emplace_back(DiagLevel::Warning,
"The \"Seek\"-element does not contain a \"SeekID\"- and a \"SeekPosition\"-element.", context);
92 DiagLevel::Warning,
"The element " % seekElement->
idToString() +
" is not a seek element and will be ignored.", context);
97 diag.emplace_back(DiagLevel::Warning,
"No seek information found.", context);
109 uint64 totalSize = 0;
113 byte sizeLength0, sizeLength1;
115 for (
const auto &info : m_info) {
117 totalSize += 2 + 1 + (2 + 1 + EbmlElement::calculateIdLength(get<0>(info))) + (2 + 1 + EbmlElement::calculateUIntegerLength(get<1>(info)));
121 stream.write(buff0, 4);
122 sizeLength0 = EbmlElement::makeSizeDenotation(totalSize, buff0);
123 stream.write(buff0, sizeLength0);
125 for (
const auto &info : m_info) {
127 sizeLength0 = EbmlElement::makeId(get<0>(info), buff0);
128 sizeLength1 = EbmlElement::makeUInteger(get<1>(info), buff1);
131 stream.write(buff2, 2);
132 stream.put(0x80 | (2 + 1 + sizeLength0 + 2 + 1 + sizeLength1));
135 stream.write(buff2, 2);
136 stream.put(0x80 | sizeLength0);
137 stream.write(buff0, sizeLength0);
140 stream.write(buff2, 2);
141 stream.put(0x80 | sizeLength1);
142 stream.write(buff1, sizeLength1);
150 uint64 MatroskaSeekInfo::minSize()
const 152 uint64 maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 1 + 2 + 1 + 1);
153 return 4 + EbmlElement::calculateSizeDenotationLength(maxTotalSize) + maxTotalSize;
160 uint64 MatroskaSeekInfo::maxSize()
const 162 uint64 maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 4 + 2 + 1 + 8);
163 return 4 + EbmlElement::calculateSizeDenotationLength(maxTotalSize) + maxTotalSize;
170 uint64 MatroskaSeekInfo::actualSize()
const 172 uint64 totalSize = 0;
173 for (
const auto &info : m_info) {
175 totalSize += 2 + 1 + (2 + 1 + EbmlElement::calculateIdLength(get<0>(info))) + (2 + 1 + EbmlElement::calculateUIntegerLength(get<1>(info)));
177 return totalSize += 4 + EbmlElement::calculateSizeDenotationLength(totalSize);
190 unsigned int currentIndex = 0;
191 for (
auto &entry : info()) {
192 if (get<0>(entry) ==
id) {
193 if (index == currentIndex) {
194 bool sizeUpdated = EbmlElement::calculateUIntegerLength(get<1>(entry)) != EbmlElement::calculateUIntegerLength(offset);
195 get<1>(entry) = offset;
201 info().emplace_back(
id, offset);
208 void MatroskaSeekInfo::clear()
210 m_seekHeadElement =
nullptr;
217 std::pair<EbmlElement::IdentifierType, uint64> *MatroskaSeekInfo::findSeekInfo(std::vector<MatroskaSeekInfo> &seekInfos, uint64 offset)
219 for (
auto &seekInfo : seekInfos) {
220 for (
auto &entry : seekInfo.info()) {
221 if (get<1>(entry) == offset) {
233 bool MatroskaSeekInfo::updateSeekInfo(
234 const std::vector<MatroskaSeekInfo> &oldSeekInfos, std::vector<MatroskaSeekInfo> &newSeekInfos, uint64 oldOffset, uint64 newOffset)
236 bool updated =
false;
237 auto oldIterator0 = oldSeekInfos.cbegin(), oldEnd0 = oldSeekInfos.cend();
238 auto newIterator0 = newSeekInfos.begin(), newEnd0 = newSeekInfos.end();
239 for (; oldIterator0 != oldEnd0 && newIterator0 != newEnd0; ++oldIterator0, ++newIterator0) {
240 auto oldIterator1 = oldIterator0->info().cbegin(), oldEnd1 = oldIterator0->info().cend();
241 auto newIterator1 = newIterator0->info().begin(), newEnd1 = newIterator0->info().end();
242 for (; oldIterator1 != oldEnd1 && newIterator1 != newEnd1; ++oldIterator1, ++newIterator1) {
243 if (get<1>(*oldIterator1) == oldOffset) {
244 if (get<1>(*newIterator1) != newOffset) {
246 = updated || (EbmlElement::calculateUIntegerLength(newOffset) != EbmlElement::calculateUIntegerLength(get<1>(*newIterator1)));
247 get<1>(*newIterator1) = newOffset;
259 bool MatroskaSeekInfo::updateSeekInfo(std::vector<MatroskaSeekInfo> &newSeekInfos, uint64 oldOffset, uint64 newOffset)
261 if (oldOffset == newOffset) {
264 bool updated =
false;
265 for (
auto &seekInfo : newSeekInfos) {
266 for (
auto &info : seekInfo.info()) {
267 if (get<1>(info) == oldOffset) {
268 get<1>(info) = newOffset;
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * firstChild()
Returns the first child of the element.
std::string idToString() const
Converts the specified EBML ID to a printable string.
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
uint64 readUInteger()
Reads the content of the element as unsigned integer.
void clear()
Clears the status of the element.
const IdentifierType & id() const
Returns the element ID.
FileElementTraits< ImplementationType >::IdentifierType IdentifierType
Specifies the type used to store identifiers.