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();
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 (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
FileElementTraits< ImplementationType >::ContainerType ContainerType
Specifies the type of the corresponding container.
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.
IoUtilities::BinaryReader & reader()
Returns the related BinaryReader.
Contains utility classes helping to read and write streams.
ImplementationType * m_parent
GenericFileElement(ContainerType &container, uint64 startOffset)
IoUtilities::BinaryWriter & writer()
Returns the related BinaryWriter.
std::iostream & stream()
Returns the related stream.
FileElementTraits< ImplementationType >::IdentifierType IdentifierType
Specifies the type used to store identifiers.
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
FileElementTraits< ImplementationType >::DataSizeType DataSizeType
Specifies the type used to store data sizes.