Tag Parser: genericcontainer.h Source File

Tag Parser 12.5.3 C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags

Loading...
Searching...
No Matches
genericcontainer.h
Go to the documentation of this file.
1#ifndef TAG_PARSER_GENERICCONTAINER_H
2#define TAG_PARSER_GENERICCONTAINER_H
3
4#include "./abstractcontainer.h"
5
6#include <algorithm>
7#include <memory>
8#include <vector>
9
10namespace TagParser {
11
22 template <class FileInfoType, class TagType, class TrackType, class ElementType> class TAG_PARSER_EXPORT GenericContainer : public AbstractContainer {
23 friend FileInfoType;
24
25public:
26 GenericContainer(FileInfoType &fileInfo, std::uint64_t startOffset);
27 ~GenericContainer() override;
28
29 void validateElementStructure(Diagnostics &diag, AbortableProgressFeedback &progress, std::uint64_t *paddingSize = nullptr);
30 FileInfoType &fileInfo() const;
31 ElementType *firstElement() const;
32 const std::vector<std::unique_ptr<ElementType>> &additionalElements() const;
33 std::vector<std::unique_ptr<ElementType>> &additionalElements();
34 TagType *tag(std::size_t index) override;
35 std::size_t tagCount() const override;
36 TrackType *track(std::size_t index) override;
37 TrackType *trackById(std::uint64_t id);
38 std::size_t trackCount() const override;
39 const std::vector<std::unique_ptr<TagType>> &tags() const;
40 std::vector<std::unique_ptr<TagType>> &tags();
41 const std::vector<std::unique_ptr<TrackType>> &tracks() const;
42 std::vector<std::unique_ptr<TrackType>> &tracks();
43
44 TagType *createTag(const TagTarget &target = TagTarget()) override;
45 bool removeTag(Tag *tag) override;
46 void removeAllTags() override;
47 bool addTrack(TrackType *track);
48 bool removeTrack(AbstractTrack *track) override;
49 void removeAllTracks() override;
50 void reset() override;
51
52 using ContainerFileInfoType = FileInfoType;
53 using ContainerTagType = TagType;
54 using ContainerTrackType = TrackType;
55 using ContainerElementType = ElementType;
56
57protected:
58 std::unique_ptr<ElementType> m_firstElement;
59 std::vector<std::unique_ptr<ElementType>> m_additionalElements;
60 std::vector<std::unique_ptr<TagType>> m_tags;
61 std::vector<std::unique_ptr<TrackType>> m_tracks;
62
63private:
64 FileInfoType *m_fileInfo;
65};
66
70template <class FileInfoType, class TagType, class TrackType, class ElementType>
71GenericContainer<FileInfoType, TagType, TrackType, ElementType>::GenericContainer(FileInfoType &fileInfo, std::uint64_t startOffset)
72 : AbstractContainer(fileInfo.stream(), startOffset)
73 , m_fileInfo(&fileInfo)
74{
75}
76
83template <class FileInfoType, class TagType, class TrackType, class ElementType>
84GenericContainer<FileInfoType, TagType, TrackType, ElementType>::~GenericContainer()
85{
86}
87
98template <class FileInfoType, class TagType, class TrackType, class ElementType>
99 inline void GenericContainer<FileInfoType, TagType, TrackType, ElementType>::validateElementStructure(
100 Diagnostics &diag, AbortableProgressFeedback &progress, std::uint64_t *paddingSize)
101{
102 parseHeader(diag, progress);
103 if (m_firstElement) {
104 m_firstElement->validateSubsequentElementStructure(diag, paddingSize, &progress);
105 }
106}
107
113template <class FileInfoType, class TagType, class TrackType, class ElementType>
114 inline FileInfoType &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::fileInfo() const
115{
116 return *m_fileInfo;
117}
118
131template <class FileInfoType, class TagType, class TrackType, class ElementType>
132 inline ElementType *GenericContainer<FileInfoType, TagType, TrackType, ElementType>::firstElement() const
133{
134 return m_firstElement.get();
135}
136
144template <class FileInfoType, class TagType, class TrackType, class ElementType>
145 inline const std::vector<std::unique_ptr<ElementType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::additionalElements() const
146{
147 return m_additionalElements;
148}
149
157template <class FileInfoType, class TagType, class TrackType, class ElementType>
158 inline std::vector<std::unique_ptr<ElementType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::additionalElements()
159{
160 return m_additionalElements;
161}
162
163template <class FileInfoType, class TagType, class TrackType, class ElementType>
164 inline TagType *GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tag(std::size_t index)
165{
166 return m_tags[index].get();
167}
168
169template <class FileInfoType, class TagType, class TrackType, class ElementType>
170 inline std::size_t GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tagCount() const
171{
172 return m_tags.size();
173}
174
175template <class FileInfoType, class TagType, class TrackType, class ElementType>
176 inline TrackType *GenericContainer<FileInfoType, TagType, TrackType, ElementType>::track(std::size_t index)
177{
178 return m_tracks[index].get();
179}
180
181template <class FileInfoType, class TagType, class TrackType, class ElementType>
182 inline TrackType *GenericContainer<FileInfoType, TagType, TrackType, ElementType>::trackById(std::uint64_t id)
183{
184 for (auto &track : m_tracks) {
185 if (track->id() == id) {
186 return track.get();
187 }
188 }
189 return nullptr;
190}
191
192template <class FileInfoType, class TagType, class TrackType, class ElementType>
193 inline std::size_t GenericContainer<FileInfoType, TagType, TrackType, ElementType>::trackCount() const
194{
195 return m_tracks.size();
196}
197
207template <class FileInfoType, class TagType, class TrackType, class ElementType>
208 inline const std::vector<std::unique_ptr<TagType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tags() const
209{
210 return m_tags;
211}
212
222template <class FileInfoType, class TagType, class TrackType, class ElementType>
223 inline std::vector<std::unique_ptr<TagType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tags()
224{
225 return m_tags;
226}
227
237template <class FileInfoType, class TagType, class TrackType, class ElementType>
238 inline const std::vector<std::unique_ptr<TrackType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tracks() const
239{
240 return m_tracks;
241}
242
252template <class FileInfoType, class TagType, class TrackType, class ElementType>
253 inline std::vector<std::unique_ptr<TrackType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::tracks()
254{
255 return m_tracks;
256}
257
258template <class FileInfoType, class TagType, class TrackType, class ElementType>
259 TagType *GenericContainer<FileInfoType, TagType, TrackType, ElementType>::createTag(const TagTarget &target)
260{
261 // check whether a tag matching the specified target is already assigned
262 if (!m_tags.empty()) {
263 if (!target.isEmpty() && m_tags.front()->supportsTarget()) {
264 for (auto &tag : m_tags) {
265 if (tag->target() == target) {
266 return tag.get();
267 }
268 }
269 } else {
270 return m_tags.front().get();
271 }
272 }
273
274 // a new tag must be created
275 const auto &tag = m_tags.emplace_back(std::make_unique<TagType>());
276 tag->setTarget(target);
277 return tag.get();
278}
279
280template <class FileInfoType, class TagType, class TrackType, class ElementType>
281 bool GenericContainer<FileInfoType, TagType, TrackType, ElementType>::removeTag(Tag *tag)
282{
283 if (const auto size = m_tags.size()) {
284 m_tags.erase(std::remove_if(m_tags.begin(), m_tags.end(),
285 [tag](const std::unique_ptr<TagType> &existingTag) -> bool { return static_cast<Tag *>(existingTag.get()) == tag; }),
286 m_tags.end());
287 return size != m_tags.size();
288 }
289 return false;
290}
291
292template <class FileInfoType, class TagType, class TrackType, class ElementType>
293 inline void GenericContainer<FileInfoType, TagType, TrackType, ElementType>::removeAllTags()
294{
295 m_tags.clear();
296}
297
314template <class FileInfoType, class TagType, class TrackType, class ElementType>
315 bool GenericContainer<FileInfoType, TagType, TrackType, ElementType>::addTrack(TrackType *track)
316{
317 if (!areTracksParsed() || !supportsTrackModifications()) {
318 return false;
319 }
320 // ensure ID is unique
321 auto id = track->id();
322ensureIdIsUnique:
323 for (const auto &existingTrack : m_tracks) {
324 if (existingTrack->id() == id) {
325 ++id;
326 goto ensureIdIsUnique;
327 }
328 }
329 track->setId(id);
330
331 m_tracks.emplace_back(track);
332 return m_tracksAltered = true;
333}
334
335template <class FileInfoType, class TagType, class TrackType, class ElementType>
336 bool GenericContainer<FileInfoType, TagType, TrackType, ElementType>::removeTrack(AbstractTrack *track)
337{
338 if (!areTracksParsed() || !supportsTrackModifications() || m_tracks.empty()) {
339 return false;
340 }
341 auto removed = false;
342 for (auto i = m_tracks.end() - 1, begin = m_tracks.begin();; --i) {
343 if (static_cast<AbstractTrack *>(i->get()) == track) {
344 i->release();
345 m_tracks.erase(i);
346 removed = true;
347 }
348 if (i == begin) {
349 break;
350 }
351 }
352 if (removed) {
353 m_tracksAltered = true;
354 }
355 return removed;
356}
357
358template <class FileInfoType, class TagType, class TrackType, class ElementType>
359 void GenericContainer<FileInfoType, TagType, TrackType, ElementType>::removeAllTracks()
360{
361 if (areTracksParsed() && supportsTrackModifications() && m_tracks.size()) {
362 m_tracks.clear();
363 m_tracksAltered = true;
364 }
365}
366
367template <class FileInfoType, class TagType, class TrackType, class ElementType>
368 void GenericContainer<FileInfoType, TagType, TrackType, ElementType>::reset()
369{
370 AbstractContainer::reset();
371 m_firstElement.reset();
372 m_additionalElements.clear();
373 m_tracks.clear();
374 m_tags.clear();
375}
376
377} // namespace TagParser
378
379#endif // TAG_PARSER_GENERICCONTAINER_H
abstractcontainer.h
TagParser::AbortableProgressFeedback
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
Definition progressfeedback.h:186
TagParser::AbstractContainer::stream
std::iostream & stream()
Returns the related stream.
Definition abstractcontainer.h:136
TagParser::AbstractContainer::startOffset
std::uint64_t startOffset() const
Returns the start offset in the related stream.
Definition abstractcontainer.h:154
TagParser::AbstractContainer::areTracksParsed
bool areTracksParsed() const
Returns an indication whether the tracks have been parsed yet.
Definition abstractcontainer.h:210
TagParser::AbstractContainer::supportsTrackModifications
virtual bool supportsTrackModifications() const
Returns whether the implementation supports adding or removing of tracks.
Definition abstractcontainer.cpp:174
TagParser::AbstractContainer::reset
virtual void reset()
Discards all parsing results.
Definition abstractcontainer.cpp:525
TagParser::AbstractContainer::parseHeader
void parseHeader(Diagnostics &diag, AbortableProgressFeedback &progress)
Parses the header if not parsed yet.
Definition abstractcontainer.cpp:60
TagParser::AbstractContainer::AbstractContainer
AbstractContainer(std::iostream &stream, std::uint64_t startOffset)
Constructs a new container for the specified file stream at the specified startOffset.
Definition abstractcontainer.cpp:22
TagParser::AbstractContainer::m_tracksAltered
bool m_tracksAltered
Definition abstractcontainer.h:119
TagParser::AbstractTrack
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
Definition abstracttrack.h:110
TagParser::Diagnostics
The Diagnostics class is a container for DiagMessage.
Definition diagnostics.h:156
TagParser::GenericContainer::tracks
const std::vector< std::unique_ptr< TrackType > > & tracks() const
Returns the tracks of the file.
Definition genericcontainer.h:238
TagParser::GenericContainer::removeTrack
bool removeTrack(AbstractTrack *track) override
Removes the specified track to the container.
Definition genericcontainer.h:336
TagParser::GenericContainer::tag
TagType * tag(std::size_t index) override
Returns the tag with the specified index.
Definition genericcontainer.h:164
TagParser::GenericContainer::validateElementStructure
void validateElementStructure(Diagnostics &diag, AbortableProgressFeedback &progress, std::uint64_t *paddingSize=nullptr)
Parses all elements the file consists of.
Definition genericcontainer.h:99
TagParser::GenericContainer::removeTag
bool removeTag(Tag *tag) override
Removes the specified tag from the container.
Definition genericcontainer.h:281
TagParser::GenericContainer::track
TrackType * track(std::size_t index) override
Returns the track with the specified index.
Definition genericcontainer.h:176
TagParser::GenericContainer::removeAllTags
void removeAllTags() override
Removes all tags attached to the container.
Definition genericcontainer.h:293
TagParser::GenericContainer::ContainerTagType
TagType ContainerTagType
Definition genericcontainer.h:53
TagParser::GenericContainer::m_tracks
std::vector< std::unique_ptr< TrackType > > m_tracks
Definition genericcontainer.h:61
TagParser::GenericContainer::createTag
TagType * createTag(const TagTarget &target=TagTarget()) override
Creates and returns a tag for the specified target.
Definition genericcontainer.h:259
TagParser::GenericContainer::tags
const std::vector< std::unique_ptr< TagType > > & tags() const
Returns the tags of the file.
Definition genericcontainer.h:208
TagParser::GenericContainer::GenericContainer
GenericContainer(FileInfoType &fileInfo, std::uint64_t startOffset)
Constructs a new container for the specified fileInfo at the specified startOffset.
Definition genericcontainer.h:71
TagParser::GenericContainer::trackById
TrackType * trackById(std::uint64_t id)
Definition genericcontainer.h:182
TagParser::GenericContainer::ContainerTrackType
TrackType ContainerTrackType
Definition genericcontainer.h:54
TagParser::GenericContainer::addTrack
bool addTrack(TrackType *track)
Adds the specified track to the container.
Definition genericcontainer.h:315
TagParser::GenericContainer::m_firstElement
std::unique_ptr< ElementType > m_firstElement
Definition genericcontainer.h:58
TagParser::GenericContainer::ContainerElementType
ElementType ContainerElementType
Definition genericcontainer.h:55
TagParser::GenericContainer< MediaFileInfo, MatroskaTag, MatroskaTrack, EbmlElement >::fileInfo
MediaFileInfo & fileInfo() const
Definition genericcontainer.h:114
TagParser::GenericContainer::~GenericContainer
~GenericContainer() override
Destroys the container.
Definition genericcontainer.h:84
TagParser::GenericContainer::m_additionalElements
std::vector< std::unique_ptr< ElementType > > m_additionalElements
Definition genericcontainer.h:59
TagParser::GenericContainer::removeAllTracks
void removeAllTracks() override
Removes all tracks from the container.
Definition genericcontainer.h:359
TagParser::GenericContainer::firstElement
ElementType * firstElement() const
Returns the first element of the file if available; otherwiese returns nullptr.
Definition genericcontainer.h:132
TagParser::GenericContainer::m_tags
std::vector< std::unique_ptr< TagType > > m_tags
Definition genericcontainer.h:60
TagParser::GenericContainer::trackCount
std::size_t trackCount() const override
Returns the number of tracks the container holds.
Definition genericcontainer.h:193
TagParser::GenericContainer::additionalElements
const std::vector< std::unique_ptr< ElementType > > & additionalElements() const
Returns all available additional elements.
Definition genericcontainer.h:145
TagParser::GenericContainer::reset
void reset() override
Discards all parsing results.
Definition genericcontainer.h:368
TagParser::GenericContainer::tagCount
std::size_t tagCount() const override
Returns the number of tags attached to the container.
Definition genericcontainer.h:170
TagParser::GenericContainer::ContainerFileInfoType
FileInfoType ContainerFileInfoType
Definition genericcontainer.h:52
TagParser::TagTarget
The TagTarget class specifies the target of a tag.
Definition tagtarget.h:20
TagParser::TagTarget::isEmpty
bool isEmpty() const
Returns an indication whether the target is empty.
Definition tagtarget.h:169
TagParser::Tag
The Tag class is used to store, read and write tag information.
Definition tag.h:179
TAG_PARSER_EXPORT
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
Definition global.h:14
TagParser
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10
TagParser::TagType
TagType
Specifies the tag type.
Definition tagtype.h:11
TagParser::TrackType
TrackType
The TrackType enum specifies the underlying file type of a track and the concrete class of the track ...
Definition abstracttrack.h:32