4 #include "../diagnostics.h"
6 #include <initializer_list>
22 using namespace MatroskaTagIds;
30 case KnownField::RecordDate:
33 case KnownField::ReleaseDate:
39 case KnownField::PartNumber:
41 case KnownField::TotalParts:
45 case KnownField::EncoderSettings:
65 case KnownField::Length:
67 case KnownField::Language:
74 KnownField MatroskaTag::internallyGetKnownField(
const IdentifierType &
id)
const
76 using namespace MatroskaTagIds;
77 static const map<string, KnownField> fieldMap({
89 {
bps(), KnownField::Bps },
98 {
language(), KnownField::Language },
100 const auto knownField(fieldMap.find(
id));
101 return knownField != fieldMap.cend() ? knownField->second : KnownField::Invalid;
113 static const string context(
"parsing Matroska tag");
114 tagElement.
parse(diag);
115 if (tagElement.
totalSize() > numeric_limits<std::uint32_t>::max()) {
117 diag.emplace_back(DiagLevel::Critical,
"Matroska tag is too big.", context);
120 m_size =
static_cast<std::uint32_t
>(tagElement.
totalSize());
123 switch (child->id()) {
127 field.
reparse(*child, diag,
true);
128 fields().emplace(field.
id(), move(field));
133 parseTargets(*child, diag);
148 static const string context(
"parsing targets of Matroska tag");
150 bool targetTypeValueFound =
false;
151 bool targetTypeFound =
false;
152 targetsElement.
parse(diag);
156 }
catch (
const Failure &) {
157 diag.emplace_back(DiagLevel::Critical,
"Unable to parse children of Targets element.", context);
160 switch (child->id()) {
162 if (!targetTypeValueFound) {
163 m_target.setLevel(child->readUInteger());
164 targetTypeValueFound =
true;
167 DiagLevel::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
171 if (!targetTypeFound) {
172 m_target.setLevelName(child->readString());
173 targetTypeFound =
true;
176 DiagLevel::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
180 m_target.tracks().emplace_back(child->readUInteger());
183 m_target.editions().emplace_back(child->readUInteger());
186 m_target.chapters().emplace_back(child->readUInteger());
189 m_target.attachments().emplace_back(child->readUInteger());
192 diag.emplace_back(DiagLevel::Warning,
"Targets element contains unknown element. It will be ignored.", context);
195 if (!m_target.level()) {
196 m_target.setLevel(50);
211 MatroskaTagMaker::MatroskaTagMaker(MatroskaTag &tag, Diagnostics &diag)
216 if (m_tag.target().level() != 50) {
220 if (!m_tag.target().levelName().empty()) {
224 for (
const auto &v : initializer_list<vector<std::uint64_t>>{
225 m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments() }) {
233 m_maker.reserve(m_tag.fields().size());
234 m_simpleTagsSize = 0;
235 for (
auto &pair : m_tag.fields()) {
237 m_maker.emplace_back(pair.second.prepareMaking(diag));
238 m_simpleTagsSize += m_maker.back().requiredSize();
239 }
catch (
const Failure &) {
242 m_tagSize += m_simpleTagsSize;
258 stream.write(buff, 2);
260 stream.write(buff, len);
263 stream.write(buff, 2);
265 stream.write(buff, len);
267 if (t.
level() != 50) {
270 stream.write(buff, 2);
272 stream.put(
static_cast<char>(0x80 | len));
273 stream.write(buff, len);
278 stream.write(buff, 2);
280 stream.write(buff, len);
284 using p = pair<std::uint16_t, vector<std::uint64_t>>;
287 if (!pair.second.empty()) {
288 BE::getBytes(pair.first, buff);
289 for (
auto uid : pair.second) {
291 *(buff + 2) =
static_cast<char>(0x80 | len);
292 stream.write(buff, 3 + len);
297 for (
const auto &maker : m_maker) {