diff --git a/taglib/matroska/ebml/ebmlbinaryelement.h b/taglib/matroska/ebml/ebmlbinaryelement.h index b8dd686e..bcf9fd70 100644 --- a/taglib/matroska/ebml/ebmlbinaryelement.h +++ b/taglib/matroska/ebml/ebmlbinaryelement.h @@ -34,6 +34,10 @@ namespace TagLib { Element(id, sizeLength, dataSize) { } + BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t) : + Element(id, sizeLength, dataSize) + { + } explicit BinaryElement(Id id) : Element(id, 0, 0) diff --git a/taglib/matroska/ebml/ebmlelement.cpp b/taglib/matroska/ebml/ebmlelement.cpp index 25fdc52a..7c947e85 100644 --- a/taglib/matroska/ebml/ebmlelement.cpp +++ b/taglib/matroska/ebml/ebmlelement.cpp @@ -39,12 +39,15 @@ using namespace TagLib; -EBML::Element *EBML::Element::factory(File &file) +#define RETURN_ELEMENT_FOR_CASE(eid) \ + case (eid): return make_unique_element(id, sizeLength, dataSize, offset) + +std::unique_ptr EBML::Element::factory(File &file) { // Get the element ID offset_t offset = file.tell(); - Id id = readId(file); - if(!id) { + unsigned int uintId = readId(file); + if(!uintId) { debug("Failed to parse EMBL ElementID"); return nullptr; } @@ -55,73 +58,62 @@ EBML::Element *EBML::Element::factory(File &file) return nullptr; // Return the subclass + // The enum switch without default will give us a warning if an ID is missing + auto id = static_cast(uintId); switch(id) { - case ElementIDs::EBMLHeader: - return new Element(id, sizeLength, dataSize); - - case ElementIDs::MkSegment: - return new MkSegment(sizeLength, dataSize, offset); - - case ElementIDs::MkInfo: - return new MkInfo(sizeLength, dataSize, offset); - - case ElementIDs::MkTracks: - return new MkTracks(sizeLength, dataSize, offset); - - case ElementIDs::MkTags: - return new MkTags(sizeLength, dataSize, offset); - - case ElementIDs::MkAttachments: - return new MkAttachments(sizeLength, dataSize, offset); - - case ElementIDs::MkTag: - case ElementIDs::MkTagTargets: - case ElementIDs::MkSimpleTag: - case ElementIDs::MkAttachedFile: - case ElementIDs::MkSeek: - case ElementIDs::MkTrackEntry: - case ElementIDs::MkAudio: - return new MasterElement(id, sizeLength, dataSize, offset); - - case ElementIDs::MkTagName: - case ElementIDs::MkTagString: - case ElementIDs::MkAttachedFileName: - case ElementIDs::MkAttachedFileDescription: - return new UTF8StringElement(id, sizeLength, dataSize); - - case ElementIDs::MkTagLanguage: - case ElementIDs::MkAttachedFileMediaType: - case ElementIDs::MkCodecID: - return new Latin1StringElement(id, sizeLength, dataSize); - - case ElementIDs::MkTagTargetTypeValue: - case ElementIDs::MkAttachedFileUID: - case ElementIDs::MkSeekPosition: - case ElementIDs::MkTimestampScale: - case ElementIDs::MkBitDepth: - case ElementIDs::MkChannels: - return new UIntElement(id, sizeLength, dataSize); - - case ElementIDs::MkAttachedFileData: - case ElementIDs::MkSeekID: - return new BinaryElement(id, sizeLength, dataSize); - - case ElementIDs::MkDuration: - case ElementIDs::MkSamplingFrequency: - return new FloatElement(id, sizeLength, dataSize); - - case ElementIDs::MkSeekHead: - return new MkSeekHead(sizeLength, dataSize, offset); - - case ElementIDs::VoidElement: - return new VoidElement(sizeLength, dataSize); - - default: - return new Element(id, sizeLength, dataSize); + RETURN_ELEMENT_FOR_CASE(Id::EBMLHeader); + RETURN_ELEMENT_FOR_CASE(Id::MkSegment); + RETURN_ELEMENT_FOR_CASE(Id::MkInfo); + RETURN_ELEMENT_FOR_CASE(Id::MkTracks); + RETURN_ELEMENT_FOR_CASE(Id::MkTags); + RETURN_ELEMENT_FOR_CASE(Id::MkAttachments); + RETURN_ELEMENT_FOR_CASE(Id::MkTag); + RETURN_ELEMENT_FOR_CASE(Id::MkTagTargets); + RETURN_ELEMENT_FOR_CASE(Id::MkSimpleTag); + RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFile); + RETURN_ELEMENT_FOR_CASE(Id::MkSeek); + RETURN_ELEMENT_FOR_CASE(Id::MkTrackEntry); + RETURN_ELEMENT_FOR_CASE(Id::MkAudio); + RETURN_ELEMENT_FOR_CASE(Id::MkTagName); + RETURN_ELEMENT_FOR_CASE(Id::MkTagString); + RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileName); + RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileDescription); + RETURN_ELEMENT_FOR_CASE(Id::MkTagLanguage); + RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileMediaType); + RETURN_ELEMENT_FOR_CASE(Id::MkCodecID); + RETURN_ELEMENT_FOR_CASE(Id::MkTagTargetTypeValue); + RETURN_ELEMENT_FOR_CASE(Id::MkTagsLanguageDefault); + RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileUID); + RETURN_ELEMENT_FOR_CASE(Id::MkSeekPosition); + RETURN_ELEMENT_FOR_CASE(Id::MkTimestampScale); + RETURN_ELEMENT_FOR_CASE(Id::MkBitDepth); + RETURN_ELEMENT_FOR_CASE(Id::MkChannels); + RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileData); + RETURN_ELEMENT_FOR_CASE(Id::MkSeekID); + RETURN_ELEMENT_FOR_CASE(Id::MkDuration); + RETURN_ELEMENT_FOR_CASE(Id::MkSamplingFrequency); + RETURN_ELEMENT_FOR_CASE(Id::MkSeekHead); + RETURN_ELEMENT_FOR_CASE(Id::VoidElement); + RETURN_ELEMENT_FOR_CASE(Id::MkCluster); + RETURN_ELEMENT_FOR_CASE(Id::MkCodecState); + RETURN_ELEMENT_FOR_CASE(Id::MkTagBinary); + RETURN_ELEMENT_FOR_CASE(Id::MkCues); + RETURN_ELEMENT_FOR_CASE(Id::MkCuePoint); + RETURN_ELEMENT_FOR_CASE(Id::MkCueTime); + RETURN_ELEMENT_FOR_CASE(Id::MkCueTrackPositions); + RETURN_ELEMENT_FOR_CASE(Id::MkCueTrack); + RETURN_ELEMENT_FOR_CASE(Id::MkCueClusterPosition); + RETURN_ELEMENT_FOR_CASE(Id::MkCueRelativePosition); + RETURN_ELEMENT_FOR_CASE(Id::MkCueDuration); + RETURN_ELEMENT_FOR_CASE(Id::MkCueBlockNumber); + RETURN_ELEMENT_FOR_CASE(Id::MkCueCodecState); + RETURN_ELEMENT_FOR_CASE(Id::MkCueReference); + RETURN_ELEMENT_FOR_CASE(Id::MkCueRefTime); } + return std::make_unique(id, sizeLength, dataSize); } -EBML::Element::Id EBML::Element::readId(File &file) +unsigned int EBML::Element::readId(File &file) { auto buffer = file.readBlock(1); if(buffer.size() != 1) { @@ -161,6 +153,7 @@ ByteVector EBML::Element::renderId() const { int numBytes = idSize(id); static const auto byteOrder = Utils::systemByteOrder(); - uint32_t data = byteOrder == Utils::LittleEndian ? Utils::byteSwap(id) : id; + auto uintId = static_cast(id); + uint32_t data = byteOrder == Utils::LittleEndian ? Utils::byteSwap(uintId) : uintId; return ByteVector(reinterpret_cast(&data) + (4 - numBytes), numBytes); } diff --git a/taglib/matroska/ebml/ebmlelement.h b/taglib/matroska/ebml/ebmlelement.h index 5cc0e06e..8f6a3fe8 100644 --- a/taglib/matroska/ebml/ebmlelement.h +++ b/taglib/matroska/ebml/ebmlelement.h @@ -22,6 +22,7 @@ #define TAGLIB_EBMLELEMENT_H #ifndef DO_NOT_DOCUMENT +#include #include "tfile.h" #include "tutils.h" #include "taglib.h" @@ -30,11 +31,67 @@ namespace TagLib::EBML { class Element { public: - using Id = unsigned int; + enum class Id : unsigned int + { + EBMLHeader = 0x1A45DFA3, + VoidElement = 0xEC, + MkSegment = 0x18538067, + MkTags = 0x1254C367, + MkTag = 0x7373, + MkTagTargets = 0x63C0, + MkTagTargetTypeValue = 0x68CA, + MkSimpleTag = 0x67C8, + MkTagName = 0x45A3, + MkTagLanguage = 0x447A, + MkTagBinary = 0x4485, + MkTagString = 0x4487, + MkTagsTagLanguage = 0x447A, + MkTagsLanguageDefault = 0x4484, + MkAttachments = 0x1941A469, + MkAttachedFile = 0x61A7, + MkAttachedFileDescription = 0x467E, + MkAttachedFileName = 0x466E, + MkAttachedFileMediaType = 0x4660, + MkAttachedFileData = 0x465C, + MkAttachedFileUID = 0x46AE, + MkSeekHead = 0x114D9B74, + MkSeek = 0x4DBB, + MkSeekID = 0x53AB, + MkSeekPosition = 0x53AC, + MkCluster = 0x1F43B675, + MkCodecState = 0xA4, + MkCues = 0x1C53BB6B, + MkCuePoint = 0xBB, + MkCueTime = 0xB3, + MkCueTrackPositions = 0xB7, + MkCueTrack = 0xF7, + MkCueClusterPosition = 0xF1, + MkCueRelativePosition = 0xF0, + MkCueDuration = 0xB2, + MkCueBlockNumber = 0x5378, + MkCueCodecState = 0xEA, + MkCueReference = 0xDB, + MkCueRefTime = 0x96, + MkInfo = 0x1549A966, + MkTimestampScale = 0x2AD7B1, + MkDuration = 0x4489, + MkTracks = 0x1654AE6B, + MkTrackEntry = 0xAE, + MkCodecID = 0x86, + MkAudio = 0xE1, + MkSamplingFrequency = 0xB5, + MkBitDepth = 0x6264, + MkChannels = 0x9F, + }; + Element(Id id, int sizeLength, offset_t dataSize) : id(id), sizeLength(sizeLength), dataSize(dataSize) { } + Element(Id id, int sizeLength, offset_t dataSize, offset_t) : + id(id), sizeLength(sizeLength), dataSize(dataSize) + { + } virtual ~Element() = default; virtual bool read(File &file) { @@ -49,8 +106,8 @@ namespace TagLib::EBML { int64_t getDataSize() const { return dataSize; } ByteVector renderId() const; virtual ByteVector render(); - static Element *factory(File &file); - static Id readId(File &file); + static std::unique_ptr factory(File &file); + static unsigned int readId(File &file); protected: Id id; @@ -58,57 +115,104 @@ namespace TagLib::EBML { offset_t dataSize; }; - namespace ElementIDs { - inline constexpr Element::Id EBMLHeader = 0x1A45DFA3; - inline constexpr Element::Id VoidElement = 0xEC; - inline constexpr Element::Id MkSegment = 0x18538067; - inline constexpr Element::Id MkTags = 0x1254C367; - inline constexpr Element::Id MkTag = 0x7373; - inline constexpr Element::Id MkTagTargets = 0x63C0; - inline constexpr Element::Id MkTagTargetTypeValue = 0x68CA; - inline constexpr Element::Id MkSimpleTag = 0x67C8; - inline constexpr Element::Id MkTagName = 0x45A3; - inline constexpr Element::Id MkTagLanguage = 0x447A; - inline constexpr Element::Id MkTagBinary = 0x4485; - inline constexpr Element::Id MkTagString = 0x4487; - inline constexpr Element::Id MkTagsTagLanguage = 0x447A; - inline constexpr Element::Id MkTagsLanguageDefault = 0x4484; - inline constexpr Element::Id MkAttachments = 0x1941A469; - inline constexpr Element::Id MkAttachedFile = 0x61A7; - inline constexpr Element::Id MkAttachedFileDescription = 0x467E; - inline constexpr Element::Id MkAttachedFileName = 0x466E; - inline constexpr Element::Id MkAttachedFileMediaType = 0x4660; - inline constexpr Element::Id MkAttachedFileData = 0x465C; - inline constexpr Element::Id MkAttachedFileUID = 0x46AE; - inline constexpr Element::Id MkSeekHead = 0x114D9B74; - inline constexpr Element::Id MkSeek = 0x4DBB; - inline constexpr Element::Id MkSeekID = 0x53AB; - inline constexpr Element::Id MkSeekPosition = 0x53AC; - inline constexpr Element::Id MkCluster = 0x1F43B675; - inline constexpr Element::Id MkCodecState = 0xA4; - inline constexpr Element::Id MkCues = 0x1C53BB6B; - inline constexpr Element::Id MkCuePoint = 0xBB; - inline constexpr Element::Id MkCueTime = 0xB3; - inline constexpr Element::Id MkCueTrackPositions = 0xB7; - inline constexpr Element::Id MkCueTrack = 0xF7; - inline constexpr Element::Id MkCueClusterPosition = 0xF1; - inline constexpr Element::Id MkCueRelativePosition = 0xF0; - inline constexpr Element::Id MkCueDuration = 0xB2; - inline constexpr Element::Id MkCueBlockNumber = 0x5378; - inline constexpr Element::Id MkCueCodecState = 0xEA; - inline constexpr Element::Id MkCueReference = 0xDB; - inline constexpr Element::Id MkCueRefTime = 0x96; - inline constexpr Element::Id MkInfo = 0x1549A966; - inline constexpr Element::Id MkTimestampScale = 0x2AD7B1; - inline constexpr Element::Id MkDuration = 0x4489; - inline constexpr Element::Id MkTracks = 0x1654AE6B; - inline constexpr Element::Id MkTrackEntry = 0xAE; - inline constexpr Element::Id MkCodecID = 0x86; - inline constexpr Element::Id MkAudio = 0xE1; - inline constexpr Element::Id MkSamplingFrequency = 0xB5; - inline constexpr Element::Id MkBitDepth = 0x6264; - inline constexpr Element::Id MkChannels = 0x9F; + // Template specializations to ensure that elements for the different IDs + // are consistently created and cast. They provide a mapping between IDs + // and Element subclasses. The switch in factory() makes sure that the + // template for all IDs are instantiated, i.e. that every ID has its Element + // subclass mapped. + class MasterElement; + class UIntElement; + class BinaryElement; + class FloatElement; + class MkSegment; + class MkInfo; + class MkTracks; + class MkTags; + class MkAttachments; + class MkSeekHead; + class VoidElement; + + template + class StringElement; + using UTF8StringElement = StringElement; + using Latin1StringElement = StringElement; + + template + struct GetElementTypeById; + + template <> struct GetElementTypeById { using type = Element; }; + template <> struct GetElementTypeById { using type = MkSegment; }; + template <> struct GetElementTypeById { using type = MkInfo; }; + template <> struct GetElementTypeById { using type = MkTracks; }; + template <> struct GetElementTypeById { using type = MkTags; }; + template <> struct GetElementTypeById { using type = MkAttachments; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = UTF8StringElement; }; + template <> struct GetElementTypeById { using type = UTF8StringElement; }; + template <> struct GetElementTypeById { using type = UTF8StringElement; }; + template <> struct GetElementTypeById { using type = UTF8StringElement; }; + template <> struct GetElementTypeById { using type = Latin1StringElement; }; + template <> struct GetElementTypeById { using type = Latin1StringElement; }; + template <> struct GetElementTypeById { using type = Latin1StringElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = BinaryElement; }; + template <> struct GetElementTypeById { using type = BinaryElement; }; + template <> struct GetElementTypeById { using type = BinaryElement; }; + template <> struct GetElementTypeById { using type = BinaryElement; }; + template <> struct GetElementTypeById { using type = FloatElement; }; + template <> struct GetElementTypeById { using type = FloatElement; }; + template <> struct GetElementTypeById { using type = MkSeekHead; }; + template <> struct GetElementTypeById { using type = VoidElement; }; + + template ::type> + const T *element_cast(const std::unique_ptr &ptr) + { + return static_cast(ptr.get()); } + + template ::type> + std::unique_ptr element_cast(std::unique_ptr &&ptr) + { + return std::unique_ptr(static_cast(ptr.release())); + } + + template ::type> + std::unique_ptr make_unique_element(Element::Id id, int sizeLength, offset_t dataSize, offset_t offset) + { + return std::make_unique(id, sizeLength, dataSize, offset); + } + + template ::type> + std::unique_ptr make_unique_element() + { + return std::make_unique(ID, 0, 0, 0); + } + } #endif diff --git a/taglib/matroska/ebml/ebmlfloatelement.h b/taglib/matroska/ebml/ebmlfloatelement.h index a51e444c..2c9ef59c 100644 --- a/taglib/matroska/ebml/ebmlfloatelement.h +++ b/taglib/matroska/ebml/ebmlfloatelement.h @@ -43,6 +43,10 @@ namespace TagLib { Element(id, sizeLength, dataSize) { } + FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t) : + Element(id, sizeLength, dataSize) + { + } explicit FloatElement(Id id) : FloatElement(id, 0, 0) diff --git a/taglib/matroska/ebml/ebmlmasterelement.cpp b/taglib/matroska/ebml/ebmlmasterelement.cpp index cfaea47e..fd0447dd 100644 --- a/taglib/matroska/ebml/ebmlmasterelement.cpp +++ b/taglib/matroska/ebml/ebmlmasterelement.cpp @@ -25,20 +25,21 @@ using namespace TagLib; -EBML::MasterElement::~MasterElement() +EBML::MasterElement::~MasterElement() = default; + +void EBML::MasterElement::appendElement(std::unique_ptr&& element) { - for(auto element : elements) - delete element; + elements.push_back(std::move(element)); } bool EBML::MasterElement::read(File &file) { offset_t maxOffset = file.tell() + dataSize; - Element *element = nullptr; + std::unique_ptr element; while((element = findNextElement(file, maxOffset))) { if(!element->read(file)) return false; - elements.append(element); + elements.push_back(std::move(element)); } return file.tell() == maxOffset; } @@ -47,7 +48,7 @@ ByteVector EBML::MasterElement::render() { ByteVector buffer = renderId(); ByteVector data; - for(auto element : elements) + for(const auto &element : elements) data.append(element->render()); dataSize = data.size(); buffer.append(renderVINT(dataSize, 0)); diff --git a/taglib/matroska/ebml/ebmlmasterelement.h b/taglib/matroska/ebml/ebmlmasterelement.h index cdccee75..c7f7a846 100644 --- a/taglib/matroska/ebml/ebmlmasterelement.h +++ b/taglib/matroska/ebml/ebmlmasterelement.h @@ -44,11 +44,13 @@ namespace TagLib::EBML { offset_t getOffset() const { return offset; } bool read(File &file) override; ByteVector render() override; - void appendElement(Element *element) { elements.append(element); } - List::Iterator begin() { return elements.begin(); } - List::Iterator end() { return elements.end(); } - List::ConstIterator cbegin() const { return elements.cbegin(); } - List::ConstIterator cend() const { return elements.cend(); } + void appendElement(std::unique_ptr &&element); + std::list>::iterator begin() { return elements.begin(); } + std::list>::iterator end() { return elements.end(); } + std::list>::const_iterator begin() const { return elements.begin(); } + std::list>::const_iterator end() const { return elements.end(); } + std::list>::const_iterator cbegin() const { return elements.cbegin(); } + std::list>::const_iterator cend() const { return elements.cend(); } offset_t getPadding() const { return padding; } void setPadding(offset_t padding) { this->padding = padding; } offset_t getMinRenderSize() const { return minRenderSize; } @@ -58,7 +60,7 @@ namespace TagLib::EBML { offset_t offset; offset_t padding = 0; offset_t minRenderSize = 0; - List elements; + std::list> elements; }; } diff --git a/taglib/matroska/ebml/ebmlmkattachments.cpp b/taglib/matroska/ebml/ebmlmkattachments.cpp index 35c35700..ed8ab2b9 100644 --- a/taglib/matroska/ebml/ebmlmkattachments.cpp +++ b/taglib/matroska/ebml/ebmlmkattachments.cpp @@ -27,14 +27,14 @@ using namespace TagLib; -Matroska::Attachments *EBML::MkAttachments::parse() +std::unique_ptr EBML::MkAttachments::parse() { - auto attachments = new Matroska::Attachments(); + auto attachments = std::make_unique(); attachments->setOffset(offset); attachments->setSize(getSize()); - for(auto element : elements) { - if(element->getId() != ElementIDs::MkAttachedFile) + for(const auto &element : elements) { + if(element->getId() != Id::MkAttachedFile) continue; const String *filename = nullptr; @@ -42,19 +42,19 @@ Matroska::Attachments *EBML::MkAttachments::parse() const String *mediaType = nullptr; const ByteVector *data = nullptr; Matroska::AttachedFile::UID uid = 0; - auto attachedFile = static_cast(element); - for(auto attachedFileChild : *attachedFile) { + auto attachedFile = element_cast(element); + for(const auto &attachedFileChild : *attachedFile) { Id id = attachedFileChild->getId(); - if(id == ElementIDs::MkAttachedFileName) - filename = &(static_cast(attachedFileChild)->getValue()); - else if(id == ElementIDs::MkAttachedFileData) - data = &(static_cast(attachedFileChild)->getValue()); - else if(id == ElementIDs::MkAttachedFileDescription) - description = &(static_cast(attachedFileChild)->getValue()); - else if(id == ElementIDs::MkAttachedFileMediaType) - mediaType = &(static_cast(attachedFileChild)->getValue()); - else if(id == ElementIDs::MkAttachedFileUID) - uid = static_cast(attachedFileChild)->getValue(); + if(id == Id::MkAttachedFileName) + filename = &(element_cast(attachedFileChild)->getValue()); + else if(id == Id::MkAttachedFileData) + data = &(element_cast(attachedFileChild)->getValue()); + else if(id == Id::MkAttachedFileDescription) + description = &(element_cast(attachedFileChild)->getValue()); + else if(id == Id::MkAttachedFileMediaType) + mediaType = &(element_cast(attachedFileChild)->getValue()); + else if(id == Id::MkAttachedFileUID) + uid = element_cast(attachedFileChild)->getValue(); } if(!(filename && data)) continue; diff --git a/taglib/matroska/ebml/ebmlmkattachments.h b/taglib/matroska/ebml/ebmlmkattachments.h index 228493d5..02f27648 100644 --- a/taglib/matroska/ebml/ebmlmkattachments.h +++ b/taglib/matroska/ebml/ebmlmkattachments.h @@ -35,14 +35,18 @@ namespace TagLib { { public: MkAttachments(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(ElementIDs::MkAttachments, sizeLength, dataSize, offset) + MasterElement(Id::MkAttachments, sizeLength, dataSize, offset) + { + } + MkAttachments(Id, int sizeLength, offset_t dataSize, offset_t offset) : + MasterElement(Id::MkAttachments, sizeLength, dataSize, offset) { } MkAttachments() : - MasterElement(ElementIDs::MkAttachments, 0, 0, 0) + MasterElement(Id::MkAttachments, 0, 0, 0) { } - Matroska::Attachments *parse(); + std::unique_ptr parse(); }; } } diff --git a/taglib/matroska/ebml/ebmlmkcues.cpp b/taglib/matroska/ebml/ebmlmkcues.cpp index c0d1bc10..a97f7dd2 100644 --- a/taglib/matroska/ebml/ebmlmkcues.cpp +++ b/taglib/matroska/ebml/ebmlmkcues.cpp @@ -29,48 +29,48 @@ Matroska::Cues *EBML::MkCues::parse() auto cues = new Matroska::Cues(); cues->setOffset(offset); cues->setSize(getSize()); - cues->setID(id); + cues->setID(static_cast(id)); - for(auto cuesChild : elements) { - if(cuesChild->getId() != ElementIDs::MkCuePoint) + for(const auto &cuesChild : elements) { + if(cuesChild->getId() != Id::MkCuePoint) continue; - auto cuePointElement = static_cast(cuesChild); - auto cuePoint = new Matroska::CuePoint(); + auto cuePointElement = element_cast(cuesChild); + auto cuePoint = std::make_unique(); - for(auto cuePointChild : *cuePointElement) { + for(const auto &cuePointChild : *cuePointElement) { Id id = cuePointChild->getId(); - if(id == ElementIDs::MkCueTime) - cuePoint->setTime(static_cast(cuePointChild)->getValue()); - else if(id == ElementIDs::MkCueTrackPositions) { - auto cueTrack = new Matroska::CueTrack(); - auto cueTrackElement = static_cast(cuePointChild); - for(auto cueTrackChild : *cueTrackElement) { + if(id == Id::MkCueTime) + cuePoint->setTime(element_cast(cuePointChild)->getValue()); + else if(id == Id::MkCueTrackPositions) { + auto cueTrack = std::make_unique(); + auto cueTrackElement = element_cast(cuePointChild); + for(const auto &cueTrackChild : *cueTrackElement) { Id trackId = cueTrackChild->getId(); - if(trackId == ElementIDs::MkCueTrack) - cueTrack->setTrackNumber(static_cast(cueTrackChild)->getValue()); - else if(trackId == ElementIDs::MkCueClusterPosition) - cueTrack->setClusterPosition(static_cast(cueTrackChild)->getValue()); - else if(trackId == ElementIDs::MkCueRelativePosition) - cueTrack->setRelativePosition(static_cast(cueTrackChild)->getValue()); - else if(trackId == ElementIDs::MkCueDuration) - cueTrack->setDuration(static_cast(cueTrackChild)->getValue()); - else if(trackId == ElementIDs::MkCueBlockNumber) - cueTrack->setBlockNumber(static_cast(cueTrackChild)->getValue()); - else if(trackId == ElementIDs::MkCueCodecState) - cueTrack->setCodecState(static_cast(cueTrackChild)->getValue()); - else if(trackId == ElementIDs::MkCueReference) { - auto cueReference = static_cast(cueTrackChild); - for(auto cueReferenceChild : *cueReference) { - if(cueReferenceChild->getId() != ElementIDs::MkCueReference) + if(trackId == Id::MkCueTrack) + cueTrack->setTrackNumber(element_cast(cueTrackChild)->getValue()); + else if(trackId == Id::MkCueClusterPosition) + cueTrack->setClusterPosition(element_cast(cueTrackChild)->getValue()); + else if(trackId == Id::MkCueRelativePosition) + cueTrack->setRelativePosition(element_cast(cueTrackChild)->getValue()); + else if(trackId == Id::MkCueDuration) + cueTrack->setDuration(element_cast(cueTrackChild)->getValue()); + else if(trackId == Id::MkCueBlockNumber) + cueTrack->setBlockNumber(element_cast(cueTrackChild)->getValue()); + else if(trackId == Id::MkCueCodecState) + cueTrack->setCodecState(element_cast(cueTrackChild)->getValue()); + else if(trackId == Id::MkCueReference) { + auto cueReference = element_cast(cueTrackChild); + for(const auto &cueReferenceChild : *cueReference) { + if(cueReferenceChild->getId() != Id::MkCueRefTime) continue; - cueTrack->addReferenceTime(static_cast(cueReferenceChild)->getValue()); + cueTrack->addReferenceTime(element_cast(cueReferenceChild)->getValue()); } } } - cuePoint->addCueTrack(cueTrack); + cuePoint->addCueTrack(std::move(cueTrack)); } } - cues->addCuePoint(cuePoint); + cues->addCuePoint(std::move(cuePoint)); } return cues; } diff --git a/taglib/matroska/ebml/ebmlmkcues.h b/taglib/matroska/ebml/ebmlmkcues.h index 2d31826e..79530513 100644 --- a/taglib/matroska/ebml/ebmlmkcues.h +++ b/taglib/matroska/ebml/ebmlmkcues.h @@ -36,11 +36,11 @@ namespace TagLib { { public: MkCues(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(ElementIDs::MkCues, sizeLength, dataSize, offset) + MasterElement(Id::MkCues, sizeLength, dataSize, offset) { } MkCues() : - MasterElement(ElementIDs::MkCues, 0, 0, 0) + MasterElement(Id::MkCues, 0, 0, 0) { } diff --git a/taglib/matroska/ebml/ebmlmkinfo.cpp b/taglib/matroska/ebml/ebmlmkinfo.cpp index feba7c01..c6c48f3c 100644 --- a/taglib/matroska/ebml/ebmlmkinfo.cpp +++ b/taglib/matroska/ebml/ebmlmkinfo.cpp @@ -38,13 +38,13 @@ void EBML::MkInfo::parse(Matroska::Properties *properties) unsigned long long timestampScale = 1000000; double duration = 0.0; - for(auto element : elements) { + for(const auto &element : elements) { Id id = element->getId(); - if (id == ElementIDs::MkTimestampScale) { - timestampScale = static_cast(element)->getValue(); + if (id == Id::MkTimestampScale) { + timestampScale = element_cast(element)->getValue(); } - else if (id == ElementIDs::MkDuration) { - duration = static_cast(element)->getValueAsDouble(); + else if (id == Id::MkDuration) { + duration = element_cast(element)->getValueAsDouble(); } } diff --git a/taglib/matroska/ebml/ebmlmkinfo.h b/taglib/matroska/ebml/ebmlmkinfo.h index 479c7056..672ea217 100644 --- a/taglib/matroska/ebml/ebmlmkinfo.h +++ b/taglib/matroska/ebml/ebmlmkinfo.h @@ -40,11 +40,15 @@ namespace TagLib { { public: MkInfo(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(ElementIDs::MkInfo, sizeLength, dataSize, offset) + MasterElement(Id::MkInfo, sizeLength, dataSize, offset) + { + } + MkInfo(Id, int sizeLength, offset_t dataSize, offset_t offset) : + MasterElement(Id::MkInfo, sizeLength, dataSize, offset) { } MkInfo() : - MasterElement(ElementIDs::MkInfo, 0, 0, 0) + MasterElement(Id::MkInfo, 0, 0, 0) { } void parse(Matroska::Properties * properties); diff --git a/taglib/matroska/ebml/ebmlmkseekhead.cpp b/taglib/matroska/ebml/ebmlmkseekhead.cpp index 477d30f2..20ae34bf 100644 --- a/taglib/matroska/ebml/ebmlmkseekhead.cpp +++ b/taglib/matroska/ebml/ebmlmkseekhead.cpp @@ -31,21 +31,21 @@ std::unique_ptr EBML::MkSeekHead::parse() seekHead->setOffset(offset); seekHead->setSize(getSize() + padding); - for(auto element : elements) { - if(element->getId() != ElementIDs::MkSeek) + for(const auto &element : elements) { + if(element->getId() != Id::MkSeek) continue; - auto seekElement = static_cast(element); + auto seekElement = element_cast(element); Matroska::Element::ID entryId = 0; offset_t offset = 0; - for(auto seekElementChild : *seekElement) { + for(const auto &seekElementChild : *seekElement) { Id id = seekElementChild->getId(); - if(id == ElementIDs::MkSeekID && !entryId) { - auto data = static_cast(seekElementChild)->getValue(); + if(id == Id::MkSeekID && !entryId) { + auto data = element_cast(seekElementChild)->getValue(); if(data.size() == 4) entryId = data.toUInt(true); } - else if(id == ElementIDs::MkSeekPosition && !offset) - offset = static_cast(seekElementChild)->getValue(); + else if(id == Id::MkSeekPosition && !offset) + offset = element_cast(seekElementChild)->getValue(); } if(entryId && offset) seekHead->addEntry(entryId, offset); diff --git a/taglib/matroska/ebml/ebmlmkseekhead.h b/taglib/matroska/ebml/ebmlmkseekhead.h index bf6b8edf..de405c6a 100644 --- a/taglib/matroska/ebml/ebmlmkseekhead.h +++ b/taglib/matroska/ebml/ebmlmkseekhead.h @@ -34,15 +34,19 @@ namespace TagLib { { public: MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(ElementIDs::MkSeekHead, sizeLength, dataSize, offset) + MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset) + { + } + MkSeekHead(Id, int sizeLength, offset_t dataSize, offset_t offset) : + MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset) { } MkSeekHead() : - MasterElement(ElementIDs::MkSeekHead, 0, 0, 0) + MasterElement(Id::MkSeekHead, 0, 0, 0) { } - Matroska::SeekHead *parse(); + std::unique_ptr parse(); }; } } diff --git a/taglib/matroska/ebml/ebmlmksegment.cpp b/taglib/matroska/ebml/ebmlmksegment.cpp index 0de3d5e8..887ca5d9 100644 --- a/taglib/matroska/ebml/ebmlmksegment.cpp +++ b/taglib/matroska/ebml/ebmlmksegment.cpp @@ -33,81 +33,73 @@ using namespace TagLib; -EBML::MkSegment::~MkSegment() -{ - delete tags; - delete attachments; - delete seekHead; - delete info; - delete tracks; -} +EBML::MkSegment::~MkSegment() = default; bool EBML::MkSegment::read(File &file) { offset_t maxOffset = file.tell() + dataSize; - Element *element = nullptr; + std::unique_ptr element; int i = 0; int seekHeadIndex = -1; while((element = findNextElement(file, maxOffset))) { Id id = element->getId(); - if(id == ElementIDs::MkSeekHead) { + if(id == Id::MkSeekHead) { seekHeadIndex = i; - seekHead = static_cast(element); + seekHead = element_cast(std::move(element)); if(!seekHead->read(file)) return false; } - else if(id == ElementIDs::MkInfo) { - info = static_cast(element); + else if(id == Id::MkInfo) { + info = element_cast(std::move(element)); if(!info->read(file)) return false; } - else if(id == ElementIDs::MkTracks) { - tracks = static_cast(element); + else if(id == Id::MkTracks) { + tracks = element_cast(std::move(element)); if(!tracks->read(file)) return false; } - else if(id == ElementIDs::MkTags) { - tags = static_cast(element); + else if(id == Id::MkTags) { + tags = element_cast(std::move(element)); if(!tags->read(file)) return false; } - else if(id == ElementIDs::MkAttachments) { - attachments = static_cast(element); + else if(id == Id::MkAttachments) { + attachments = element_cast(std::move(element)); if(!attachments->read(file)) return false; } else { - if(id == ElementIDs::VoidElement + if(id == Id::VoidElement && seekHead && seekHeadIndex == i - 1) seekHead->setPadding(element->getSize()); element->skipData(file); - delete element; } i++; } return true; } -Matroska::Tag *EBML::MkSegment::parseTag() +std::unique_ptr EBML::MkSegment::parseTag() { return tags ? tags->parse() : nullptr; } -Matroska::Attachments *EBML::MkSegment::parseAttachments() +std::unique_ptr EBML::MkSegment::parseAttachments() { return attachments ? attachments->parse() : nullptr; } -Matroska::SeekHead *EBML::MkSegment::parseSeekHead() +std::unique_ptr EBML::MkSegment::parseSeekHead() { return seekHead ? seekHead->parse() : nullptr; } -Matroska::Segment *EBML::MkSegment::parseSegment() +std::unique_ptr EBML::MkSegment::parseSegment() { - return new Matroska::Segment(sizeLength, dataSize, offset + idSize(id)); + return std::make_unique(sizeLength, dataSize, offset + idSize(id)); } void EBML::MkSegment::parseInfo(Matroska::Properties *properties) diff --git a/taglib/matroska/ebml/ebmlmksegment.h b/taglib/matroska/ebml/ebmlmksegment.h index 15ab7db3..e913f36c 100644 --- a/taglib/matroska/ebml/ebmlmksegment.h +++ b/taglib/matroska/ebml/ebmlmksegment.h @@ -23,6 +23,9 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlmasterelement.h" +#include "ebmlmktags.h" +#include "ebmlmkattachments.h" +#include "ebmlmkseekhead.h" #include "ebmlmkinfo.h" #include "ebmlmktracks.h" #include "taglib.h" @@ -35,31 +38,32 @@ namespace TagLib { class Segment; } namespace EBML { - class MkTags; - class MkAttachments; - class MkSeekHead; class MkSegment : public MasterElement { public: MkSegment(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(ElementIDs::MkSegment, sizeLength, dataSize, offset) + MasterElement(Id::MkSegment, sizeLength, dataSize, offset) + { + } + MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset) : + MasterElement(Id::MkSegment, sizeLength, dataSize, offset) { } ~MkSegment() override; bool read(File &file) override; - Matroska::Tag *parseTag(); - Matroska::Attachments *parseAttachments(); - Matroska::SeekHead *parseSeekHead(); - Matroska::Segment *parseSegment(); + std::unique_ptr parseTag(); + std::unique_ptr parseAttachments(); + std::unique_ptr parseSeekHead(); + std::unique_ptr parseSegment(); void parseInfo(Matroska::Properties *properties); void parseTracks(Matroska::Properties *properties); private: - MkTags *tags = nullptr; - MkAttachments *attachments = nullptr; - MkSeekHead *seekHead = nullptr; - MkInfo *info = nullptr; - MkTracks *tracks = nullptr; + std::unique_ptr tags; + std::unique_ptr attachments; + std::unique_ptr seekHead; + std::unique_ptr info; + std::unique_ptr tracks; }; } } diff --git a/taglib/matroska/ebml/ebmlmktags.cpp b/taglib/matroska/ebml/ebmlmktags.cpp index d594797e..a7dd5709 100644 --- a/taglib/matroska/ebml/ebmlmktags.cpp +++ b/taglib/matroska/ebml/ebmlmktags.cpp @@ -28,39 +28,39 @@ using namespace TagLib; -Matroska::Tag *EBML::MkTags::parse() +std::unique_ptr EBML::MkTags::parse() { - auto mTag = new Matroska::Tag(); + auto mTag = std::make_unique(); mTag->setOffset(offset); mTag->setSize(getSize()); - mTag->setID(id); + mTag->setID(static_cast(id)); // Loop through each element - for(auto tagsChild : elements) { - if(tagsChild->getId() != ElementIDs::MkTag) + for(const auto &tagsChild : elements) { + if(tagsChild->getId() != Id::MkTag) continue; - auto tag = static_cast(tagsChild); - List simpleTags; - MasterElement *targets = nullptr; + auto tag = element_cast(tagsChild); + List simpleTags; + const MasterElement *targets = nullptr; // Identify the element and the elements - for(auto tagChild : *tag) { + for(const auto &tagChild : *tag) { Id tagChildId = tagChild->getId(); - if(!targets && tagChildId == ElementIDs::MkTagTargets) - targets = static_cast(tagChild); - else if(tagChildId == ElementIDs::MkSimpleTag) - simpleTags.append(static_cast(tagChild)); + if(!targets && tagChildId == Id::MkTagTargets) + targets = element_cast(tagChild); + else if(tagChildId == Id::MkSimpleTag) + simpleTags.append(element_cast(tagChild)); } // Parse the element Matroska::SimpleTag::TargetTypeValue targetTypeValue = Matroska::SimpleTag::TargetTypeValue::None; if(targets) { - for(auto targetsChild : *targets) { + for(const auto &targetsChild : *targets) { Id id = targetsChild->getId(); - if(id == ElementIDs::MkTagTargetTypeValue + if(id == Id::MkTagTargetTypeValue && targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None) { targetTypeValue = static_cast( - static_cast(targetsChild)->getValue() + element_cast(targetsChild)->getValue() ); } } @@ -74,18 +74,18 @@ Matroska::Tag *EBML::MkTags::parse() const String *language = nullptr; bool defaultLanguageFlag = true; - for(auto simpleTagChild : *simpleTag) { + for(const auto &simpleTagChild : *simpleTag) { Id id = simpleTagChild->getId(); - if(id == ElementIDs::MkTagName && !tagName) - tagName = &(static_cast(simpleTagChild)->getValue()); - else if(id == ElementIDs::MkTagString && !tagValueString) - tagValueString = &(static_cast(simpleTagChild)->getValue()); - else if(id == ElementIDs::MkTagBinary && !tagValueBinary) - tagValueBinary = &(static_cast(simpleTagChild)->getValue()); - else if(id == ElementIDs::MkTagsTagLanguage && !language) - language = &(static_cast(simpleTagChild)->getValue()); - else if(id == ElementIDs::MkTagsLanguageDefault) - defaultLanguageFlag = static_cast(simpleTagChild)->getValue() ? true : false; + if(id == Id::MkTagName && !tagName) + tagName = &(element_cast(simpleTagChild)->getValue()); + else if(id == Id::MkTagString && !tagValueString) + tagValueString = &(element_cast(simpleTagChild)->getValue()); + else if(id == Id::MkTagBinary && !tagValueBinary) + tagValueBinary = &(element_cast(simpleTagChild)->getValue()); + else if(id == Id::MkTagsTagLanguage && !language) + language = &(element_cast(simpleTagChild)->getValue()); + else if(id == Id::MkTagsLanguageDefault) + defaultLanguageFlag = element_cast(simpleTagChild)->getValue() ? true : false; } if(!tagName || (tagValueString && tagValueBinary) || (!tagValueString && !tagValueBinary)) continue; diff --git a/taglib/matroska/ebml/ebmlmktags.h b/taglib/matroska/ebml/ebmlmktags.h index 1f00e1e2..dea4e2eb 100644 --- a/taglib/matroska/ebml/ebmlmktags.h +++ b/taglib/matroska/ebml/ebmlmktags.h @@ -36,15 +36,19 @@ namespace TagLib { { public: MkTags(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(ElementIDs::MkTags, sizeLength, dataSize, offset) + MasterElement(Id::MkTags, sizeLength, dataSize, offset) + { + } + MkTags(Id, int sizeLength, offset_t dataSize, offset_t offset) : + MasterElement(Id::MkTags, sizeLength, dataSize, offset) { } MkTags() : - MasterElement(ElementIDs::MkTags, 0, 0, 0) + MasterElement(Id::MkTags, 0, 0, 0) { } - Matroska::Tag *parse(); + std::unique_ptr parse(); }; } } diff --git a/taglib/matroska/ebml/ebmlmktracks.cpp b/taglib/matroska/ebml/ebmlmktracks.cpp index 552b07c3..febdaad2 100644 --- a/taglib/matroska/ebml/ebmlmktracks.cpp +++ b/taglib/matroska/ebml/ebmlmktracks.cpp @@ -36,29 +36,29 @@ void EBML::MkTracks::parse(Matroska::Properties *properties) if(!properties) return; - for(auto element : elements) { - if(element->getId() != ElementIDs::MkTrackEntry) + for(const auto &element : elements) { + if(element->getId() != Id::MkTrackEntry) continue; String codecId; double samplingFrequency = 0.0; unsigned long long bitDepth = 0; unsigned long long channels = 0; - auto trackEntry = static_cast(element); - for(auto trackEntryChild : *trackEntry) { + auto trackEntry = element_cast(element); + for(const auto &trackEntryChild : *trackEntry) { Id trackEntryChildId = trackEntryChild->getId(); - if(trackEntryChildId == ElementIDs::MkCodecID) - codecId = static_cast(trackEntryChild)->getValue(); - else if(trackEntryChildId == ElementIDs::MkAudio) { - auto audio = static_cast(trackEntryChild); - for(auto audioChild : *audio) { + if(trackEntryChildId == Id::MkCodecID) + codecId = element_cast(trackEntryChild)->getValue(); + else if(trackEntryChildId == Id::MkAudio) { + auto audio = element_cast(trackEntryChild); + for(const auto &audioChild : *audio) { Id audioChildId = audioChild->getId(); - if(audioChildId == ElementIDs::MkSamplingFrequency) - samplingFrequency = static_cast(audioChild)->getValueAsDouble(); - else if(audioChildId == ElementIDs::MkBitDepth) - bitDepth = static_cast(audioChild)->getValue(); - else if(audioChildId == ElementIDs::MkChannels) - channels = static_cast(audioChild)->getValue(); + if(audioChildId == Id::MkSamplingFrequency) + samplingFrequency = element_cast(audioChild)->getValueAsDouble(); + else if(audioChildId == Id::MkBitDepth) + bitDepth = element_cast(audioChild)->getValue(); + else if(audioChildId == Id::MkChannels) + channels = element_cast(audioChild)->getValue(); } } } diff --git a/taglib/matroska/ebml/ebmlmktracks.h b/taglib/matroska/ebml/ebmlmktracks.h index 53754fb7..1f8ebb2f 100644 --- a/taglib/matroska/ebml/ebmlmktracks.h +++ b/taglib/matroska/ebml/ebmlmktracks.h @@ -40,11 +40,15 @@ namespace TagLib { { public: MkTracks(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(ElementIDs::MkTracks, sizeLength, dataSize, offset) + MasterElement(Id::MkTracks, sizeLength, dataSize, offset) + { + } + MkTracks(Id, int sizeLength, offset_t dataSize, offset_t offset) : + MasterElement(Id::MkTracks, sizeLength, dataSize, offset) { } MkTracks() : - MasterElement(ElementIDs::MkTracks, 0, 0, 0) + MasterElement(Id::MkTracks, 0, 0, 0) { } void parse(Matroska::Properties *properties); diff --git a/taglib/matroska/ebml/ebmlstringelement.h b/taglib/matroska/ebml/ebmlstringelement.h index afeb1ef3..258eb553 100644 --- a/taglib/matroska/ebml/ebmlstringelement.h +++ b/taglib/matroska/ebml/ebmlstringelement.h @@ -37,6 +37,10 @@ namespace TagLib { Element(id, sizeLength, dataSize) { } + StringElement(Id id, int sizeLength, offset_t dataSize, offset_t) : + Element(id, sizeLength, dataSize) + { + } explicit StringElement(Id id) : Element(id, 0, 0) diff --git a/taglib/matroska/ebml/ebmluintelement.h b/taglib/matroska/ebml/ebmluintelement.h index 581a19ce..efd6f32f 100644 --- a/taglib/matroska/ebml/ebmluintelement.h +++ b/taglib/matroska/ebml/ebmluintelement.h @@ -35,6 +35,10 @@ namespace TagLib { Element(id, sizeLength, dataSize) { } + UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t) : + Element(id, sizeLength, dataSize) + { + } explicit UIntElement(Id id) : UIntElement(id, 0, 0) diff --git a/taglib/matroska/ebml/ebmlutils.cpp b/taglib/matroska/ebml/ebmlutils.cpp index 2793fb23..149109a1 100644 --- a/taglib/matroska/ebml/ebmlutils.cpp +++ b/taglib/matroska/ebml/ebmlutils.cpp @@ -30,21 +30,20 @@ using namespace TagLib; -EBML::Element *EBML::findElement(File &file, Element::Id id, offset_t maxOffset) +std::unique_ptr EBML::findElement(File &file, Element::Id id, offset_t maxOffset) { - Element *element = nullptr; + std::unique_ptr element; while(file.tell() < maxOffset) { element = Element::factory(file); if(!element || element->getId() == id) return element; element->skipData(file); - delete element; - element = nullptr; + element.reset(); } return element; } -EBML::Element *EBML::findNextElement(File &file, offset_t maxOffset) +std::unique_ptr EBML::findNextElement(File &file, offset_t maxOffset) { return file.tell() < maxOffset ? Element::factory(file) : nullptr; } diff --git a/taglib/matroska/ebml/ebmlutils.h b/taglib/matroska/ebml/ebmlutils.h index 9644cfba..c418d632 100644 --- a/taglib/matroska/ebml/ebmlutils.h +++ b/taglib/matroska/ebml/ebmlutils.h @@ -59,8 +59,8 @@ namespace TagLib { std::pair readVINT(File &file); template std::pair parseVINT(const ByteVector &buffer); - Element *findElement(File &file, Element::Id id, offset_t maxOffset); - Element *findNextElement(File &file, offset_t maxOffset); + std::unique_ptr findElement(File &file, Element::Id id, offset_t maxOffset); + std::unique_ptr findNextElement(File &file, offset_t maxOffset); ByteVector renderVINT(uint64_t number, int minSizeLength); unsigned long long randomUID(); @@ -82,11 +82,12 @@ namespace TagLib { constexpr int idSize(Element::Id id) { - if(id <= 0xFF) + auto uintId = static_cast(id); + if(uintId <= 0xFF) return 1; - else if(id <= 0xFFFF) + else if(uintId <= 0xFFFF) return 2; - else if(id <= 0xFFFFFF) + else if(uintId <= 0xFFFFFF) return 3; else return 4; diff --git a/taglib/matroska/ebml/ebmlvoidelement.h b/taglib/matroska/ebml/ebmlvoidelement.h index 8e928e04..9b6864ac 100644 --- a/taglib/matroska/ebml/ebmlvoidelement.h +++ b/taglib/matroska/ebml/ebmlvoidelement.h @@ -33,10 +33,13 @@ namespace TagLib { { public: VoidElement(int sizeLength, offset_t dataSize) : - Element(ElementIDs::VoidElement, sizeLength, dataSize) + Element(Id::VoidElement, sizeLength, dataSize) + {} + VoidElement(Id, int sizeLength, offset_t dataSize, offset_t) : + Element(Id::VoidElement, sizeLength, dataSize) {} VoidElement() : - Element(ElementIDs::VoidElement, 0, 0) + Element(Id::VoidElement, 0, 0) {} ByteVector render() override; offset_t getTargetSize() const; diff --git a/taglib/matroska/matroskaattachments.cpp b/taglib/matroska/matroskaattachments.cpp index 1dab3c1d..8fb34700 100644 --- a/taglib/matroska/matroskaattachments.cpp +++ b/taglib/matroska/matroskaattachments.cpp @@ -1,5 +1,5 @@ -#include #include "matroskaattachments.h" +#include #include "matroskaattachedfile.h" #include "ebmlmkattachments.h" #include "ebmlmasterelement.h" @@ -22,7 +22,7 @@ public: }; Matroska::Attachments::Attachments() : - Element(ElementIDs::MkAttachments), + Element(static_cast(EBML::Element::Id::MkAttachments)), d(std::make_unique()) { d->files.setAutoDelete(true); @@ -57,40 +57,40 @@ bool Matroska::Attachments::render() { EBML::MkAttachments attachments; for(const auto attachedFile : d->files) { - auto attachedFileElement = new EBML::MasterElement(EBML::ElementIDs::MkAttachedFile); + auto attachedFileElement = EBML::make_unique_element(); // Filename - auto fileNameElement = new EBML::UTF8StringElement(EBML::ElementIDs::MkAttachedFileName); + auto fileNameElement = EBML::make_unique_element(); fileNameElement->setValue(attachedFile->fileName()); - attachedFileElement->appendElement(fileNameElement); + attachedFileElement->appendElement(std::move(fileNameElement)); // Media/MIME type - auto mediaTypeElement = new EBML::Latin1StringElement(EBML::ElementIDs::MkAttachedFileMediaType); + auto mediaTypeElement = EBML::make_unique_element(); mediaTypeElement->setValue(attachedFile->mediaType()); - attachedFileElement->appendElement(mediaTypeElement); + attachedFileElement->appendElement(std::move(mediaTypeElement)); // Description const String &description = attachedFile->description(); if(!description.isEmpty()) { - auto descriptionElement = new EBML::UTF8StringElement(EBML::ElementIDs::MkAttachedFileDescription); + auto descriptionElement = EBML::make_unique_element(); descriptionElement->setValue(description); - attachedFileElement->appendElement(descriptionElement); + attachedFileElement->appendElement(std::move(descriptionElement)); } // Data - auto dataElement = new EBML::BinaryElement(EBML::ElementIDs::MkAttachedFileData); + auto dataElement = EBML::make_unique_element(); dataElement->setValue(attachedFile->data()); - attachedFileElement->appendElement(dataElement); + attachedFileElement->appendElement(std::move(dataElement)); // UID - auto uidElement = new EBML::UIntElement(EBML::ElementIDs::MkAttachedFileUID); + auto uidElement = EBML::make_unique_element(); AttachedFile::UID uid = attachedFile->uid(); if(!uid) uid = EBML::randomUID(); uidElement->setValue(uid); - attachedFileElement->appendElement(uidElement); + attachedFileElement->appendElement(std::move(uidElement)); - attachments.appendElement(attachedFileElement); + attachments.appendElement(std::move(attachedFileElement)); } auto beforeSize = size(); diff --git a/taglib/matroska/matroskacues.cpp b/taglib/matroska/matroskacues.cpp index 06d6e288..a064ae51 100644 --- a/taglib/matroska/matroskacues.cpp +++ b/taglib/matroska/matroskacues.cpp @@ -30,48 +30,47 @@ using namespace TagLib; Matroska::Cues::Cues() : - Element(ElementIDs::MkCues) + Element(static_cast(EBML::Element::Id::MkCues)) { - cuePoints.setAutoDelete(true); } ByteVector Matroska::Cues::renderInternal() { EBML::MkCues cues; - for(auto &cuePoint : cuePoints) { - auto cuePointElement = new EBML::MasterElement(EBML::ElementIDs::MkCuePoint); - auto timestamp = new EBML::UIntElement(EBML::ElementIDs::MkCueTime); + for(const auto &cuePoint : cuePoints) { + auto cuePointElement = EBML::make_unique_element(); + auto timestamp = EBML::make_unique_element(); timestamp->setValue(cuePoint->getTime()); - cuePointElement->appendElement(timestamp); + cuePointElement->appendElement(std::move(timestamp)); - auto trackList = cuePoint->cueTrackList(); - for(auto &cueTrack : trackList) { - auto cueTrackElement = new EBML::MasterElement(EBML::ElementIDs::MkCueTrackPositions); + const auto &trackList = cuePoint->cueTrackList(); + for(const auto &cueTrack : trackList) { + auto cueTrackElement = EBML::make_unique_element(); // Track number - auto trackNumber = new EBML::UIntElement(EBML::ElementIDs::MkCueTrack); + auto trackNumber = EBML::make_unique_element(); trackNumber->setValue(cueTrack->getTrackNumber()); - cueTrackElement->appendElement(trackNumber); + cueTrackElement->appendElement(std::move(trackNumber)); // Cluster position - auto clusterPosition = new EBML::UIntElement(EBML::ElementIDs::MkCueClusterPosition); + auto clusterPosition = EBML::make_unique_element(); clusterPosition->setValue(cueTrack->getClusterPosition()); - cueTrackElement->appendElement(clusterPosition); + cueTrackElement->appendElement(std::move(clusterPosition)); // Todo - other elements // Reference times auto referenceTimes = cueTrack->referenceTimes(); if(!referenceTimes.isEmpty()) { - auto cueReference = new EBML::MasterElement(EBML::ElementIDs::MkCueReference); + auto cueReference = EBML::make_unique_element(); for(auto reference : referenceTimes) { - auto refTime = new EBML::UIntElement(EBML::ElementIDs::MkCueRefTime); + auto refTime = EBML::make_unique_element(); refTime->setValue(reference); - cueReference->appendElement(refTime); + cueReference->appendElement(std::move(refTime)); } - cueTrackElement->appendElement(cueReference); + cueTrackElement->appendElement(std::move(cueReference)); } - cuePointElement->appendElement(cueTrackElement); + cuePointElement->appendElement(std::move(cueTrackElement)); } } return cues.render(); @@ -90,38 +89,47 @@ bool Matroska::Cues::render() bool Matroska::Cues::sizeChanged(Element &caller, offset_t delta) { offset_t offset = caller.offset(); - for(auto cuePoint : cuePoints) + for(auto &cuePoint : cuePoints) needsRender |= cuePoint->adjustOffset(offset, delta); return true; } bool Matroska::Cues::isValid(TagLib::File &file, offset_t segmentDataOffset) const { - for(const auto cuePoint : cuePoints) { + for(const auto &cuePoint : cuePoints) { if(!cuePoint->isValid(file, segmentDataOffset)) return false; } return true; } +void Matroska::Cues::addCuePoint(std::unique_ptr &&cuePoint) +{ + cuePoints.push_back(std::move(cuePoint)); +} + Matroska::CuePoint::CuePoint() { - cueTracks.setAutoDelete(true); } bool Matroska::CuePoint::isValid(TagLib::File &file, offset_t segmentDataOffset) const { - for(const auto track : cueTracks) { + for(const auto &track : cueTracks) { if(!track->isValid(file, segmentDataOffset)) return false; } return true; } +void Matroska::CuePoint::addCueTrack(std::unique_ptr &&cueTrack) +{ + cueTracks.push_back(std::move(cueTrack)); +} + bool Matroska::CuePoint::adjustOffset(offset_t offset, offset_t delta) { bool ret = false; - for(auto cueTrack : cueTracks) + for(auto &cueTrack : cueTracks) ret |= cueTrack->adjustOffset(offset, delta); return ret; @@ -138,13 +146,13 @@ bool Matroska::CueTrack::isValid(TagLib::File &file, offset_t segmentDataOffset) return false; } file.seek(segmentDataOffset + clusterPosition); - if(EBML::Element::readId(file) != EBML::ElementIDs::MkCluster) { + if(EBML::Element::readId(file) != static_cast(EBML::Element::Id::MkCluster)) { debug("No cluster found at position"); return false; } if(codecState) { file.seek(segmentDataOffset + codecState); - if(EBML::Element::readId(file) != EBML::ElementIDs::MkCodecState) { + if(EBML::Element::readId(file) != static_cast(EBML::Element::Id::MkCodecState)) { debug("No codec state found at position"); return false; } diff --git a/taglib/matroska/matroskacues.h b/taglib/matroska/matroskacues.h index 109c90ce..61539413 100644 --- a/taglib/matroska/matroskacues.h +++ b/taglib/matroska/matroskacues.h @@ -37,12 +37,12 @@ namespace TagLib { class Cues : public Element { public: - using CuePointList = List; + using CuePointList = std::list>; Cues(); ~Cues() override = default; bool isValid(File &file, offset_t segmentDataOffset) const; - void addCuePoint(CuePoint *cuePoint) { cuePoints.append(cuePoint); } - CuePointList cuePointList() { return cuePoints; } + void addCuePoint(std::unique_ptr &&cuePoint); + const CuePointList &cuePointList() { return cuePoints; } bool sizeChanged(Element &caller, offset_t delta) override; bool render() override; @@ -51,19 +51,19 @@ namespace TagLib { ByteVector renderInternal(); bool needsRender = false; - List cuePoints; + CuePointList cuePoints; }; class CuePoint { public: - using CueTrackList = List; + using CueTrackList = std::list>; using Time = unsigned long long; CuePoint(); ~CuePoint() = default; bool isValid(File &file, offset_t segmentDataOffset) const; - void addCueTrack(CueTrack *cueTrack) { cueTracks.append(cueTrack); } - CueTrackList cueTrackList() const { return cueTracks; } + void addCueTrack(std::unique_ptr &&cueTrack); + const CueTrackList &cueTrackList() const { return cueTracks; } void setTime(Time time) { this->time = time; } Time getTime() const { return time; } bool adjustOffset(offset_t offset, offset_t delta); @@ -93,7 +93,7 @@ namespace TagLib { void setDuration(unsigned long long duration) { this->duration = duration; } unsigned long long getDuration() const { return duration; } void addReferenceTime(unsigned long long refTime) { refTimes.append(refTime); } - ReferenceTimeList referenceTimes() const { return refTimes; } + const ReferenceTimeList &referenceTimes() const { return refTimes; } bool adjustOffset(offset_t offset, offset_t delta); private: diff --git a/taglib/matroska/matroskaelement.h b/taglib/matroska/matroskaelement.h index ed11584d..c5c3aec0 100644 --- a/taglib/matroska/matroskaelement.h +++ b/taglib/matroska/matroskaelement.h @@ -65,13 +65,6 @@ namespace TagLib { TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE std::unique_ptr e; }; - namespace ElementIDs { - inline constexpr Element::ID MkTags = 0x1254C367; - inline constexpr Element::ID MkAttachments = 0x1941A469; - inline constexpr Element::ID MkSeekHead = 0x114D9B74; - inline constexpr Element::ID MkSegment = 0x18538067; - inline constexpr Element::ID MkCues = 0x1C53BB6B; - } } } diff --git a/taglib/matroska/matroskafile.cpp b/taglib/matroska/matroskafile.cpp index 7e9e19f5..9651a1a2 100644 --- a/taglib/matroska/matroskafile.cpp +++ b/taglib/matroska/matroskafile.cpp @@ -39,20 +39,15 @@ class Matroska::File::FilePrivate { public: FilePrivate() = default; - ~FilePrivate() - { - delete tag; - delete attachments; - delete seekHead; - delete segment; - } + ~FilePrivate() = default; FilePrivate(const FilePrivate &) = delete; FilePrivate &operator=(const FilePrivate &) = delete; - Tag *tag = nullptr; - Attachments *attachments = nullptr; - SeekHead *seekHead = nullptr; - Segment *segment = nullptr; + + std::unique_ptr tag; + std::unique_ptr attachments; + std::unique_ptr seekHead; + std::unique_ptr segment; std::unique_ptr properties; }; @@ -110,24 +105,16 @@ Tag *Matroska::File::tag() const Matroska::Tag *Matroska::File::tag(bool create) const { - if(d->tag) - return d->tag; - else { - if(create) - d->tag = new Tag(); - return d->tag; - } + if(!d->tag && create) + d->tag = std::make_unique(); + return d->tag.get(); } Matroska::Attachments *Matroska::File::attachments(bool create) const { - if(d->attachments) - return d->attachments; - else { - if(create) - d->attachments = new Attachments(); - return d->attachments; - } + if(!d->attachments && create) + d->attachments = std::make_unique(); + return d->attachments.get(); } void Matroska::File::read(bool readProperties, Properties::ReadStyle) @@ -136,7 +123,7 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle) // Find the EBML Header std::unique_ptr head(EBML::Element::factory(*this)); - if(!head || head->getId() != EBML::ElementIDs::EBMLHeader) { + if(!head || head->getId() != EBML::Element::Id::EBMLHeader) { debug("Failed to find EBML head"); setValid(false); return; @@ -145,8 +132,8 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle) // Find the Matroska segment in the file std::unique_ptr segment( - static_cast( - EBML::findElement(*this, EBML::ElementIDs::MkSegment, fileLength - tell()) + EBML::element_cast( + EBML::findElement(*this, EBML::Element::Id::MkSegment, fileLength - tell()) ) ); if(!segment) { @@ -193,8 +180,8 @@ bool Matroska::File::save() // List of all possible elements we can write List elements { - d->attachments, - d->tag + d->attachments.get(), + d->tag.get() }; /* Build render list. New elements will be added @@ -235,15 +222,15 @@ bool Matroska::File::save() for(auto it2 = std::next(it); it2 != renderList.end(); ++it2) (*it)->addSizeListener(*it2); if(d->seekHead) - (*it)->addSizeListener(d->seekHead); - (*it)->addSizeListener(d->segment); + (*it)->addSizeListener(d->seekHead.get()); + (*it)->addSizeListener(d->segment.get()); } if(d->seekHead) { d->seekHead->addSizeListeners(renderList); - renderList.append(d->seekHead); + renderList.append(d->seekHead.get()); } d->segment->addSizeListeners(renderList); - renderList.append(d->segment); + renderList.append(d->segment.get()); // Render the elements for(auto element : renderList) { diff --git a/taglib/matroska/matroskaseekhead.cpp b/taglib/matroska/matroskaseekhead.cpp index b135b002..09a3070d 100644 --- a/taglib/matroska/matroskaseekhead.cpp +++ b/taglib/matroska/matroskaseekhead.cpp @@ -27,6 +27,11 @@ using namespace TagLib; +Matroska::SeekHead::SeekHead() : + Element(static_cast(EBML::Element::Id::MkSeekHead)) +{ +} + void Matroska::SeekHead::addEntry(const Element &element) { entries.append({element.id(), element.offset()}); @@ -46,16 +51,16 @@ ByteVector Matroska::SeekHead::renderInternal() EBML::MkSeekHead seekHead; seekHead.setMinRenderSize(beforeSize); for(const auto &[id, position] : entries) { - auto seekElement = new EBML::MasterElement(EBML::ElementIDs::MkSeek); - auto idElement = new EBML::BinaryElement(EBML::ElementIDs::MkSeekID); + auto seekElement = EBML::make_unique_element(); + auto idElement = EBML::make_unique_element(); idElement->setValue(ByteVector::fromUInt(id, true)); - seekElement->appendElement(idElement); + seekElement->appendElement(std::move(idElement)); - auto positionElement = new EBML::UIntElement(EBML::ElementIDs::MkSeekPosition); + auto positionElement = EBML::make_unique_element(); positionElement->setValue(static_cast(position)); - seekElement->appendElement(positionElement); + seekElement->appendElement(std::move(positionElement)); - seekHead.appendElement(seekElement); + seekHead.appendElement(std::move(seekElement)); } return seekHead.render(); } @@ -94,7 +99,7 @@ void Matroska::SeekHead::sort() bool Matroska::SeekHead::sizeChanged(Element &caller, offset_t delta) { ID callerID = caller.id(); - if(callerID == ElementIDs::MkSegment) { + if(callerID == static_cast(EBML::Element::Id::MkSegment)) { adjustOffset(delta); return true; } diff --git a/taglib/matroska/matroskaseekhead.h b/taglib/matroska/matroskaseekhead.h index e684a3d9..4f4b09da 100644 --- a/taglib/matroska/matroskaseekhead.h +++ b/taglib/matroska/matroskaseekhead.h @@ -32,7 +32,7 @@ namespace TagLib { class SeekHead : public Element { public: - SeekHead() : Element(ElementIDs::MkSeekHead) {} + SeekHead(); ~SeekHead() override = default; void addEntry(const Element &element); void addEntry(ID id, offset_t offset); diff --git a/taglib/matroska/matroskasegment.cpp b/taglib/matroska/matroskasegment.cpp index 3de08b31..ddcffa90 100644 --- a/taglib/matroska/matroskasegment.cpp +++ b/taglib/matroska/matroskasegment.cpp @@ -23,6 +23,14 @@ using namespace TagLib; +Matroska::Segment::Segment(offset_t sizeLength, offset_t dataSize, offset_t lengthOffset) : + Element(static_cast(EBML::Element::Id::MkSegment)), + sizeLength(sizeLength), dataSize(dataSize) +{ + setOffset(lengthOffset); + setSize(sizeLength); +} + bool Matroska::Segment::render() { auto data = EBML::renderVINT(dataSize, static_cast(sizeLength)); diff --git a/taglib/matroska/matroskasegment.h b/taglib/matroska/matroskasegment.h index dcd1163a..0c9b2e0a 100644 --- a/taglib/matroska/matroskasegment.h +++ b/taglib/matroska/matroskasegment.h @@ -28,13 +28,7 @@ namespace TagLib::Matroska { class Segment : public Element { public: - Segment(offset_t sizeLength, offset_t dataSize, offset_t lengthOffset) : - Element(ElementIDs::MkSegment), sizeLength(sizeLength), dataSize(dataSize) - { - setOffset(lengthOffset); - setSize(sizeLength); - } - + Segment(offset_t sizeLength, offset_t dataSize, offset_t lengthOffset); ~Segment() override = default; bool render() override; bool sizeChanged(Element &caller, offset_t delta) override; diff --git a/taglib/matroska/matroskatag.cpp b/taglib/matroska/matroskatag.cpp index fe65d1e4..d7982b8a 100644 --- a/taglib/matroska/matroskatag.cpp +++ b/taglib/matroska/matroskatag.cpp @@ -95,7 +95,7 @@ public: }; Matroska::Tag::Tag() : - Element(ElementIDs::MkTags), + Element(static_cast(EBML::Element::Id::MkTags)), d(std::make_unique()) { d->tags.setAutoDelete(true); @@ -241,52 +241,52 @@ bool Matroska::Tag::render() for(auto list : targetList) { auto frontTag = list->front(); auto targetTypeValue = frontTag->targetTypeValue(); - auto tag = new EBML::MasterElement(EBML::ElementIDs::MkTag); + auto tag = EBML::make_unique_element(); // Build element - auto targets = new EBML::MasterElement(EBML::ElementIDs::MkTagTargets); + auto targets = EBML::make_unique_element(); if(targetTypeValue != SimpleTag::TargetTypeValue::None) { - auto element = new EBML::UIntElement(EBML::ElementIDs::MkTagTargetTypeValue); + auto element = EBML::make_unique_element(); element->setValue(static_cast(targetTypeValue)); - targets->appendElement(element); + targets->appendElement(std::move(element)); } - tag->appendElement(targets); + tag->appendElement(std::move(targets)); // Build element for(auto simpleTag : *list) { - auto t = new EBML::MasterElement(EBML::ElementIDs::MkSimpleTag); - auto tagName = new EBML::UTF8StringElement(EBML::ElementIDs::MkTagName); + auto t = EBML::make_unique_element(); + auto tagName = EBML::make_unique_element(); tagName->setValue(simpleTag->name()); - t->appendElement(tagName); + t->appendElement(std::move(tagName)); // Tag Value SimpleTagString *tStr = nullptr; SimpleTagBinary *tBin = nullptr; if((tStr = dynamic_cast(simpleTag))) { - auto tagValue = new EBML::UTF8StringElement(EBML::ElementIDs::MkTagString); + auto tagValue = EBML::make_unique_element(); tagValue->setValue(tStr->value()); - t->appendElement(tagValue); + t->appendElement(std::move(tagValue)); } else if((tBin = dynamic_cast(simpleTag))) { - auto tagValue = new EBML::BinaryElement(EBML::ElementIDs::MkTagBinary); + auto tagValue = EBML::make_unique_element(); tagValue->setValue(tBin->value()); - t->appendElement(tagValue); + t->appendElement(std::move(tagValue)); } // Language - auto language = new EBML::Latin1StringElement(EBML::ElementIDs::MkTagsTagLanguage); + auto language = EBML::make_unique_element(); const String &lang = simpleTag->language(); language->setValue(!lang.isEmpty() ? lang : "und"); - t->appendElement(language); + t->appendElement(std::move(language)); // Default language flag - auto dlf = new EBML::UIntElement(EBML::ElementIDs::MkTagsLanguageDefault); + auto dlf = EBML::make_unique_element(); dlf->setValue(simpleTag->defaultLanguageFlag() ? 1 : 0); - t->appendElement(dlf); + t->appendElement(std::move(dlf)); - tag->appendElement(t); + tag->appendElement(std::move(t)); } - tags.appendElement(tag); + tags.appendElement(std::move(tag)); } auto data = tags.render();