4 #include "../diagnostics.h" 6 #include <initializer_list> 22 using namespace MatroskaTagIds;
30 case KnownField::RecordDate:
38 case KnownField::PartNumber:
40 case KnownField::TotalParts:
44 case KnownField::EncoderSettings:
64 case KnownField::Length:
66 case KnownField::Language:
73 KnownField MatroskaTag::internallyGetKnownField(
const IdentifierType &
id)
const 75 using namespace MatroskaTagIds;
76 static const map<string, KnownField> fieldMap({
88 {
bps(), KnownField::Bps },
97 {
language(), KnownField::Language },
99 const auto knownField(fieldMap.find(
id));
100 return knownField != fieldMap.cend() ? knownField->second : KnownField::Invalid;
112 static const string context(
"parsing Matroska tag");
113 tagElement.
parse(diag);
114 if (tagElement.
totalSize() > numeric_limits<uint32>::max()) {
116 diag.emplace_back(DiagLevel::Critical,
"Matroska tag is too big.", context);
119 m_size =
static_cast<uint32
>(tagElement.
totalSize());
122 switch (child->id()) {
126 field.
reparse(*child, diag,
true);
127 fields().emplace(field.
id(), move(field));
132 parseTargets(*child, diag);
147 static const string context(
"parsing targets of Matroska tag");
149 bool targetTypeValueFound =
false;
150 bool targetTypeFound =
false;
151 targetsElement.
parse(diag);
155 }
catch (
const Failure &) {
156 diag.emplace_back(DiagLevel::Critical,
"Unable to parse childs of Targets element.", context);
159 switch (child->id()) {
161 if (!targetTypeValueFound) {
162 m_target.setLevel(child->readUInteger());
163 targetTypeValueFound =
true;
166 DiagLevel::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
170 if (!targetTypeFound) {
171 m_target.setLevelName(child->readString());
172 targetTypeFound =
true;
175 DiagLevel::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
179 m_target.tracks().emplace_back(child->readUInteger());
182 m_target.editions().emplace_back(child->readUInteger());
185 m_target.chapters().emplace_back(child->readUInteger());
188 m_target.attachments().emplace_back(child->readUInteger());
191 diag.emplace_back(DiagLevel::Warning,
"Targets element contains unknown element. It will be ignored.", context);
194 if (!m_target.level()) {
195 m_target.setLevel(50);
210 MatroskaTagMaker::MatroskaTagMaker(MatroskaTag &tag, Diagnostics &diag)
215 if (m_tag.target().level() != 50) {
219 if (!m_tag.target().levelName().empty()) {
223 for (
const auto &v : initializer_list<vector<uint64>>{
224 m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments() }) {
232 m_maker.reserve(m_tag.fields().size());
233 m_simpleTagsSize = 0;
234 for (
auto &pair : m_tag.fields()) {
236 m_maker.emplace_back(pair.second.prepareMaking(diag));
237 m_simpleTagsSize += m_maker.back().requiredSize();
238 }
catch (
const Failure &) {
241 m_tagSize += m_simpleTagsSize;
257 stream.write(buff, 2);
259 stream.write(buff, len);
262 stream.write(buff, 2);
264 stream.write(buff, len);
266 if (t.
level() != 50) {
269 stream.write(buff, 2);
271 stream.put(static_cast<char>(0x80 | len));
272 stream.write(buff, len);
277 stream.write(buff, 2);
279 stream.write(buff, len);
283 using p = pair<uint16, vector<uint64>>;
286 if (!pair.second.empty()) {
287 BE::getBytes(pair.first, buff);
288 for (
auto uid : pair.second) {
290 *(buff + 2) = static_cast<char>(0x80 | len);
291 stream.write(buff, 3 + len);
296 for (
const auto &maker : m_maker) {
constexpr TAG_PARSER_EXPORT const char * encoder()
This exception is thrown when the an operation is invoked that has not been implemented yet...
constexpr TAG_PARSER_EXPORT const char * bpm()
constexpr TAG_PARSER_EXPORT const char * dateRecorded()
typename FieldMapBasedTagTraits< MatroskaTag >::FieldType::IdentifierType IdentifierType
const IdContainerType & attachments() const
Returns the attachments.
ImplementationType * firstChild()
Returns the first child of the element.
static byte calculateSizeDenotationLength(uint64 size)
Returns the length of the size denotation for the specified size in byte.
uint64 level() const
Returns the level.
constexpr TAG_PARSER_EXPORT const char * lyrics()
constexpr TAG_PARSER_EXPORT const char * lyricist()
KnownField
Specifies the field.
static byte calculateUIntegerLength(uint64 integer)
Returns the length of the specified unsigned integer in byte.
The EbmlElement class helps to parse EBML files such as Matroska files.
uint64 totalSize() const
Returns the total size of the element.
The MatroskaTagField class is used by MatroskaTag to store the fields.
constexpr TAG_PARSER_EXPORT const char * rating()
constexpr TAG_PARSER_EXPORT const char * language()
constexpr TAG_PARSER_EXPORT const char * encoderSettings()
constexpr TAG_PARSER_EXPORT const char * comment()
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
constexpr TAG_PARSER_EXPORT const char * actor()
static byte makeUInteger(uint64 value, char *buff)
Writes value to buff.
static byte makeSizeDenotation(uint64 size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
The TagTarget class specifies the target of a tag.
constexpr TAG_PARSER_EXPORT const char * partNumber()
constexpr TAG_PARSER_EXPORT const char * album()
constexpr TAG_PARSER_EXPORT const char * dateRelease()
constexpr TAG_PARSER_EXPORT const char * title()
const IdentifierType & id() const
Returns the id of the current TagField.
constexpr TAG_PARSER_EXPORT const char * bps()
constexpr TAG_PARSER_EXPORT const char * genre()
void make(std::ostream &stream) const
Saves the tag (specified when constructing the object) to the specified stream (makes a "Tag"-element...
const IdContainerType & tracks() const
Returns the tracks.
constexpr TAG_PARSER_EXPORT const char * duration()
constexpr TAG_PARSER_EXPORT const char * artist()
constexpr TAG_PARSER_EXPORT const char * composer()
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
const std::string & levelName() const
Returns the level name.
const IdContainerType & editions() const
Returns the editions.
constexpr TAG_PARSER_EXPORT const char * description()
const IdContainerType & chapters() const
Returns the chapters.
const TagTarget & target() const
Returns the target of tag.
Contains all classes and functions of the TagInfo library.
void reparse(EbmlElement &simpleTagElement, Diagnostics &diag, bool parseNestedFields=true)
Parses field information from the specified EbmlElement.
constexpr TAG_PARSER_EXPORT const char * totalParts()
The Diagnostics class is a container for DiagMessage.