8#include <c++utilities/io/binarywriter.h>
49 string context(
"parsing Matroska tag field");
50 simpleTagElement.
parse(diag);
51 bool tagDefaultFound =
false, tagLanguageFound =
false, tagLanguageIETFFound =
false;
56 diag.emplace_back(
DiagLevel::Critical,
"Unable to parse children of \"SimpleTag\"-element.", context);
59 switch (child->id()) {
62 setId(child->readString());
63 context =
"parsing Matroska tag field " +
id();
66 "\"SimpleTag\"-element contains multiple \"TagName\"-elements. Surplus TagName elements will be ignored.", context);
71 if (
value().isEmpty()) {
72 unique_ptr<char[]> buffer = make_unique<char[]>(child->dataSize());
73 child->stream().seekg(
static_cast<streamoff
>(child->dataOffset()));
74 child->stream().read(buffer.get(),
static_cast<streamoff
>(child->dataSize()));
75 switch (child->id()) {
85 "\"SimpleTag\"-element contains multiple \"TagString\"/\"TagBinary\"-elements. Surplus \"TagName\"/\"TagBinary\"-elements will "
91 if (!tagLanguageFound) {
92 tagLanguageFound =
true;
93 auto language = child->readString();
94 if (language !=
"und") {
99 "\"SimpleTag\"-element contains multiple \"TagLanguage\"-elements. Surplus \"TagLanguage\"-elements will be ignored.", context);
103 if (!tagLanguageIETFFound) {
104 tagLanguageIETFFound =
true;
108 "\"SimpleTag\"-element contains multiple \"TagLanguageIETF\"-elements. Surplus \"TagLanguageIETF\"-elements will be ignored.",
113 if (!tagDefaultFound) {
115 tagDefaultFound =
true;
118 "\"SimpleTag\"-element contains multiple \"TagDefault\" elements. Surplus \"TagDefault\"-elements will be ignored.", context);
122 if (parseNestedFields) {
127 "Nested fields are currently not supported. Nested tags can not be displayed and will be discarded when rewriting the file.",
137 "\"SimpleTag\"-element contains unknown element ", child->idToString(),
" at ", child->startOffset(),
". It will be ignored."),
145 }
catch (
const ConversionException &) {
146 diag.emplace_back(
DiagLevel::Warning, argsToString(
"The rating is not a number."), context);
164 static const string context(
"making Matroska \"SimpleTag\" element.");
167 diag.emplace_back(
DiagLevel::Critical,
"Can not make \"SimpleTag\" element with empty \"TagName\".", context);
172 }
catch (
const ConversionException &) {
173 diag.emplace_back(
DiagLevel::Critical,
"The assigned tag value can not be converted to be written appropriately.", context);
196 if (c >=
'a' && c <=
'z') {
225 }
catch (
const ConversionException &) {
227 "The assigned tag value can not be converted to a string and is treated as binary value (which is likely not what you want since "
228 "official Matroska specifiecation doesn't list any binary fields).",
229 "making Matroska \"SimpleTag\" element.");
234 const auto languageSize = m_language.empty() ? 3 : m_language.size();
237 const auto languageIETFElementSize
244 + m_field.id().size()
246 + languageElementSize
247 + languageIETFElementSize
256 m_nestedMaker.emplace_back(nestedField.prepareMaking(diag));
257 m_simpleTagSize += m_nestedMaker.back().m_totalSize;
271 BinaryWriter writer(&stream);
276 stream.write(buff, sizeDenotationLen);
280 stream.write(buff, sizeDenotationLen);
281 stream.write(m_field.
id().c_str(),
static_cast<std::streamsize
>(m_field.
id().size()));
284 if (m_language.empty()) {
285 stream.put(
static_cast<ostream::char_type
>(0x80 | 3));
286 stream.write(
"und", 3);
289 stream.write(buff, sizeDenotationLen);
290 stream.write(m_language.data(),
static_cast<std::streamsize
>(m_language.size()));
293 if (!m_languageIETF.empty()) {
296 stream.write(buff, sizeDenotationLen);
297 stream.write(m_languageIETF.data(),
static_cast<std::streamsize
>(m_languageIETF.size()));
301 stream.put(
static_cast<ostream::char_type
>(0x80 | 1));
307 stream.write(buff, sizeDenotationLen);
312 stream.write(buff, sizeDenotationLen);
313 stream.write(m_stringValue.data(),
static_cast<std::streamsize
>(m_stringValue.size()));
316 for (
const auto &maker : m_nestedMaker) {
The Diagnostics class is a container for DiagMessage.
The EbmlElement class helps to parse EBML files such as Matroska files.
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * firstChild()
Returns the first child of the element.
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
The MatroskaTagFieldMaker class helps making tag fields.
void make(std::ostream &stream) const
Saves the field (specified when constructing the object) to the specified stream (makes a "SimpleTag"...
The MatroskaTagField class is used by MatroskaTag to store the fields.
static void normalizeId(std::string &id)
Ensures the specified id is upper-case as recommended by the Matroska spec.
void reparse(EbmlElement &simpleTagElement, Diagnostics &diag, bool parseNestedFields=true)
Parses field information from the specified EbmlElement.
MatroskaTagFieldMaker prepareMaking(Diagnostics &diag)
Prepares making.
void make(std::ostream &stream, Diagnostics &diag)
Saves the field to the specified stream (makes a "SimpleTag" element).
MatroskaTagField()
Constructs a new MatroskaTagField.
The TagField class is used by FieldMapBasedTag to store the fields.
void setDefault(bool isDefault)
const std::vector< MatroskaTagField > & nestedFields() const
void setId(const IdentifierType &id)
bool isDefault() const
Returns an indication whether the field is labeled as default.
The TagValue class wraps values of different types.
void assignData(const char *data, std::size_t length, TagDataType type=TagDataType::Binary, TagTextEncoding encoding=TagTextEncoding::Latin1)
void assignPopularity(const Popularity &value)
Assigns the specified popularity value.
std::size_t dataSize() const
Returns the size of the assigned value in bytes.
const Locale & locale() const
Returns the locale.
char * dataPointer()
Returns a pointer to the raw data assigned to the current instance.
constexpr TAG_PARSER_EXPORT std::string_view rating()
Contains all classes and functions of the TagInfo library.
LocaleFormat
The LocaleFormat enum class specifies the format used by a LocaleDetail.
The Popularity class contains a value for ID3v2's "Popularimeter" field.