Tag Parser  10.0.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
genericfileelement.h
Go to the documentation of this file.
1 #ifndef TAG_PARSER_GENERICFILEELEMENT_H
2 #define TAG_PARSER_GENERICFILEELEMENT_H
3 
4 #include "./exceptions.h"
5 #include "./progressfeedback.h"
6 
7 #include <c++utilities/io/copy.h>
8 
9 #include <cstdint>
10 #include <initializer_list>
11 #include <iostream>
12 #include <list>
13 #include <memory>
14 #include <string>
15 
16 namespace CppUtilities {
17 class BinaryReader;
18 class BinaryWriter;
19 } // namespace CppUtilities
20 
21 namespace TagParser {
22 
23 class Diagnostics;
24 
34 template <typename ImplementationType> class FileElementTraits {
35 };
36 
45 template <class ImplementationType> class TAG_PARSER_EXPORT GenericFileElement {
46  friend class FileElementTraits<ImplementationType>;
47 
48 public:
53 
58 
63 
64  GenericFileElement(ContainerType &container, std::uint64_t startOffset);
65  GenericFileElement(ImplementationType &parent, std::uint64_t startOffset);
66  GenericFileElement(ContainerType &container, std::uint64_t startOffset, std::uint64_t maxSize);
67  GenericFileElement(const GenericFileElement &other) = delete;
70 
72  const ContainerType &container() const;
73  std::iostream &stream();
74  CppUtilities::BinaryReader &reader();
75  CppUtilities::BinaryWriter &writer();
76  std::uint64_t startOffset() const;
77  std::uint64_t relativeStartOffset() const;
78  const IdentifierType &id() const;
79  std::string idToString() const;
80  std::uint32_t idLength() const;
81  std::uint32_t headerSize() const;
83  std::uint32_t sizeLength() const;
84  std::uint64_t dataOffset() const;
85  std::uint64_t totalSize() const;
86  std::uint64_t endOffset() const;
87  std::uint64_t maxTotalSize() const;
88  std::uint8_t level() const;
89  ImplementationType *parent();
90  const ImplementationType *parent() const;
91  ImplementationType *parent(std::uint8_t n);
92  const ImplementationType *parent(std::uint8_t n) const;
93  ImplementationType *nextSibling();
94  const ImplementationType *nextSibling() const;
95  ImplementationType *firstChild();
96  const ImplementationType *firstChild() const;
97  ImplementationType *lastChild();
98  const ImplementationType *lastChild() const;
99  ImplementationType *subelementByPath(Diagnostics &diag, IdentifierType item);
100  ImplementationType *subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...);
101  const ImplementationType *subelementByPath(Diagnostics &diag, IdentifierType item) const;
102  const ImplementationType *subelementByPath(Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...) const;
103  ImplementationType *childById(const IdentifierType &id, Diagnostics &diag);
104  const ImplementationType *childById(const IdentifierType &id, Diagnostics &diag) const;
105  ImplementationType *siblingById(const IdentifierType &id, Diagnostics &diag);
106  const ImplementationType *siblingById(const IdentifierType &id, Diagnostics &diag) const;
107  ImplementationType *siblingByIdIncludingThis(const IdentifierType &id, Diagnostics &diag);
108  const ImplementationType *siblingByIdIncludingThis(const IdentifierType &id, Diagnostics &diag) const;
109  bool isParent() const;
110  bool isPadding() const;
111  std::uint64_t firstChildOffset() const;
112  bool isParsed() const;
113  void clear();
114  void parse(Diagnostics &diag);
115  void reparse(Diagnostics &diag);
116  void validateSubsequentElementStructure(Diagnostics &diag, std::uint64_t *paddingSize = nullptr, AbortableProgressFeedback *progress = nullptr);
117  static constexpr std::uint32_t maximumIdLengthSupported();
118  static constexpr std::uint32_t maximumSizeLengthSupported();
119  static constexpr std::uint8_t minimumElementSize();
120  void copyHeader(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress);
121  void copyWithoutChilds(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress);
122  void copyEntirely(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress);
123  void makeBuffer();
125  void copyBuffer(std::ostream &targetStream);
126  void copyPreferablyFromBuffer(std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress);
127  const std::unique_ptr<char[]> &buffer();
128  ImplementationType *denoteFirstChild(std::uint32_t offset);
129 
130 protected:
132  std::uint64_t m_startOffset;
133  std::uint64_t m_maxSize;
135  std::uint32_t m_idLength;
136  std::uint32_t m_sizeLength;
137  ImplementationType *m_parent;
138  std::unique_ptr<ImplementationType> m_nextSibling;
139  std::unique_ptr<ImplementationType> m_firstChild;
140  std::unique_ptr<char[]> m_buffer;
141 
142 private:
143  void copyInternal(
144  std::ostream &targetStream, std::uint64_t startOffset, std::uint64_t bytesToCopy, Diagnostics &diag, AbortableProgressFeedback *progress);
145 
146  ContainerType *m_container;
147  bool m_parsed;
148 
149 protected:
151 };
152 
157 template <class ImplementationType>
159  GenericFileElement<ImplementationType>::ContainerType &container, std::uint64_t startOffset)
160  : m_id(IdentifierType())
161  , m_startOffset(startOffset)
162  , m_dataSize(0)
163  , m_idLength(0)
164  , m_sizeLength(0)
165  , m_parent(nullptr)
166  , m_container(&container)
167  , m_parsed(false)
168  , m_sizeUnknown(false)
169 {
170  m_maxSize = container.fileInfo().size();
171  if (m_maxSize > startOffset) {
173  stream().seekg(static_cast<std::streamoff>(startOffset), std::ios_base::beg);
174  } else {
175  m_maxSize = 0;
176  }
177 }
178 
182 template <class ImplementationType>
183 GenericFileElement<ImplementationType>::GenericFileElement(ImplementationType &parent, std::uint64_t startOffset)
184  : m_id(IdentifierType())
185  , m_startOffset(startOffset)
186  , m_maxSize(parent.startOffset() + parent.totalSize() - startOffset)
187  , m_dataSize(0)
188  , m_idLength(0)
189  , m_sizeLength(0)
190  , m_parent(&parent)
191  , m_container(&parent.container())
192  , m_parsed(false)
193  , m_sizeUnknown(false)
194 {
195 }
196 
200 template <class ImplementationType>
202  GenericFileElement<ImplementationType>::ContainerType &container, std::uint64_t startOffset, std::uint64_t maxSize)
203  : m_id(IdentifierType())
204  , m_startOffset(startOffset)
205  , m_maxSize(maxSize)
206  , m_dataSize(0)
207  , m_idLength(0)
208  , m_sizeLength(0)
209  , m_parent(nullptr)
210  , m_container(&container)
211  , m_parsed(false)
212  , m_sizeUnknown(false)
213 {
214 }
215 
219 template <class ImplementationType>
221 {
222  return *m_container;
223 }
224 
228 template <class ImplementationType>
230 {
231  return *m_container;
232 }
233 
237 template <class ImplementationType> inline std::iostream &GenericFileElement<ImplementationType>::stream()
238 {
239  return m_container->stream();
240 }
241 
245 template <class ImplementationType> inline CppUtilities::BinaryReader &GenericFileElement<ImplementationType>::reader()
246 {
247  return m_container->reader();
248 }
249 
253 template <class ImplementationType> inline CppUtilities::BinaryWriter &GenericFileElement<ImplementationType>::writer()
254 {
255  return m_container->writer();
256 }
257 
261 template <class ImplementationType> inline std::uint64_t GenericFileElement<ImplementationType>::startOffset() const
262 {
263  return m_startOffset;
264 }
265 
269 template <class ImplementationType> inline std::uint64_t GenericFileElement<ImplementationType>::relativeStartOffset() const
270 {
271  return parent() ? startOffset() - parent()->startOffset() : startOffset();
272 }
273 
277 template <class ImplementationType>
279 {
280  return m_id;
281 }
282 
286 template <class ImplementationType> inline std::string GenericFileElement<ImplementationType>::idToString() const
287 {
288  return static_cast<ImplementationType *>(this)->idToString();
289 }
290 
294 template <class ImplementationType> inline std::uint32_t GenericFileElement<ImplementationType>::idLength() const
295 {
296  return m_idLength;
297 }
298 
304 template <class ImplementationType> inline std::uint32_t GenericFileElement<ImplementationType>::headerSize() const
305 {
306  return m_idLength + m_sizeLength;
307 }
308 
314 template <class ImplementationType>
316 {
317  return m_dataSize;
318 }
319 
323 template <class ImplementationType> inline std::uint32_t GenericFileElement<ImplementationType>::sizeLength() const
324 {
325  return m_sizeLength;
326 }
327 
333 template <class ImplementationType> inline std::uint64_t GenericFileElement<ImplementationType>::dataOffset() const
334 {
335  return startOffset() + headerSize();
336 }
337 
343 template <class ImplementationType> inline std::uint64_t GenericFileElement<ImplementationType>::totalSize() const
344 {
345  return headerSize() + dataSize();
346 }
347 
351 template <class ImplementationType> inline std::uint64_t GenericFileElement<ImplementationType>::endOffset() const
352 {
353  return startOffset() + totalSize();
354 }
355 
362 template <class ImplementationType> inline std::uint64_t GenericFileElement<ImplementationType>::maxTotalSize() const
363 {
364  return m_maxSize;
365 }
366 
371 template <class ImplementationType> std::uint8_t GenericFileElement<ImplementationType>::level() const
372 {
373  std::uint8_t level = 0;
374  for (const ImplementationType *parent = m_parent; parent; ++level, parent = parent->m_parent)
375  ;
376  return level;
377 }
378 
385 template <class ImplementationType> inline ImplementationType *GenericFileElement<ImplementationType>::parent()
386 {
387  return m_parent;
388 }
389 
396 template <class ImplementationType> inline const ImplementationType *GenericFileElement<ImplementationType>::parent() const
397 {
398  return m_parent;
399 }
400 
407 template <class ImplementationType> ImplementationType *GenericFileElement<ImplementationType>::parent(std::uint8_t n)
408 {
409  ImplementationType *parent = static_cast<ImplementationType *>(this);
410  for (; n && parent; --n, parent = parent->m_parent)
411  ;
412  return parent;
413 }
414 
421 template <class ImplementationType> inline const ImplementationType *GenericFileElement<ImplementationType>::parent(std::uint8_t n) const
422 {
423  return const_cast<GenericFileElement<ImplementationType> *>(this)->parent(n);
424 }
425 
434 template <class ImplementationType> inline ImplementationType *GenericFileElement<ImplementationType>::nextSibling()
435 {
436  return m_nextSibling.get();
437 }
438 
447 template <class ImplementationType> inline const ImplementationType *GenericFileElement<ImplementationType>::nextSibling() const
448 {
449  return m_nextSibling.get();
450 }
451 
460 template <class ImplementationType> inline ImplementationType *GenericFileElement<ImplementationType>::firstChild()
461 {
462  return m_firstChild.get();
463 }
464 
473 template <class ImplementationType> inline const ImplementationType *GenericFileElement<ImplementationType>::firstChild() const
474 {
475  return m_firstChild.get();
476 }
477 
486 template <class ImplementationType> inline ImplementationType *GenericFileElement<ImplementationType>::lastChild()
487 {
488  for (ImplementationType *child = firstChild(); child; child = child->nextSibling()) {
489  if (!child->m_nextSibling) {
490  return child;
491  }
492  }
493  return nullptr;
494 }
495 
504 template <class ImplementationType> inline const ImplementationType *GenericFileElement<ImplementationType>::lastChild() const
505 {
506  return const_cast<GenericFileElement<ImplementationType> *>(this)->lastChild();
507 }
508 
518 template <class ImplementationType>
520 {
521  // ensure element is parsed
522  parse(diag);
523  // return the element if it matches the current and last item in the path
524  if (item == id()) {
525  return static_cast<ImplementationType *>(this);
526  }
527  // check whether a sibling matches the item
528  if (nextSibling()) {
529  return nextSibling()->subelementByPath(diag, item);
530  }
531  return nullptr;
532 }
533 
543 template <class ImplementationType>
545 {
546  // ensure element is parsed
547  parse(diag);
548  // continue with next item in path if the element matches the current item
549  if (item == id()) {
550  if (!firstChild()) {
551  return nullptr;
552  }
553  return firstChild()->subelementByPath(diag, remainingPath);
554  }
555  // check whether a sibling matches the current item
556  if (nextSibling()) {
557  return nextSibling()->subelementByPath(diag, item, remainingPath);
558  }
559  return nullptr;
560 }
561 
571 template <class ImplementationType>
573 {
574  return const_cast<GenericFileElement<ImplementationType> *>(this)->subelementByPath(diag, item);
575 }
576 
586 template <class ImplementationType>
588  Diagnostics &diag, IdentifierType item, IdentifierType remainingPath...) const
589 {
590  return const_cast<GenericFileElement<ImplementationType> *>(this)->subelementByPath(diag, item, remainingPath);
591 }
592 
602 template <class ImplementationType> ImplementationType *GenericFileElement<ImplementationType>::childById(const IdentifierType &id, Diagnostics &diag)
603 {
604  parse(diag); // ensure element is parsed
605  for (ImplementationType *child = firstChild(); child; child = child->nextSibling()) {
606  child->parse(diag);
607  if (child->id() == id) {
608  return child;
609  }
610  }
611  return nullptr;
612 }
613 
623 template <class ImplementationType>
624 const ImplementationType *GenericFileElement<ImplementationType>::childById(const IdentifierType &id, Diagnostics &diag) const
625 {
626  return const_cast<GenericFileElement<ImplementationType> *>(this)->childById(id, diag);
627 }
628 
639 template <class ImplementationType>
641 {
642  parse(diag); // ensure element is parsed
643  for (ImplementationType *sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) {
644  sibling->parse(diag);
645  if (sibling->id() == id) {
646  return sibling;
647  }
648  }
649  return nullptr;
650 }
651 
662 template <class ImplementationType>
663 const ImplementationType *GenericFileElement<ImplementationType>::siblingById(const IdentifierType &id, Diagnostics &diag) const
664 {
665  return const_cast<GenericFileElement<ImplementationType> *>(this)->siblingById(id, diag);
666 }
667 
678 template <class ImplementationType>
680 {
681  parse(diag); // ensure element is parsed
682  for (ImplementationType *sibling = static_cast<ImplementationType *>(this); sibling; sibling = sibling->nextSibling()) {
683  sibling->parse(diag);
684  if (sibling->id() == id) {
685  return sibling;
686  }
687  }
688  return nullptr;
689 }
690 
701 template <class ImplementationType>
703 {
704  return const_cast<GenericFileElement<ImplementationType> *>(this)->siblingByIdIncludingThis(id, diag);
705 }
706 
710 template <class ImplementationType> inline bool GenericFileElement<ImplementationType>::isParent() const
711 {
712  return static_cast<const ImplementationType *>(this)->isParent();
713 }
714 
718 template <class ImplementationType> inline bool GenericFileElement<ImplementationType>::isPadding() const
719 {
720  return static_cast<const ImplementationType *>(this)->isPadding();
721 }
722 
726 template <class ImplementationType> inline std::uint64_t GenericFileElement<ImplementationType>::firstChildOffset() const
727 {
728  return static_cast<const ImplementationType *>(this)->firstChildOffset();
729 }
730 
734 template <class ImplementationType> inline bool GenericFileElement<ImplementationType>::isParsed() const
735 {
736  return m_parsed;
737 }
738 
745 template <class ImplementationType> void GenericFileElement<ImplementationType>::clear()
746 {
747  m_id = IdentifierType();
748  //m_startOffset = 0;
749  m_idLength = 0;
750  m_dataSize = 0;
751  m_sizeLength = 0;
752  m_nextSibling = nullptr;
753  m_firstChild = nullptr;
754  m_parsed = false;
755 }
756 
771 template <class ImplementationType> void GenericFileElement<ImplementationType>::parse(Diagnostics &diag)
772 {
773  if (!m_parsed) {
774  static_cast<ImplementationType *>(this)->internalParse(diag);
775  m_parsed = true;
776  }
777 }
778 
795 template <class ImplementationType> void GenericFileElement<ImplementationType>::reparse(Diagnostics &diag)
796 {
797  clear();
798  static_cast<ImplementationType *>(this)->parse(diag);
799  m_parsed = true;
800 }
801 
814 template <class ImplementationType>
816  Diagnostics &diag, std::uint64_t *paddingSize, AbortableProgressFeedback *progress)
817 {
818  if (progress) {
819  progress->stopIfAborted();
820  }
821  // validate element itself by just parsing it
822  parse(diag);
823  // validate children
824  if (firstChild()) {
825  try {
826  firstChild()->validateSubsequentElementStructure(diag, paddingSize, progress);
827  } catch (const Failure &) {
828  // ignore critical errors in child structure to continue validating siblings
829  // (critical notifications about the errors should have already been added to diag, so nothing to do)
830  }
831  } else if (paddingSize && isPadding()) { // element is padding
832  *paddingSize += totalSize();
833  }
834  // validate siblings
835  if (nextSibling()) {
836  nextSibling()->validateSubsequentElementStructure(diag, paddingSize, progress);
837  }
838 }
839 
843 template <class ImplementationType>
845 {
846  copyInternal(targetStream, startOffset(), headerSize(), diag, progress);
847 }
848 
852 template <class ImplementationType>
854 {
855  if (std::uint32_t firstChildOffset = this->firstChildOffset()) {
856  copyInternal(targetStream, startOffset(), firstChildOffset, diag, progress);
857  } else {
858  copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
859  }
860 }
861 
865 template <class ImplementationType>
867 {
868  copyInternal(targetStream, startOffset(), totalSize(), diag, progress);
869 }
870 
875 template <class ImplementationType> void GenericFileElement<ImplementationType>::makeBuffer()
876 {
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()));
880 }
881 
885 template <class ImplementationType> inline void GenericFileElement<ImplementationType>::discardBuffer()
886 {
887  m_buffer.reset();
888 }
889 
894 template <class ImplementationType> inline void GenericFileElement<ImplementationType>::copyBuffer(std::ostream &targetStream)
895 {
896  targetStream.write(m_buffer.get(), static_cast<std::streamsize>(totalSize()));
897 }
898 
903 template <class ImplementationType>
905  std::ostream &targetStream, Diagnostics &diag, AbortableProgressFeedback *progress)
906 {
907  m_buffer ? copyBuffer(targetStream) : copyEntirely(targetStream, diag, progress);
908 }
909 
914 template <class ImplementationType> inline const std::unique_ptr<char[]> &GenericFileElement<ImplementationType>::buffer()
915 {
916  return m_buffer;
917 }
918 
926 template <class ImplementationType>
928  std::ostream &targetStream, std::uint64_t startOffset, std::uint64_t bytesToCopy, Diagnostics &diag, AbortableProgressFeedback *progress)
929 {
930  // ensure the header has been parsed correctly
931  try {
932  parse(diag);
933  } catch (const Failure &) {
934  throw InvalidDataException();
935  }
936  auto &stream = container().stream();
937  stream.seekg(static_cast<std::streamoff>(startOffset), std::ios_base::beg);
939  if (progress) {
940  copyHelper.callbackCopy(stream, targetStream, bytesToCopy, std::bind(&AbortableProgressFeedback::isAborted, std::ref(progress)),
941  std::bind(&AbortableProgressFeedback::updateStepPercentageFromFraction, std::ref(progress), std::placeholders::_1));
942  } else {
943  copyHelper.copy(stream, targetStream, bytesToCopy);
944  }
945 }
946 
951 template <class ImplementationType>
952 ImplementationType *GenericFileElement<ImplementationType>::denoteFirstChild(std::uint32_t relativeFirstChildOffset)
953 {
954  if (relativeFirstChildOffset + minimumElementSize() <= totalSize()) {
955  m_firstChild.reset(new ImplementationType(static_cast<ImplementationType &>(*this), startOffset() + relativeFirstChildOffset));
956  } else {
957  m_firstChild.reset();
958  }
959  return m_firstChild.get();
960 }
961 
965 template <class ImplementationType> constexpr std::uint32_t GenericFileElement<ImplementationType>::maximumIdLengthSupported()
966 {
967  return sizeof(IdentifierType);
968 }
969 
973 template <class ImplementationType> constexpr std::uint32_t GenericFileElement<ImplementationType>::maximumSizeLengthSupported()
974 {
975  return sizeof(DataSizeType);
976 }
977 
981 template <class ImplementationType> constexpr std::uint8_t GenericFileElement<ImplementationType>::minimumElementSize()
982 {
984 }
985 
1000 } // namespace TagParser
1001 
1002 #endif // TAG_PARSER_GENERICFILEELEMENT_H
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.
Definition: diagnostics.h:156
The class inherits from std::exception and serves as base class for exceptions thrown by the elements...
Definition: exceptions.h:11
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...
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.
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.
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10