Tag Parser 12.5.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
genericcontainer.h
Go to the documentation of this file.
1#ifndef TAG_PARSER_GENERICCONTAINER_H
2#define TAG_PARSER_GENERICCONTAINER_H
3
5
6#include <algorithm>
7#include <memory>
8#include <vector>
9
10namespace TagParser {
11
22template <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);
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;
49 void removeAllTracks() override;
50 void reset() override;
51
52 using ContainerFileInfoType = FileInfoType;
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>
76
83template <class FileInfoType, class TagType, class TrackType, class ElementType>
87
98template <class FileInfoType, class TagType, class TrackType, class ElementType>
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>
115{
116 return *m_fileInfo;
117}
118
131template <class FileInfoType, class TagType, class TrackType, class ElementType>
136
144template <class FileInfoType, class TagType, class TrackType, class ElementType>
145inline const std::vector<std::unique_ptr<ElementType>> &GenericContainer<FileInfoType, TagType, TrackType, ElementType>::additionalElements() const
146{
148}
149
157template <class FileInfoType, class TagType, class TrackType, class ElementType>
159{
161}
162
163template <class FileInfoType, class TagType, class TrackType, class ElementType>
165{
166 return m_tags[index].get();
167}
168
169template <class FileInfoType, class TagType, class TrackType, class ElementType>
171{
172 return m_tags.size();
173}
174
175template <class FileInfoType, class TagType, class TrackType, class ElementType>
177{
178 return m_tracks[index].get();
179}
180
181template <class FileInfoType, class TagType, class TrackType, class ElementType>
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>
194{
195 return m_tracks.size();
196}
197
207template <class FileInfoType, class TagType, class TrackType, class ElementType>
208inline 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>
224{
225 return m_tags;
226}
227
237template <class FileInfoType, class TagType, class TrackType, class ElementType>
238inline 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>
253inline 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>
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>
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>
297
314template <class FileInfoType, class TagType, class TrackType, class ElementType>
316{
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>
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>
366
367template <class FileInfoType, class TagType, class TrackType, class ElementType>
376
377} // namespace TagParser
378
379#endif // TAG_PARSER_GENERICCONTAINER_H
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
std::iostream & stream()
Returns the related stream.
std::uint64_t startOffset() const
Returns the start offset in the related stream.
bool areTracksParsed() const
Returns an indication whether the tracks have been parsed yet.
virtual bool supportsTrackModifications() const
Returns whether the implementation supports adding or removing of tracks.
virtual void reset()
Discards all parsing results.
void parseHeader(Diagnostics &diag, AbortableProgressFeedback &progress)
Parses the header if not parsed yet.
AbstractContainer(std::iostream &stream, std::uint64_t startOffset)
Constructs a new container for the specified file stream at the specified startOffset.
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
The Diagnostics class is a container for DiagMessage.
const std::vector< std::unique_ptr< TrackType > > & tracks() const
Returns the tracks of the file.
bool removeTrack(AbstractTrack *track) override
Removes the specified track to the container.
TagType * tag(std::size_t index) override
Returns the tag with the specified index.
void validateElementStructure(Diagnostics &diag, AbortableProgressFeedback &progress, std::uint64_t *paddingSize=nullptr)
Parses all elements the file consists of.
bool removeTag(Tag *tag) override
Removes the specified tag from the container.
TrackType * track(std::size_t index) override
Returns the track with the specified index.
void removeAllTags() override
Removes all tags attached to the container.
std::vector< std::unique_ptr< TrackType > > m_tracks
TagType * createTag(const TagTarget &target=TagTarget()) override
Creates and returns a tag for the specified target.
const std::vector< std::unique_ptr< TagType > > & tags() const
Returns the tags of the file.
GenericContainer(FileInfoType &fileInfo, std::uint64_t startOffset)
Constructs a new container for the specified fileInfo at the specified startOffset.
TrackType * trackById(std::uint64_t id)
bool addTrack(TrackType *track)
Adds the specified track to the container.
std::unique_ptr< ElementType > m_firstElement
~GenericContainer() override
Destroys the container.
std::vector< std::unique_ptr< ElementType > > m_additionalElements
void removeAllTracks() override
Removes all tracks from the container.
std::vector< std::unique_ptr< TrackType > > & tracks()
Returns the tracks of the file.
ElementType * firstElement() const
Returns the first element of the file if available; otherwiese returns nullptr.
std::vector< std::unique_ptr< TagType > > m_tags
std::size_t trackCount() const override
Returns the number of tracks the container holds.
std::vector< std::unique_ptr< TagType > > & tags()
Returns the tags of the file.
const std::vector< std::unique_ptr< ElementType > > & additionalElements() const
Returns all available additional elements.
void reset() override
Discards all parsing results.
std::size_t tagCount() const override
Returns the number of tags attached to the container.
std::vector< std::unique_ptr< ElementType > > & additionalElements()
Returns all available additional elements.
The TagTarget class specifies the target of a tag.
Definition tagtarget.h:20
bool isEmpty() const
Returns an indication whether the target is empty.
Definition tagtarget.h:169
The Tag class is used to store, read and write tag information.
Definition tag.h:179
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
Definition global.h:14
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10
TagType
Specifies the tag type.
Definition tagtype.h:11
TrackType
The TrackType enum specifies the underlying file type of a track and the concrete class of the track ...