Tag Parser
9.2.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
|
Go to the documentation of this file. 1 #ifndef TAG_PARSER_GENERICFILEELEMENT_H
2 #define TAG_PARSER_GENERICFILEELEMENT_H
7 #include <c++utilities/io/copy.h>
10 #include <initializer_list>
74 CppUtilities::BinaryReader &
reader();
75 CppUtilities::BinaryWriter &
writer();
90 const ImplementationType *
parent()
const;
91 ImplementationType *
parent(std::uint8_t n);
92 const ImplementationType *
parent(std::uint8_t n)
const;
157 template <
class ImplementationType>
160 : m_id(IdentifierType())
161 , m_startOffset(startOffset)
166 , m_container(&container)
168 , m_sizeUnknown(false)
170 m_maxSize = container.fileInfo().size();
171 if (m_maxSize > startOffset) {
172 m_maxSize -= startOffset;
173 stream().seekg(startOffset, std::ios_base::beg);
182 template <
class ImplementationType>
185 , m_startOffset(startOffset)
186 , m_maxSize(parent.startOffset() + parent.totalSize() - startOffset)
191 , m_container(&parent.container())
193 , m_sizeUnknown(false)
200 template <
class ImplementationType>
203 : m_id(IdentifierType())
204 , m_startOffset(startOffset)
210 , m_container(&container)
212 , m_sizeUnknown(false)
219 template <
class ImplementationType>
228 template <
class ImplementationType>
239 return m_container->stream();
247 return m_container->reader();
255 return m_container->writer();
263 return m_startOffset;
271 return parent() ? startOffset() - parent()->startOffset() : startOffset();
277 template <
class ImplementationType>
288 return static_cast<ImplementationType *
>(
this)->idToString();
306 return m_idLength + m_sizeLength;
314 template <
class ImplementationType>
335 return startOffset() + headerSize();
345 return headerSize() + dataSize();
353 return startOffset() + totalSize();
373 std::uint8_t level = 0;
374 for (
const ImplementationType *parent = m_parent; parent; ++level, parent = parent->m_parent)
409 ImplementationType *parent =
static_cast<ImplementationType *
>(
this);
410 for (; n && parent; --n, parent = parent->m_parent)
436 return m_nextSibling.get();
449 return m_nextSibling.get();
462 return m_firstChild.get();
475 return m_firstChild.get();
488 for (ImplementationType *child = firstChild(); child; child = child->nextSibling()) {
489 if (!child->m_nextSibling) {
518 template <
class ImplementationType>
525 return static_cast<ImplementationType *
>(
this);
529 return nextSibling()->subelementByPath(diag, item);
543 template <
class ImplementationType>
553 return firstChild()->subelementByPath(diag, remainingPath);
557 return nextSibling()->subelementByPath(diag, item, remainingPath);
571 template <
class ImplementationType>
586 template <
class ImplementationType>
605 for (ImplementationType *child = firstChild(); child; child = child->nextSibling()) {
607 if (child->id() ==
id) {
623 template <
class ImplementationType>
639 template <
class ImplementationType>
643 for (ImplementationType *sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
644 sibling->parse(diag);
645 if (sibling->id() ==
id) {
662 template <
class ImplementationType>
678 template <
class ImplementationType>
682 for (ImplementationType *sibling =
static_cast<ImplementationType *
>(
this); sibling; sibling = sibling->nextSibling()) {
683 sibling->parse(diag);
684 if (sibling->id() ==
id) {
701 template <
class ImplementationType>
712 return static_cast<const ImplementationType *
>(
this)->isParent();
720 return static_cast<const ImplementationType *
>(
this)->isPadding();
728 return static_cast<const ImplementationType *
>(
this)->firstChildOffset();
752 m_nextSibling =
nullptr;
753 m_firstChild =
nullptr;
774 static_cast<ImplementationType *
>(
this)->internalParse(diag);
798 static_cast<ImplementationType *
>(
this)->parse(diag);
814 template <
class ImplementationType>
822 firstChild()->validateSubsequentElementStructure(diag, paddingSize);
827 }
else if (paddingSize && isPadding()) {
828 *paddingSize += totalSize();
832 nextSibling()->validateSubsequentElementStructure(diag, paddingSize);
839 template <
class ImplementationType>
842 copyInternal(targetStream, startOffset(), headerSize(), diag, progress);
848 template <
class ImplementationType>
851 if (std::uint32_t firstChildOffset = this->firstChildOffset()) {
852 copyInternal(targetStream, startOffset(), firstChildOffset, diag, progress);
854 copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
861 template <
class ImplementationType>
864 copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
873 m_buffer = std::make_unique<char[]>(totalSize());
874 container().stream().seekg(startOffset());
875 container().stream().read(m_buffer.get(), totalSize());
892 targetStream.write(m_buffer.get(), totalSize());
899 template <
class ImplementationType>
903 m_buffer ? copyBuffer(targetStream) : copyEntirely(targetStream, diag, progress);
922 template <
class ImplementationType>
929 }
catch (
const Failure &) {
930 throw InvalidDataException();
932 auto &stream = container().stream();
933 stream.seekg(startOffset);
939 copyHelper.copy(stream, targetStream, bytesToCopy);
947 template <
class ImplementationType>
950 if (relativeFirstChildOffset + minimumElementSize() <= totalSize()) {
951 m_firstChild.reset(
new ImplementationType(
static_cast<ImplementationType &
>(*
this), startOffset() + relativeFirstChildOffset));
953 m_firstChild.reset();
955 return m_firstChild.get();
998 #endif // TAG_PARSER_GENERICFILEELEMENT_H
bool isParsed() const
Returns an indication whether this instance has been parsed yet.
void discardBuffer()
Discards buffered data.
void copyHeader(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the header informaton of the element to the specified targetStream.
ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item)
Returns the sub element for the specified path.
const ImplementationType * childById(const IdentifierType &id, Diagnostics &diag) const
Returns the first child with the specified id.
std::unique_ptr< ImplementationType > m_nextSibling
GenericFileElement(ContainerType &container, std::uint64_t startOffset, std::uint64_t maxSize)
CppUtilities::BinaryReader & reader()
Returns the related BinaryReader.
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks....
std::uint32_t m_sizeLength
GenericFileElement(GenericFileElement &other)=delete
std::iostream & stream()
Returns the related stream.
std::uint32_t sizeLength() const
Returns the length of the size denotation of the element in byte.
std::uint32_t idLength() const
Returns the length of the id denotation in byte.
bool isAborted() const
Returns whether the operation has been aborted via tryToAbort().
void makeBuffer()
Buffers the element (header and data).
std::uint64_t startOffset() const
Returns the start offset in the related stream.
void updateStepPercentageFromFraction(double stepPercentage)
Updates the current step percentage and invokes the second callback specified on construction (or the...
const ImplementationType * firstChild() const
Returns the first child of the element.
Defines traits for the specified ImplementationType.
The Diagnostics class is a container for DiagMessage.
typename FileElementTraits< Mpeg4Descriptor >::IdentifierType IdentifierType
Specifies the type used to store identifiers.
Contains all classes and functions of the TagInfo library.
ImplementationType * nextSibling()
Returns the next sibling of the element.
const IdentifierType & id() const
Returns the element ID.
bool isParent() const
Returns an indication whether this instance is a parent element.
static constexpr std::uint8_t minimumElementSize()
Returns the mimimum element size.
void clear()
Clears the status 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...
const ImplementationType * siblingByIdIncludingThis(const IdentifierType &id, Diagnostics &diag) const
Returns the first sibling with the specified id or the current instance if its ID equals id.
DataSizeType dataSize() const
Returns the data size of the element in byte.
std::uint64_t relativeStartOffset() const
Returns the offset of the element in its parent or - if it is a top-level element - in the related st...
ImplementationType * firstChild()
Returns the first child of the element.
The GenericFileElement class helps to parse binary files which consist of an arboreal element strucut...
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
std::uint64_t endOffset() const
Returns the offset of the first byte which doesn't belong to this element anymore.
const std::unique_ptr< char[]> & buffer()
Returns buffered data.
ImplementationType * parent(std::uint8_t n)
Returns the n-th parent of the element.
static constexpr std::uint32_t maximumIdLengthSupported()
Returns the maximum id length supported by the class in byte.
typename FileElementTraits< Mpeg4Descriptor >::DataSizeType DataSizeType
Specifies the type used to store data sizes.
ImplementationType * denoteFirstChild(std::uint32_t offset)
Denotes the first child to start at the specified offset (relative to the start offset of this descri...
std::unique_ptr< char[]> m_buffer
void validateSubsequentElementStructure(Diagnostics &diag, std::uint64_t *paddingSize=nullptr)
Parses (see parse()) this and all subsequent elements.
std::string idToString() const
Returns a printable string representation of the element ID.
ImplementationType * m_parent
GenericFileElement(ContainerType &container, std::uint64_t startOffset)
const ImplementationType * siblingById(const IdentifierType &id, Diagnostics &diag) const
Returns the first sibling with the specified id.
std::uint32_t headerSize() const
Returns the header size of the element in byte.
void reparse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
void copyBuffer(std::ostream &targetStream)
Copies buffered data to targetStream.
std::uint8_t level() const
Returns how deep the element is nested (0 for top-level elements, 1 for children of top-level element...
ImplementationType * lastChild()
Returns the last child of the element.
const ImplementationType * lastChild() const
Returns the last child of the element.
const ImplementationType * parent(std::uint8_t n) const
Returns the n-th parent of the element.
const ContainerType & container() const
Returns the related container.
std::uint64_t firstChildOffset() const
Returns the offset of the first child (relative to the start offset of this element).
ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...)
Returns the sub element for the specified path.
ImplementationType * siblingById(const IdentifierType &id, Diagnostics &diag)
Returns the first sibling with the specified id.
const ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...) const
Returns the sub element for the specified path.
typename FileElementTraits< Mpeg4Descriptor >::ContainerType ContainerType
Specifies the type of the corresponding container.
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
static constexpr std::uint32_t maximumSizeLengthSupported()
Returns the maximum size length supported by the class in byte.
bool isPadding() const
Returns an indication whether this instance is a padding element.
GenericFileElement(const GenericFileElement &other)=delete
ContainerType & container()
Returns the related container.
std::uint64_t dataOffset() const
Returns the data offset of the element in the related stream.
std::uint64_t m_startOffset
std::unique_ptr< ImplementationType > m_firstChild
CppUtilities::BinaryWriter & writer()
Returns the related BinaryWriter.
void copyWithoutChilds(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the element without its children to the specified targetStream.
const ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item) const
Returns the sub element for the specified path.
const ImplementationType * parent() const
Returns the parent of the element.
ImplementationType * siblingByIdIncludingThis(const IdentifierType &id, Diagnostics &diag)
Returns the first sibling with the specified id or the current instance if its ID equals id.
GenericFileElement & operator=(const GenericFileElement &other)=delete
GenericFileElement(ImplementationType &parent, std::uint64_t startOffset)
Constructs a new sub level file element with the specified parent at the specified startOffset.
ImplementationType * parent()
Returns the parent of the element.
std::uint64_t maxTotalSize() const
Returns maximum total size.
void copyEntirely(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the entire element including all children to the specified targetStream.
const ImplementationType * nextSibling() const
Returns the next sibling of the element.
std::uint64_t totalSize() const
Returns the total size of the element.
void copyPreferablyFromBuffer(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Copies buffered data to targetStream if data has been buffered; copies from input stream otherwise.