1#ifndef TAG_PARSER_GENERICFILEELEMENT_H
2#define TAG_PARSER_GENERICFILEELEMENT_H
7#include <c++utilities/io/copy.h>
10#include <initializer_list>
73 CppUtilities::BinaryReader &
reader();
74 CppUtilities::BinaryWriter &
writer();
89 const ImplementationType *
parent()
const;
90 ImplementationType *
parent(std::uint8_t n);
91 const ImplementationType *
parent(std::uint8_t n)
const;
119 template <
typename TargetStream = std::ostream>
121 template <
typename TargetStream = std::ostream>
123 template <
typename TargetStream = std::ostream>
127 template <
typename TargetStream = std::ostream>
void copyBuffer(TargetStream &targetStream);
128 template <
typename TargetStream = std::ostream>
146 template <
typename TargetStream = std::ostream>
161template <
class ImplementationType>
164 : m_id(IdentifierType())
165 , m_startOffset(startOffset)
170 , m_container(&container)
172 , m_sizeUnknown(false)
186template <
class ImplementationType>
189 , m_startOffset(startOffset)
190 , m_maxSize(parent.startOffset() + parent.totalSize() - startOffset)
195 , m_container(&parent.container())
197 , m_sizeUnknown(false)
204template <
class ImplementationType>
207 : m_id(IdentifierType())
208 , m_startOffset(startOffset)
214 , m_container(&container)
216 , m_sizeUnknown(false)
223template <
class ImplementationType>
232template <
class ImplementationType>
243 return m_container->stream();
251 return m_container->reader();
259 return m_container->writer();
267 return m_startOffset;
275 return parent() ? startOffset() - parent()->startOffset() : startOffset();
281template <
class ImplementationType>
292 return static_cast<ImplementationType *
>(
this)->idToString();
310 return m_idLength + m_sizeLength;
318template <
class ImplementationType>
339 return startOffset() + headerSize();
349 return headerSize() + dataSize();
357 return startOffset() + totalSize();
377 std::uint8_t level = 0;
378 for (
const ImplementationType *parent = m_parent; parent; ++level, parent = parent->m_parent)
413 ImplementationType *parent =
static_cast<ImplementationType *
>(
this);
414 for (; n && parent; --n, parent = parent->m_parent)
440 return m_nextSibling.get();
453 return m_nextSibling.get();
466 return m_firstChild.get();
479 return m_firstChild.get();
492 for (ImplementationType *child = firstChild(); child; child = child->nextSibling()) {
493 if (!child->m_nextSibling) {
522template <
class ImplementationType>
529 return static_cast<ImplementationType *
>(
this);
533 return nextSibling()->subelementByPath(diag, item);
547template <
class ImplementationType>
557 return firstChild()->subelementByPath(diag, remainingPath);
561 return nextSibling()->subelementByPath(diag, item, remainingPath);
575template <
class ImplementationType>
590template <
class ImplementationType>
609 for (ImplementationType *child = firstChild(); child; child = child->nextSibling()) {
611 if (child->id() ==
id) {
627template <
class ImplementationType>
643template <
class ImplementationType>
647 for (ImplementationType *sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
648 sibling->parse(diag);
649 if (sibling->id() ==
id) {
666template <
class ImplementationType>
682template <
class ImplementationType>
686 for (ImplementationType *sibling =
static_cast<ImplementationType *
>(
this); sibling; sibling = sibling->nextSibling()) {
687 sibling->parse(diag);
688 if (sibling->id() ==
id) {
705template <
class ImplementationType>
716 return static_cast<const ImplementationType *
>(
this)->isParent();
724 return static_cast<const ImplementationType *
>(
this)->isPadding();
732 return static_cast<const ImplementationType *
>(
this)->firstChildOffset();
756 m_nextSibling =
nullptr;
757 m_firstChild =
nullptr;
778 static_cast<ImplementationType *
>(
this)->internalParse(diag);
802 static_cast<ImplementationType *
>(
this)->parse(diag);
818template <
class ImplementationType>
830 firstChild()->validateSubsequentElementStructure(diag, paddingSize, progress);
835 }
else if (paddingSize && isPadding()) {
836 *paddingSize += totalSize();
840 nextSibling()->validateSubsequentElementStructure(diag, paddingSize, progress);
847template <
class ImplementationType>
848template <
typename TargetStream>
851 copyInternal(targetStream, startOffset(), headerSize(), diag, progress);
857template <
class ImplementationType>
858template <
typename TargetStream>
861 if (std::uint32_t firstChildOffset = this->firstChildOffset()) {
862 copyInternal(targetStream, startOffset(), firstChildOffset, diag, progress);
864 copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
871template <
class ImplementationType>
872template <
typename TargetStream>
875 copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
884 m_buffer = std::make_unique<char[]>(totalSize());
885 container().stream().seekg(
static_cast<std::streamoff
>(startOffset()));
886 container().stream().read(m_buffer.get(),
static_cast<std::streamsize
>(totalSize()));
901template <
class ImplementationType>
902template <
typename TargetStream>
905 targetStream.write(m_buffer.get(),
static_cast<std::streamsize
>(totalSize()));
912template <
class ImplementationType>
913template <
typename TargetStream>
917 m_buffer ? copyBuffer(targetStream) : copyEntirely(targetStream, diag, progress);
936template <
class ImplementationType>
937template <
typename TargetStream>
944 }
catch (
const Failure &) {
945 throw InvalidDataException();
947 auto &stream = container().stream();
948 stream.seekg(
static_cast<std::streamoff
>(startOffset), std::ios_base::beg);
949 CppUtilities::CopyHelper<0x10000> copyHelper;
954 copyHelper.copy(stream, targetStream, bytesToCopy);
962template <
class ImplementationType>
965 if (relativeFirstChildOffset + minimumElementSize() <= totalSize()) {
966 m_firstChild.reset(
new ImplementationType(
static_cast<ImplementationType &
>(*
this), startOffset() + relativeFirstChildOffset));
968 m_firstChild.reset();
970 return m_firstChild.get();
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
bool isAborted() const
Returns whether the operation has been aborted via tryToAbort().
void stopIfAborted() const
Throws an OperationAbortedException if aborted.
void updateStepPercentageFromFraction(double stepPercentage)
Updates the current step percentage and invokes the second callback specified on construction (or the...
The Diagnostics class is a container for DiagMessage.
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
Defines traits for the specified ImplementationType.
The GenericFileElement class helps to parse binary files which consist of an arboreal element structu...
GenericFileElement(ContainerType &container, std::uint64_t startOffset)
const ImplementationType * parent(std::uint8_t n) const
Returns the n-th parent of the element.
ImplementationType * lastChild()
Returns the last child of the element.
void copyEntirely(TargetStream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the entire element including all children to the specified targetStream.
void copyBuffer(TargetStream &targetStream)
Copies buffered data to targetStream.
const ContainerType & container() const
Returns the related container.
std::uint64_t startOffset() const
Returns the start offset in the related stream.
void copyHeader(TargetStream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the header information of the element to the specified targetStream.
std::string idToString() const
Returns a printable string representation of the element ID.
const ImplementationType * nextSibling() const
Returns the next sibling of the element.
void discardBuffer()
Discards buffered data.
GenericFileElement(ContainerType &container, std::uint64_t startOffset, std::uint64_t maxSize)
ImplementationType * siblingByIdIncludingThis(const IdentifierType &id, Diagnostics &diag)
Returns the first sibling with the specified id or the current instance if its ID equals id.
const std::unique_ptr< char[]> & buffer()
Returns buffered data.
const ImplementationType * firstChild() const
Returns the first child of the element.
std::uint32_t headerSize() const
Returns the header size of the element in byte.
const ImplementationType * childById(const IdentifierType &id, Diagnostics &diag) const
Returns the first child with the specified id.
bool isParent() const
Returns an indication whether this instance is a parent element.
std::uint64_t endOffset() const
Returns the offset of the first byte which doesn't belong to this element anymore.
bool isPadding() const
Returns an indication whether this instance is a padding element.
const IdentifierType & id() const
Returns the element ID.
CppUtilities::BinaryWriter & writer()
Returns the related BinaryWriter.
typename FileElementTraits< ImplementationType >::DataSizeType DataSizeType
Specifies the type used to store data sizes.
std::uint8_t level() const
Returns how deep the element is nested (0 for top-level elements, 1 for children of top-level element...
typename FileElementTraits< ImplementationType >::ContainerType ContainerType
Specifies the type of the corresponding container.
ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...)
Returns the sub element for the specified path.
std::iostream & stream()
Returns the related stream.
const ImplementationType * siblingById(const IdentifierType &id, Diagnostics &diag) const
Returns the first sibling with the specified id.
GenericFileElement & operator=(const GenericFileElement &other)=delete
const ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...) const
Returns the sub element for the specified path.
ImplementationType * childById(const IdentifierType &id, Diagnostics &diag)
Returns the first child with the specified id.
std::uint64_t firstChildOffset() const
Returns the offset of the first child (relative to the start offset of this element).
bool isParsed() const
Returns an indication whether this instance has been parsed yet.
ImplementationType * nextSibling()
Returns the next sibling of the element.
std::unique_ptr< ImplementationType > m_nextSibling
GenericFileElement(GenericFileElement &other)=delete
ImplementationType * parent()
Returns the parent of the element.
static constexpr std::uint8_t minimumElementSize()
Returns the minimum element size.
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::uint64_t m_startOffset
void copyWithoutChilds(TargetStream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the element without its children to the specified targetStream.
ImplementationType * firstChild()
Returns the first child of the element.
std::uint32_t sizeLength() const
Returns the length of the size denotation of the element in byte.
std::unique_ptr< ImplementationType > m_firstChild
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.
const ImplementationType * lastChild() const
Returns the last child of the element.
ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item)
Returns the sub element for the specified path.
static constexpr std::uint32_t maximumIdLengthSupported()
Returns the maximum id length supported by the class in byte.
DataSizeType dataSize() const
Returns the data size of the element in byte.
std::uint64_t totalSize() const
Returns the total size of the element.
const ImplementationType * parent() const
Returns the parent of the element.
const ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item) const
Returns the sub element for the specified path.
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
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...
void validateSubsequentElementStructure(Diagnostics &diag, std::uint64_t *paddingSize=nullptr, AbortableProgressFeedback *progress=nullptr)
Parses (see parse()) this and all subsequent elements.
typename FileElementTraits< ImplementationType >::IdentifierType IdentifierType
Specifies the type used to store identifiers.
static constexpr std::uint32_t maximumSizeLengthSupported()
Returns the maximum size length supported by the class in byte.
ImplementationType * m_parent
std::uint64_t dataOffset() const
Returns the data offset of the element in the related stream.
GenericFileElement(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.
ContainerType & container()
Returns the related container.
ImplementationType * parent(std::uint8_t n)
Returns the n-th parent of the element.
void clear()
Clears the status of the element.
std::uint32_t idLength() const
Returns the length of the id denotation in byte.
std::unique_ptr< char[]> m_buffer
CppUtilities::BinaryReader & reader()
Returns the related BinaryReader.
std::uint64_t maxTotalSize() const
Returns maximum total size.
void makeBuffer()
Buffers the element (header and data).
void reparse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
ImplementationType * siblingById(const IdentifierType &id, Diagnostics &diag)
Returns the first sibling with the specified id.
std::uint32_t m_sizeLength
void copyPreferablyFromBuffer(TargetStream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Copies buffered data to targetStream if data has been buffered; copies from input stream otherwise.
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
Contains all classes and functions of the TagInfo library.