1 #ifndef TAG_PARSER_GENERICFILEELEMENT_H 2 #define TAG_PARSER_GENERICFILEELEMENT_H 7 #include <c++utilities/conversion/types.h> 8 #include <c++utilities/io/copy.h> 10 #include <initializer_list> 73 ContainerType &container();
74 const ContainerType &container()
const;
75 std::iostream &stream();
76 IoUtilities::BinaryReader &reader();
77 IoUtilities::BinaryWriter &writer();
78 uint64 startOffset()
const;
79 uint64 relativeStartOffset()
const;
81 std::string idToString()
const;
82 uint32 idLength()
const;
83 uint32 headerSize()
const;
85 uint32 sizeLength()
const;
86 uint64 dataOffset()
const;
87 uint64 totalSize()
const;
88 uint64 endOffset()
const;
89 uint64 maxTotalSize()
const;
91 ImplementationType *parent();
92 const ImplementationType *parent()
const;
93 ImplementationType *parent(
byte n);
94 const ImplementationType *parent(
byte n)
const;
95 ImplementationType *nextSibling();
96 const ImplementationType *nextSibling()
const;
97 ImplementationType *firstChild();
98 const ImplementationType *firstChild()
const;
99 ImplementationType *lastChild();
100 const ImplementationType *lastChild()
const;
111 bool isParent()
const;
112 bool isPadding()
const;
113 uint64 firstChildOffset()
const;
114 bool isParsed()
const;
118 void validateSubsequentElementStructure(
Diagnostics &diag, uint64 *paddingSize =
nullptr);
119 static constexpr uint32 maximumIdLengthSupported();
120 static constexpr uint32 maximumSizeLengthSupported();
121 static constexpr
byte minimumElementSize();
126 void discardBuffer();
127 void copyBuffer(std::ostream &targetStream);
129 const std::unique_ptr<char[]> &buffer();
130 ImplementationType *denoteFirstChild(uint32 offset);
147 ContainerType *m_container;
158 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();
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();
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 (uint32 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);
936 copyHelper.callbackCopy(stream, targetStream, bytesToCopy, std::bind(&AbortableProgressFeedback::isAborted, std::ref(progress)),
937 std::bind(&AbortableProgressFeedback::updateStepPercentageFromFraction, std::ref(progress), std::placeholders::_1));
939 copyHelper.copy(stream, targetStream, bytesToCopy);
949 if (relativeFirstChildOffset + minimumElementSize() <= totalSize()) {
950 m_firstChild.reset(
new ImplementationType(static_cast<ImplementationType &>(*
this), startOffset() + relativeFirstChildOffset));
952 m_firstChild.reset();
954 return m_firstChild.get();
997 #endif // TAG_PARSER_GENERICFILEELEMENT_H Defines traits for the specified ImplementationType.
std::unique_ptr< char[]> m_buffer
std::unique_ptr< ImplementationType > m_firstChild
std::unique_ptr< ImplementationType > m_nextSibling
uint64 startOffset() const
Returns the start offset in the related stream.
bool isPadding() const
Returns an indication whether this instance is a padding element.
The GenericFileElement class helps to parse binary files which consist of an arboreal element strucut...
IoUtilities::BinaryReader & reader()
Returns the related BinaryReader.
Contains utility classes helping to read and write streams.
ImplementationType * m_parent
GenericFileElement(ContainerType &container, uint64 startOffset)
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
std::string idToString() const
Returns a printable string representation of the element ID.
IoUtilities::BinaryWriter & writer()
Returns the related BinaryWriter.
typename FileElementTraits< ImplementationType >::ContainerType ContainerType
Specifies the type of the corresponding container.
std::iostream & stream()
Returns the related stream.
typename FileElementTraits< Mp4Atom >::DataSizeType DataSizeType
Specifies the type used to store data sizes.
typename FileElementTraits< Mp4Atom >::IdentifierType IdentifierType
Specifies the type used to store identifiers.
bool isParent() const
Returns an indication whether this instance is a parent element.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
Contains all classes and functions of the TagInfo library.
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
uint64 firstChildOffset() const
Returns the offset of the first child (relative to the start offset of this element).
The Diagnostics class is a container for DiagMessage.