Tag Parser 12.3.1
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
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;
47 bool addTrack(TrackType *track);
48 bool removeTrack(AbstractTrack *track) 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>
72 : AbstractContainer(fileInfo.stream(), startOffset)
73 , m_fileInfo(&fileInfo)
74{
75}
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>
133{
134 return m_firstElement.get();
135}
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{
147 return m_additionalElements;
148}
149
157template <class FileInfoType, class TagType, class TrackType, class ElementType>
159{
160 return m_additionalElements;
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{
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>
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>
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>
369{
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
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
The AbstractContainer class provides an interface and common functionality to parse and make a certai...
virtual void reset()
Discards all parsing results.
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
FileInfoType & fileInfo() const
Returns the related file info.
~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.
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.
#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 ...