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)
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>
826 firstChild()->validateSubsequentElementStructure(diag, paddingSize, progress);
831 }
else if (paddingSize && isPadding()) {
832 *paddingSize += totalSize();
836 nextSibling()->validateSubsequentElementStructure(diag, paddingSize, progress);
843 template <
class ImplementationType>
846 copyInternal(targetStream, startOffset(), headerSize(), diag, progress);
852 template <
class ImplementationType>
855 if (std::uint32_t firstChildOffset = this->firstChildOffset()) {
856 copyInternal(targetStream, startOffset(), firstChildOffset, diag, progress);
858 copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
865 template <
class ImplementationType>
868 copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
877 m_buffer = std::make_unique<char[]>(totalSize());
878 container().stream().seekg(
static_cast<std::streamoff
>(startOffset()));
879 container().stream().read(m_buffer.get(),
static_cast<std::streamsize
>(totalSize()));
896 targetStream.write(m_buffer.get(),
static_cast<std::streamsize
>(totalSize()));
903 template <
class ImplementationType>
907 m_buffer ? copyBuffer(targetStream) : copyEntirely(targetStream, diag, progress);
926 template <
class ImplementationType>
933 }
catch (
const Failure &) {
934 throw InvalidDataException();
936 auto &stream = container().stream();
937 stream.seekg(
static_cast<std::streamoff
>(startOffset), std::ios_base::beg);
943 copyHelper.copy(stream, targetStream, bytesToCopy);
951 template <
class ImplementationType>
954 if (relativeFirstChildOffset + minimumElementSize() <= totalSize()) {
955 m_firstChild.reset(
new ImplementationType(
static_cast<ImplementationType &
>(*
this), startOffset() + relativeFirstChildOffset));
957 m_firstChild.reset();
959 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 strucut...
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.
const ContainerType & container() const
Returns the related container.
std::uint64_t startOffset() const
Returns the start offset in the related stream.
std::string idToString() const
Returns a printable string representation of the element ID.
void copyPreferablyFromBuffer(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Copies buffered data to targetStream if data has been buffered; copies from input stream otherwise.
const ImplementationType * nextSibling() const
Returns the next sibling of the element.
void discardBuffer()
Discards buffered data.
GenericFileElement & operator=(const GenericFileElement &other)=delete
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.
void copyEntirely(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the entire element including all children to the specified targetStream.
const std::unique_ptr< char[]> & buffer()
Returns buffered data.
const ImplementationType * firstChild() const
Returns the first child of the element.
void copyWithoutChilds(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the element without its children to the specified targetStream.
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.
void copyHeader(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
Writes the header informaton of the element to the specified targetStream.
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.
const ImplementationType * subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...) const
Returns the sub element for the specified path.
void copyBuffer(std::ostream &targetStream)
Copies buffered data to targetStream.
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 mimimum 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
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
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
Contains all classes and functions of the TagInfo library.