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) {
30 get<1>(info) += static_cast<uint64>(amount);
32 get<1>(info) -= static_cast<uint64>(-amount);
46 static const string context(
"parsing \"SeekHead\"-element");
47 m_seekHeadElement = seekHeadElement;
50 EbmlElement *seekElementChild, *seekIdElement, *seekPositionElement;
52 seekElement->
parse(diag);
53 switch (seekElement->
id()) {
56 seekIdElement = seekPositionElement =
nullptr;
57 while (seekElementChild) {
58 seekElementChild->
parse(diag);
59 switch (seekElementChild->
id()) {
62 diag.emplace_back(DiagLevel::Warning,
63 "The \"Seek\"-element contains multiple \"SeekID\"-elements. Surplus elements will be ignored.", context);
65 seekIdElement = seekElementChild;
68 if (seekPositionElement) {
69 diag.emplace_back(DiagLevel::Warning,
70 "The \"Seek\"-element contains multiple \"SeekPosition\"-elements. Surplus elements will be ignored.", context);
72 seekPositionElement = seekElementChild;
78 diag.emplace_back(DiagLevel::Warning,
79 "The element \"" % seekElementChild->
idToString()
80 +
"\" within the \"Seek\" element is not a \"SeekID\"-element nor a \"SeekPosition\"-element and will be ignored.",
85 if (seekIdElement && seekPositionElement) {
88 diag.emplace_back(DiagLevel::Warning,
"The \"Seek\"-element does not contain a \"SeekID\"- and a \"SeekPosition\"-element.", context);
96 DiagLevel::Warning,
"The element " % seekElement->
idToString() +
" is not a seek element and will be ignored.", context);
100 if (m_info.empty()) {
101 diag.emplace_back(DiagLevel::Warning,
"No seek information found.", context);
115 uint64 totalSize = 0;
119 byte sizeLength0, sizeLength1;
121 for (
const auto &info : m_info) {
123 totalSize += 2 + 1 + (2 + 1 + EbmlElement::calculateIdLength(get<0>(info))) + (2 + 1 + EbmlElement::calculateUIntegerLength(get<1>(info)));
127 stream.write(buff0, 4);
128 sizeLength0 = EbmlElement::makeSizeDenotation(totalSize, buff0);
129 stream.write(buff0, sizeLength0);
131 for (
const auto &info : m_info) {
133 sizeLength0 = EbmlElement::makeId(get<0>(info), buff0);
134 sizeLength1 = EbmlElement::makeUInteger(get<1>(info), buff1);
137 stream.write(buff2, 2);
138 stream.put(static_cast<char>(0x80 | (2 + 1 + sizeLength0 + 2 + 1 + sizeLength1)));
141 stream.write(buff2, 2);
142 stream.put(static_cast<char>(0x80 | sizeLength0));
143 stream.write(buff0, sizeLength0);
146 stream.write(buff2, 2);
147 stream.put(static_cast<char>(0x80 | sizeLength1));
148 stream.write(buff1, sizeLength1);
156 uint64 MatroskaSeekInfo::minSize()
const 158 uint64 maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 1 + 2 + 1 + 1);
159 return 4 + EbmlElement::calculateSizeDenotationLength(maxTotalSize) + maxTotalSize;
166 uint64 MatroskaSeekInfo::maxSize()
const 168 uint64 maxTotalSize = m_info.size() * (2 + 1 + 2 + 1 + 4 + 2 + 1 + 8);
169 return 4 + EbmlElement::calculateSizeDenotationLength(maxTotalSize) + maxTotalSize;
176 uint64 MatroskaSeekInfo::actualSize()
const 178 uint64 totalSize = 0;
179 for (
const auto &info : m_info) {
181 totalSize += 2 + 1 + (2 + 1 + EbmlElement::calculateIdLength(get<0>(info))) + (2 + 1 + EbmlElement::calculateUIntegerLength(get<1>(info)));
183 return totalSize += 4 + EbmlElement::calculateSizeDenotationLength(totalSize);
196 unsigned int currentIndex = 0;
197 for (
auto &entry : info()) {
198 if (get<0>(entry) ==
id) {
199 if (index == currentIndex) {
200 bool sizeUpdated = EbmlElement::calculateUIntegerLength(get<1>(entry)) != EbmlElement::calculateUIntegerLength(offset);
201 get<1>(entry) = offset;
207 info().emplace_back(
id, offset);
214 void MatroskaSeekInfo::clear()
216 m_seekHeadElement =
nullptr;
223 std::pair<EbmlElement::IdentifierType, uint64> *MatroskaSeekInfo::findSeekInfo(std::vector<MatroskaSeekInfo> &seekInfos, uint64 offset)
225 for (
auto &seekInfo : seekInfos) {
226 for (
auto &entry : seekInfo.info()) {
227 if (get<1>(entry) == offset) {
239 bool MatroskaSeekInfo::updateSeekInfo(
240 const std::vector<MatroskaSeekInfo> &oldSeekInfos, std::vector<MatroskaSeekInfo> &newSeekInfos, uint64 oldOffset, uint64 newOffset)
242 bool updated =
false;
243 auto oldIterator0 = oldSeekInfos.cbegin(), oldEnd0 = oldSeekInfos.cend();
244 auto newIterator0 = newSeekInfos.begin(), newEnd0 = newSeekInfos.end();
245 for (; oldIterator0 != oldEnd0 && newIterator0 != newEnd0; ++oldIterator0, ++newIterator0) {
246 auto oldIterator1 = oldIterator0->info().cbegin(), oldEnd1 = oldIterator0->info().cend();
247 auto newIterator1 = newIterator0->info().begin(), newEnd1 = newIterator0->info().end();
248 for (; oldIterator1 != oldEnd1 && newIterator1 != newEnd1; ++oldIterator1, ++newIterator1) {
249 if (get<1>(*oldIterator1) == oldOffset) {
250 if (get<1>(*newIterator1) != newOffset) {
252 = updated || (EbmlElement::calculateUIntegerLength(newOffset) != EbmlElement::calculateUIntegerLength(get<1>(*newIterator1)));
253 get<1>(*newIterator1) = newOffset;
265 bool MatroskaSeekInfo::updateSeekInfo(std::vector<MatroskaSeekInfo> &newSeekInfos, uint64 oldOffset, uint64 newOffset)
267 if (oldOffset == newOffset) {
270 bool updated =
false;
271 for (
auto &seekInfo : newSeekInfos) {
272 for (
auto &info : seekInfo.info()) {
273 if (get<1>(info) == oldOffset) {
274 get<1>(info) = newOffset;
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * firstChild()
Returns the first child of the element.
The EbmlElement class helps to parse EBML files such as Matroska files.
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.
typename FileElementTraits< ImplementationType >::IdentifierType IdentifierType
Specifies the type used to store identifiers.
const IdentifierType & id() const
Returns the element ID.
Contains all classes and functions of the TagInfo library.
The Diagnostics class is a container for DiagMessage.