Tag Parser  9.4.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
matroskaattachment.cpp
Go to the documentation of this file.
1 #include "./matroskaattachment.h"
2 #include "./ebmlelement.h"
3 #include "./matroskacontainer.h"
4 #include "./matroskaid.h"
5 
6 #include <c++utilities/conversion/binaryconversion.h>
7 #include <c++utilities/conversion/stringbuilder.h>
8 
9 #include <memory>
10 
11 using namespace std;
12 using namespace CppUtilities;
13 
14 namespace TagParser {
15 
28 void MatroskaAttachment::parse(EbmlElement *attachedFileElement, Diagnostics &diag)
29 {
30  clear();
31  static const string context("parsing \"AttachedFile\"-element");
32  m_attachedFileElement = attachedFileElement;
33  EbmlElement *subElement = attachedFileElement->firstChild();
34  while (subElement) {
35  subElement->parse(diag);
36  switch (subElement->id()) {
38  if (description().empty()) {
39  setDescription(subElement->readString());
40  } else {
41  diag.emplace_back(DiagLevel::Warning, "Multiple \"FileDescription\"-elements found. Surplus elements will be ignored.", context);
42  }
43  break;
45  if (name().empty()) {
46  setName(subElement->readString());
47  } else {
48  diag.emplace_back(DiagLevel::Warning, "Multiple \"FileName\"-elements found. Surplus elements will be ignored.", context);
49  }
50  break;
52  if (mimeType().empty()) {
53  setMimeType(subElement->readString());
54  } else {
55  diag.emplace_back(DiagLevel::Warning, "Multiple \"FileMimeType\"-elements found. Surplus elements will be ignored.", context);
56  }
57  break;
59  if (data()) {
60  diag.emplace_back(DiagLevel::Warning, "Multiple \"FileData\"-elements found. Surplus elements will be ignored.", context);
61  } else {
62  setData(make_unique<StreamDataBlock>(std::bind(&EbmlElement::stream, subElement), subElement->dataOffset(), ios_base::beg,
63  subElement->startOffset() + subElement->totalSize(), ios_base::beg));
64  }
65  break;
67  if (id()) {
68  diag.emplace_back(DiagLevel::Warning, "Multiple \"FileUID\"-elements found. Surplus elements will be ignored.", context);
69  } else {
70  setId(subElement->readUInteger());
71  }
72  break;
76  case EbmlIds::Crc32:
77  case EbmlIds::Void:
78  break;
79  default:
80  diag.emplace_back(DiagLevel::Warning, "Unknown child element \"" % subElement->idToString() + "\" found.", context);
81  }
82  subElement = subElement->nextSibling();
83  }
84 }
85 
93 void MatroskaAttachment::make(std::ostream &stream, Diagnostics &diag)
94 {
95  if (!data() || !data()->size()) {
96  diag.emplace_back(DiagLevel::Critical, "There is no data assigned.", "making Matroska attachment");
97  throw InvalidDataException();
98  }
99  prepareMaking(diag).make(stream, diag);
100 }
101 
113 MatroskaAttachmentMaker::MatroskaAttachmentMaker(MatroskaAttachment &attachment, Diagnostics &diag)
114  : m_attachment(attachment)
115 {
116  m_attachedFileElementSize = 2 + EbmlElement::calculateSizeDenotationLength(attachment.name().size()) + attachment.name().size() + 2
117  + EbmlElement::calculateSizeDenotationLength(attachment.mimeType().size()) + attachment.mimeType().size() + 2 + 1
119  if (auto dataSize = attachment.data() ? attachment.data()->size() : static_cast<istream::pos_type>(0)) {
120  m_attachedFileElementSize += 2 + EbmlElement::calculateSizeDenotationLength(dataSize) + dataSize;
121  }
122  if (!attachment.description().empty()) {
123  m_attachedFileElementSize
124  += 2 + EbmlElement::calculateSizeDenotationLength(attachment.description().size()) + attachment.description().size();
125  }
126  if (attachment.attachedFileElement()) {
127  EbmlElement *child;
128  for (auto id : initializer_list<EbmlElement::IdentifierType>{
130  if ((child = attachment.attachedFileElement()->childById(id, diag))) {
131  m_attachedFileElementSize += child->totalSize();
132  }
133  }
134  }
135  m_totalSize = 2 + EbmlElement::calculateSizeDenotationLength(m_attachedFileElementSize) + m_attachedFileElementSize;
136 }
137 
145 void MatroskaAttachmentMaker::make(ostream &stream, Diagnostics &diag) const
146 {
147  char buff[8];
148  BE::getBytes(static_cast<std::uint16_t>(MatroskaIds::AttachedFile), buff);
149  stream.write(buff, 2);
150  std::uint8_t len = EbmlElement::makeSizeDenotation(m_attachedFileElementSize, buff);
151  stream.write(buff, len);
152  // make elements
154  if (!attachment().description().empty()) {
156  }
159  if (attachment().attachedFileElement()) {
160  EbmlElement *child;
161  for (auto id : initializer_list<EbmlElement::IdentifierType>{
163  if ((child = attachment().attachedFileElement()->childById(id, diag))) {
164  if (child->buffer()) {
165  child->copyBuffer(stream);
166  } else {
167  child->copyEntirely(stream, diag, nullptr);
168  }
169  }
170  }
171  }
172  if (attachment().data() && attachment().data()->size()) {
173  BE::getBytes(static_cast<std::uint16_t>(MatroskaIds::FileData), buff);
174  stream.write(buff, 2);
175  len = EbmlElement::makeSizeDenotation(static_cast<std::uint64_t>(attachment().data()->size()), buff);
176  stream.write(buff, len);
177  attachment().data()->copyTo(stream);
178  }
179 }
180 
182 {
183  EbmlElement *child;
184  if (attachment().attachedFileElement()) {
185  for (auto id : initializer_list<EbmlElement::IdentifierType>{
187  if ((child = attachment().attachedFileElement()->childById(id, diag))) {
188  child->makeBuffer();
189  }
190  }
191  }
192  if (attachment().data() && attachment().data()->size() && !attachment().isDataFromFile()) {
193  attachment().data()->makeBuffer();
194  }
195 }
196 
197 } // namespace TagParser
matroskaattachment.h
TagParser::MatroskaAttachment::attachedFileElement
EbmlElement * attachedFileElement() const
Returns the "AttachedFile"-element which has been specified when the parse() method has been called.
Definition: matroskaattachment.h:69
TagParser::MatroskaIds::FileReferral
@ FileReferral
Definition: matroskaid.h:282
TagParser::EbmlElement::calculateUIntegerLength
static std::uint8_t calculateUIntegerLength(std::uint64_t integer)
Returns the length of the specified unsigned integer in byte.
Definition: ebmlelement.cpp:415
TagParser::StreamDataBlock::makeBuffer
void makeBuffer() const
Buffers the data block.
Definition: abstractattachment.cpp:69
TagParser::MatroskaTagIds::description
constexpr TAG_PARSER_EXPORT const char * description()
Definition: matroskatagid.h:231
TagParser::StreamDataBlock::copyTo
void copyTo(std::ostream &stream) const
Copies the data to the specified stream.
Definition: abstractattachment.cpp:80
TagParser::EbmlElement::calculateSizeDenotationLength
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
Definition: ebmlelement.cpp:288
TagParser::MatroskaAttachmentMaker::bufferCurrentAttachments
void bufferCurrentAttachments(Diagnostics &diag)
Definition: matroskaattachment.cpp:181
TagParser::StreamDataBlock::size
std::istream::pos_type size() const
Returns the size of the data block.
Definition: abstractattachment.h:69
TagParser::AbstractAttachment::name
const std::string & name() const
Returns the (file) name of the attachment.
Definition: abstractattachment.h:167
TagParser::EbmlElement::readUInteger
std::uint64_t readUInteger()
Reads the content of the element as unsigned integer.
Definition: ebmlelement.cpp:238
TagParser::GenericFileElement::makeBuffer
void makeBuffer()
Buffers the element (header and data).
Definition: genericfileelement.h:871
TagParser::GenericFileElement::startOffset
std::uint64_t startOffset() const
Returns the start offset in the related stream.
Definition: genericfileelement.h:261
TagParser::MatroskaIds::FileName
@ FileName
Definition: matroskaid.h:278
TagParser::AbstractAttachment::mimeType
const std::string & mimeType() const
Returns the MIME-type of the attachment.
Definition: abstractattachment.h:183
TagParser::Diagnostics
The Diagnostics class is a container for DiagMessage.
Definition: diagnostics.h:156
TagParser::AbstractAttachment::id
std::uint64_t id() const
Returns the ID of the attachment.
Definition: abstractattachment.h:199
TagParser
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10
TagParser::GenericFileElement::nextSibling
ImplementationType * nextSibling()
Returns the next sibling of the element.
Definition: genericfileelement.h:434
TagParser::MatroskaIds::FileUsedStartTime
@ FileUsedStartTime
Definition: matroskaid.h:283
TagParser::GenericFileElement::id
const IdentifierType & id() const
Returns the element ID.
Definition: genericfileelement.h:278
matroskacontainer.h
TagParser::GenericFileElement::parse
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
Definition: genericfileelement.h:771
TagParser::EbmlElement::makeSimpleElement
static void makeSimpleElement(std::ostream &stream, IdentifierType id, std::uint64_t content)
Makes a simple EBML element.
Definition: ebmlelement.cpp:513
TagParser::MatroskaIds::FileMimeType
@ FileMimeType
Definition: matroskaid.h:279
TagParser::EbmlElement::readString
std::string readString()
Reads the content of the element as string.
Definition: ebmlelement.cpp:226
TagParser::MatroskaIds::FileDescription
@ FileDescription
Definition: matroskaid.h:277
TagParser::MatroskaAttachmentMaker::attachment
const MatroskaAttachment & attachment() const
Returns the associated attachment.
Definition: matroskaattachment.h:31
TagParser::MatroskaAttachmentMaker::make
void make(std::ostream &stream, Diagnostics &diag) const
Saves the attachment (specified when constructing the object) to the specified stream (makes an "Atta...
Definition: matroskaattachment.cpp:145
TagParser::MatroskaAttachment
Implementation of TagParser::AbstractAttachment for the Matroska container.
Definition: matroskaattachment.h:44
TagParser::GenericFileElement::firstChild
ImplementationType * firstChild()
Returns the first child of the element.
Definition: genericfileelement.h:460
matroskaid.h
TagParser::EbmlElement::makeSizeDenotation
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
Definition: ebmlelement.cpp:343
TagParser::EbmlElement
The EbmlElement class helps to parse EBML files such as Matroska files.
Definition: ebmlelement.h:31
TagParser::GenericFileElement::buffer
const std::unique_ptr< char[]> & buffer()
Returns buffered data.
Definition: genericfileelement.h:910
CppUtilities
Definition: abstractcontainer.h:15
TagParser::GenericFileElement::childById
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
Definition: genericfileelement.h:602
TagParser::EbmlElement::idToString
std::string idToString() const
Converts the specified EBML ID to a printable string.
Definition: ebmlelement.h:71
TagParser::GenericFileElement::copyBuffer
void copyBuffer(std::ostream &targetStream)
Copies buffered data to targetStream.
Definition: genericfileelement.h:890
TagParser::AbstractAttachment::description
const std::string & description() const
Returns a description of the attachment.
Definition: abstractattachment.h:151
TagParser::EbmlIds::Void
@ Void
Definition: ebmlid.h:28
TagParser::MatroskaIds::FileUsedEndTime
@ FileUsedEndTime
Definition: matroskaid.h:284
TagParser::InvalidDataException
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
Definition: exceptions.h:25
TagParser::MatroskaIds::FileUID
@ FileUID
Definition: matroskaid.h:281
ebmlelement.h
TagParser::EbmlIds::Crc32
@ Crc32
Definition: ebmlid.h:28
TagParser::MatroskaIds::AttachedFile
@ AttachedFile
Definition: matroskaid.h:271
TagParser::AbstractAttachment::data
const StreamDataBlock * data() const
Returns a reference to the data of the attachment.
Definition: abstractattachment.h:219
TagParser::GenericFileElement::dataOffset
std::uint64_t dataOffset() const
Returns the data offset of the element in the related stream.
Definition: genericfileelement.h:333
TagParser::MatroskaIds::FileData
@ FileData
Definition: matroskaid.h:280
TagParser::GenericFileElement::copyEntirely
void copyEntirely(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the entire element including all children to the specified targetStream.
Definition: genericfileelement.h:862
TagParser::GenericFileElement::totalSize
std::uint64_t totalSize() const
Returns the total size of the element.
Definition: genericfileelement.h:343