From 607cd5bdf46d43d8643a424ade1c9e85fb30b139 Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Sun, 16 Nov 2025 16:12:54 +0100 Subject: [PATCH] Matroska: Fix issues reported by static analysis, formatting, docs --- taglib/matroska/ebml/ebmlbinaryelement.cpp | 1 + taglib/matroska/ebml/ebmlbinaryelement.h | 17 +- taglib/matroska/ebml/ebmlelement.cpp | 18 +- taglib/matroska/ebml/ebmlelement.h | 423 ++++++++++----------- taglib/matroska/ebml/ebmlfloatelement.cpp | 2 +- taglib/matroska/ebml/ebmlfloatelement.h | 14 +- taglib/matroska/ebml/ebmlmasterelement.cpp | 8 +- taglib/matroska/ebml/ebmlmasterelement.h | 68 ++-- taglib/matroska/ebml/ebmlmkattachments.cpp | 15 +- taglib/matroska/ebml/ebmlmkattachments.h | 16 +- taglib/matroska/ebml/ebmlmkchapters.cpp | 17 +- taglib/matroska/ebml/ebmlmkchapters.h | 15 +- taglib/matroska/ebml/ebmlmkcues.cpp | 14 +- taglib/matroska/ebml/ebmlmkcues.h | 17 +- taglib/matroska/ebml/ebmlmkinfo.cpp | 9 +- taglib/matroska/ebml/ebmlmkinfo.h | 16 +- taglib/matroska/ebml/ebmlmkseekhead.cpp | 11 +- taglib/matroska/ebml/ebmlmkseekhead.h | 14 +- taglib/matroska/ebml/ebmlmksegment.cpp | 23 +- taglib/matroska/ebml/ebmlmksegment.h | 21 +- taglib/matroska/ebml/ebmlmktags.cpp | 19 +- taglib/matroska/ebml/ebmlmktags.h | 17 +- taglib/matroska/ebml/ebmlmktracks.cpp | 12 +- taglib/matroska/ebml/ebmlmktracks.h | 16 +- taglib/matroska/ebml/ebmlstringelement.cpp | 18 +- taglib/matroska/ebml/ebmlstringelement.h | 42 +- taglib/matroska/ebml/ebmluintelement.cpp | 8 +- taglib/matroska/ebml/ebmluintelement.h | 16 +- taglib/matroska/ebml/ebmlutils.cpp | 17 +- taglib/matroska/ebml/ebmlutils.h | 21 +- taglib/matroska/ebml/ebmlvoidelement.cpp | 7 +- taglib/matroska/ebml/ebmlvoidelement.h | 12 +- taglib/matroska/matroskaattachedfile.cpp | 6 +- taglib/matroska/matroskaattachedfile.h | 7 +- taglib/matroska/matroskaattachments.cpp | 19 +- taglib/matroska/matroskaattachments.h | 6 +- taglib/matroska/matroskachapter.cpp | 13 +- taglib/matroska/matroskachapter.h | 8 +- taglib/matroska/matroskachapteredition.cpp | 7 +- taglib/matroska/matroskachapteredition.h | 4 +- taglib/matroska/matroskachapters.cpp | 13 +- taglib/matroska/matroskachapters.h | 3 + taglib/matroska/matroskacues.cpp | 23 +- taglib/matroska/matroskacues.h | 16 +- taglib/matroska/matroskaelement.cpp | 15 +- taglib/matroska/matroskaelement.h | 3 +- taglib/matroska/matroskafile.cpp | 44 +-- taglib/matroska/matroskafile.h | 2 - taglib/matroska/matroskaproperties.cpp | 4 +- taglib/matroska/matroskaseekhead.cpp | 58 +-- taglib/matroska/matroskaseekhead.h | 4 +- taglib/matroska/matroskasegment.cpp | 5 +- taglib/matroska/matroskasimpletag.cpp | 10 +- taglib/matroska/matroskasimpletag.h | 6 +- taglib/matroska/matroskatag.cpp | 50 ++- taglib/matroska/matroskatag.h | 29 +- tests/test_matroska.cpp | 2 +- 57 files changed, 624 insertions(+), 677 deletions(-) diff --git a/taglib/matroska/ebml/ebmlbinaryelement.cpp b/taglib/matroska/ebml/ebmlbinaryelement.cpp index 81e35cbc..c8377c70 100644 --- a/taglib/matroska/ebml/ebmlbinaryelement.cpp +++ b/taglib/matroska/ebml/ebmlbinaryelement.cpp @@ -20,6 +20,7 @@ #include "ebmlbinaryelement.h" #include "ebmlutils.h" +#include "tfile.h" using namespace TagLib; diff --git a/taglib/matroska/ebml/ebmlbinaryelement.h b/taglib/matroska/ebml/ebmlbinaryelement.h index bcf9fd70..f14b2b5b 100644 --- a/taglib/matroska/ebml/ebmlbinaryelement.h +++ b/taglib/matroska/ebml/ebmlbinaryelement.h @@ -23,6 +23,7 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlelement.h" +#include "tbytevector.h" namespace TagLib { class File; @@ -31,20 +32,14 @@ namespace TagLib { { public: BinaryElement(Id id, int sizeLength, offset_t dataSize) : - Element(id, sizeLength, dataSize) - { - } + Element(id, sizeLength, dataSize) {} BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t) : - Element(id, sizeLength, dataSize) - { - } - + Element(id, sizeLength, dataSize) {} explicit BinaryElement(Id id) : - Element(id, 0, 0) - { - } + Element(id, 0, 0) {} + const ByteVector &getValue() const { return value; } - void setValue(const ByteVector &value) { this->value = value; } + void setValue(const ByteVector &val) { value = val; } bool read(File &file) override; ByteVector render() override; diff --git a/taglib/matroska/ebml/ebmlelement.cpp b/taglib/matroska/ebml/ebmlelement.cpp index 3acef51e..46c3dd11 100644 --- a/taglib/matroska/ebml/ebmlelement.cpp +++ b/taglib/matroska/ebml/ebmlelement.cpp @@ -36,8 +36,6 @@ #include "tdebug.h" #include "tutils.h" -#include - using namespace TagLib; #define RETURN_ELEMENT_FOR_CASE(eid) \ @@ -46,7 +44,7 @@ using namespace TagLib; std::unique_ptr EBML::Element::factory(File &file) { // Get the element ID - offset_t offset = file.tell(); + const offset_t offset = file.tell(); unsigned int uintId = readId(file); if(!uintId) { debug("Failed to parse EMBL ElementID"); @@ -138,12 +136,12 @@ unsigned int EBML::Element::readId(File &file) debug("Failed to read VINT size"); return 0; } - unsigned int nb_bytes = VINTSizeLength<4>(*buffer.begin()); - if(!nb_bytes) + const unsigned int numBytes = VINTSizeLength<4>(*buffer.begin()); + if(!numBytes) return 0; - if(nb_bytes > 1) - buffer.append(file.readBlock(nb_bytes - 1)); - if(buffer.size() != nb_bytes) { + if(numBytes > 1) + buffer.append(file.readBlock(numBytes - 1)); + if(buffer.size() != numBytes) { debug("Failed to read VINT data"); return 0; } @@ -169,9 +167,9 @@ ByteVector EBML::Element::render() ByteVector EBML::Element::renderId() const { - int numBytes = idSize(id); + const int numBytes = idSize(id); static const auto byteOrder = Utils::systemByteOrder(); - auto uintId = static_cast(id); + const 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 950bcbd7..9c8144b8 100644 --- a/taglib/matroska/ebml/ebmlelement.h +++ b/taglib/matroska/ebml/ebmlelement.h @@ -22,233 +22,232 @@ #define TAGLIB_EBMLELEMENT_H #ifndef DO_NOT_DOCUMENT +#include #include -#include "tfile.h" -#include "tutils.h" #include "taglib.h" -namespace TagLib::EBML { - class Element - { - public: - enum class Id : unsigned int +namespace TagLib +{ + class File; + class ByteVector; + + namespace EBML { + + class Element { - EBMLHeader = 0x1A45DFA3, - DocType = 0x4282, - DocTypeVersion = 0x4287, - VoidElement = 0xEC, - MkSegment = 0x18538067, - MkTags = 0x1254C367, - MkTag = 0x7373, - MkTagTargets = 0x63C0, - MkTagTargetTypeValue = 0x68CA, - MkTagTrackUID = 0x63C5, - 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, - MkTitle = 0x7BA9, - MkTracks = 0x1654AE6B, - MkTrackEntry = 0xAE, - MkCodecID = 0x86, - MkAudio = 0xE1, - MkSamplingFrequency = 0xB5, - MkBitDepth = 0x6264, - MkChannels = 0x9F, - MkChapters = 0x1043A770, - MkEditionEntry = 0x45B9, - MkEditionUID = 0x45BC, - MkEditionFlagDefault = 0x45DB, - MkEditionFlagOrdered = 0x45DD, - MkChapterAtom = 0xB6, - MkChapterUID = 0x73C4, - MkChapterTimeStart = 0x91, - MkChapterTimeEnd = 0x92, - MkChapterFlagHidden = 0x98, - MkChapterDisplay = 0x80, - MkChapString = 0x85, - MkChapLanguage = 0x437C, + public: + enum class Id : unsigned int + { + EBMLHeader = 0x1A45DFA3, + DocType = 0x4282, + DocTypeVersion = 0x4287, + VoidElement = 0xEC, + MkSegment = 0x18538067, + MkTags = 0x1254C367, + MkTag = 0x7373, + MkTagTargets = 0x63C0, + MkTagTargetTypeValue = 0x68CA, + MkTagTrackUID = 0x63C5, + 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, + MkTitle = 0x7BA9, + MkTracks = 0x1654AE6B, + MkTrackEntry = 0xAE, + MkCodecID = 0x86, + MkAudio = 0xE1, + MkSamplingFrequency = 0xB5, + MkBitDepth = 0x6264, + MkChannels = 0x9F, + MkChapters = 0x1043A770, + MkEditionEntry = 0x45B9, + MkEditionUID = 0x45BC, + MkEditionFlagDefault = 0x45DB, + MkEditionFlagOrdered = 0x45DD, + MkChapterAtom = 0xB6, + MkChapterUID = 0x73C4, + MkChapterTimeStart = 0x91, + MkChapterTimeEnd = 0x92, + MkChapterFlagHidden = 0x98, + MkChapterDisplay = 0x80, + MkChapString = 0x85, + MkChapLanguage = 0x437C, + }; + + 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) + { + skipData(file); + return true; + } + void skipData(File &file); + Id getId() const { return id; } + offset_t headSize() const; + offset_t getSize() const { return headSize() + dataSize; } + int getSizeLength() const { return sizeLength; } + int64_t getDataSize() const { return dataSize; } + ByteVector renderId() const; + virtual ByteVector render(); + static std::unique_ptr factory(File &file); + static unsigned int readId(File &file); + + protected: + Id id; + int sizeLength; + offset_t dataSize; }; - Element(Id id, int sizeLength, offset_t dataSize) : - id(id), sizeLength(sizeLength), dataSize(dataSize) + // 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 MkChapters; + class MkCues; + class VoidElement; + class UTF8StringElement; + class Latin1StringElement; + + template + struct GetElementTypeById; + + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = Latin1StringElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + 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 = MkCues; }; + 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 = 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 = UTF8StringElement; }; + template <> struct GetElementTypeById { using type = FloatElement; }; + template <> struct GetElementTypeById { using type = MkSeekHead; }; + template <> struct GetElementTypeById { using type = MkChapters; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = MasterElement; }; + 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 = MasterElement; }; + template <> struct GetElementTypeById { using type = UTF8StringElement; }; + template <> struct GetElementTypeById { using type = Latin1StringElement; }; + template <> struct GetElementTypeById { using type = VoidElement; }; + + template ::type> + const T *element_cast(const std::unique_ptr &ptr) { + return static_cast(ptr.get()); } - Element(Id id, int sizeLength, offset_t dataSize, offset_t) : - id(id), sizeLength(sizeLength), dataSize(dataSize) + + template ::type> + std::unique_ptr element_cast(std::unique_ptr &&ptr) { + return std::unique_ptr(static_cast(ptr.release())); } - virtual ~Element() = default; - virtual bool read(File &file) + + template ::type> + std::unique_ptr make_unique_element(Element::Id id, int sizeLength, offset_t dataSize, offset_t offset) { - skipData(file); - return true; + return std::make_unique(id, sizeLength, dataSize, offset); } - void skipData(File &file); - Id getId() const { return id; } - offset_t headSize() const; - offset_t getSize() const { return headSize() + dataSize; } - int getSizeLength() const { return sizeLength; } - int64_t getDataSize() const { return dataSize; } - ByteVector renderId() const; - virtual ByteVector render(); - static std::unique_ptr factory(File &file); - static unsigned int readId(File &file); - protected: - Id id; - int sizeLength; - offset_t dataSize; - }; + template ::type> + std::unique_ptr make_unique_element() + { + return std::make_unique(ID, 0, 0, 0); + } - // 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 MkChapters; - class MkCues; - class VoidElement; - - template - class StringElement; - using UTF8StringElement = StringElement; - using Latin1StringElement = StringElement; - - template - struct GetElementTypeById; - - template <> struct GetElementTypeById { using type = MasterElement; }; - template <> struct GetElementTypeById { using type = Latin1StringElement; }; - template <> struct GetElementTypeById { using type = UIntElement; }; - 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 = MkCues; }; - 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 = 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 = UTF8StringElement; }; - template <> struct GetElementTypeById { using type = FloatElement; }; - template <> struct GetElementTypeById { using type = MkSeekHead; }; - template <> struct GetElementTypeById { using type = MkChapters; }; - template <> struct GetElementTypeById { using type = MasterElement; }; - template <> struct GetElementTypeById { using type = UIntElement; }; - template <> struct GetElementTypeById { using type = UIntElement; }; - template <> struct GetElementTypeById { using type = UIntElement; }; - template <> struct GetElementTypeById { using type = MasterElement; }; - 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 = MasterElement; }; - template <> struct GetElementTypeById { using type = UTF8StringElement; }; - template <> struct GetElementTypeById { using type = Latin1StringElement; }; - 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.cpp b/taglib/matroska/ebml/ebmlfloatelement.cpp index 4752d862..781aca16 100644 --- a/taglib/matroska/ebml/ebmlfloatelement.cpp +++ b/taglib/matroska/ebml/ebmlfloatelement.cpp @@ -44,7 +44,7 @@ double EBML::FloatElement::getValueAsDouble(double defaultValue) const bool EBML::FloatElement::read(File &file) { - ByteVector buffer = file.readBlock(dataSize); + const ByteVector buffer = file.readBlock(dataSize); if(buffer.size() != dataSize) { debug("Failed to read EBML Float element"); return false; diff --git a/taglib/matroska/ebml/ebmlfloatelement.h b/taglib/matroska/ebml/ebmlfloatelement.h index 2c9ef59c..34a2cab8 100644 --- a/taglib/matroska/ebml/ebmlfloatelement.h +++ b/taglib/matroska/ebml/ebmlfloatelement.h @@ -40,18 +40,12 @@ namespace TagLib { using FloatVariantType = std::variant; FloatElement(Id id, int sizeLength, offset_t dataSize) : - Element(id, sizeLength, dataSize) - { - } + Element(id, sizeLength, dataSize) {} FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t) : - Element(id, sizeLength, dataSize) - { - } - + Element(id, sizeLength, dataSize) {} explicit FloatElement(Id id) : - FloatElement(id, 0, 0) - { - } + FloatElement(id, 0, 0) {} + FloatVariantType getValue() const { return value; } double getValueAsDouble(double defaultValue = 0.0) const; void setValue(FloatVariantType val) { value = val; } diff --git a/taglib/matroska/ebml/ebmlmasterelement.cpp b/taglib/matroska/ebml/ebmlmasterelement.cpp index fd0447dd..85d041e1 100644 --- a/taglib/matroska/ebml/ebmlmasterelement.cpp +++ b/taglib/matroska/ebml/ebmlmasterelement.cpp @@ -27,14 +27,14 @@ using namespace TagLib; EBML::MasterElement::~MasterElement() = default; -void EBML::MasterElement::appendElement(std::unique_ptr&& element) +void EBML::MasterElement::appendElement(std::unique_ptr &&element) { elements.push_back(std::move(element)); } bool EBML::MasterElement::read(File &file) { - offset_t maxOffset = file.tell() + dataSize; + const offset_t maxOffset = file.tell() + dataSize; std::unique_ptr element; while((element = findNextElement(file, maxOffset))) { if(!element->read(file)) @@ -54,8 +54,8 @@ ByteVector EBML::MasterElement::render() buffer.append(renderVINT(dataSize, 0)); buffer.append(data); if(minRenderSize) { - auto bufferSize = buffer.size(); - if(minRenderSize >= bufferSize + MIN_VOID_ELEMENT_SIZE) + if(const auto bufferSize = buffer.size(); + minRenderSize >= bufferSize + MIN_VOID_ELEMENT_SIZE) buffer.append(VoidElement::renderSize(minRenderSize - bufferSize)); } return buffer; diff --git a/taglib/matroska/ebml/ebmlmasterelement.h b/taglib/matroska/ebml/ebmlmasterelement.h index c7f7a846..158bcf84 100644 --- a/taglib/matroska/ebml/ebmlmasterelement.h +++ b/taglib/matroska/ebml/ebmlmasterelement.h @@ -23,46 +23,46 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlelement.h" -#include "tbytevector.h" -#include "tlist.h" #include "taglib.h" +#include "tlist.h" -namespace TagLib::EBML { - class MasterElement : public Element - { - public: - MasterElement(Id id, int sizeLength, offset_t dataSize, offset_t offset) : - Element(id, sizeLength, dataSize), offset(offset) +namespace TagLib +{ + class ByteVector; + + namespace EBML { + class MasterElement : public Element { - } + public: + MasterElement(Id id, int sizeLength, offset_t dataSize, offset_t offset) : + Element(id, sizeLength, dataSize), offset(offset) {} + explicit MasterElement(Id id) : + Element(id, 0, 0), offset(0) {} + ~MasterElement() override; - explicit MasterElement(Id id) : - Element(id, 0, 0), offset(0) - { - } - ~MasterElement() override; - offset_t getOffset() const { return offset; } - bool read(File &file) override; - ByteVector render() override; - 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; } - void setMinRenderSize(offset_t minRenderSize) { this->minRenderSize = minRenderSize; } + offset_t getOffset() const { return offset; } + bool read(File &file) override; + ByteVector render() override; + 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 numBytes) { padding = numBytes; } + offset_t getMinRenderSize() const { return minRenderSize; } + void setMinRenderSize(offset_t minimumSize) { minRenderSize = minimumSize; } - protected: - offset_t offset; - offset_t padding = 0; - offset_t minRenderSize = 0; - std::list> elements; - }; + protected: + offset_t offset; + offset_t padding = 0; + offset_t minRenderSize = 0; + std::list> elements; + }; + } } #endif diff --git a/taglib/matroska/ebml/ebmlmkattachments.cpp b/taglib/matroska/ebml/ebmlmkattachments.cpp index bc58b952..43c2efb9 100644 --- a/taglib/matroska/ebml/ebmlmkattachments.cpp +++ b/taglib/matroska/ebml/ebmlmkattachments.cpp @@ -27,7 +27,7 @@ using namespace TagLib; -std::unique_ptr EBML::MkAttachments::parse() +std::unique_ptr EBML::MkAttachments::parse() const { auto attachments = std::make_unique(); attachments->setOffset(offset); @@ -42,17 +42,16 @@ std::unique_ptr EBML::MkAttachments::parse() const String *mediaType = nullptr; const ByteVector *data = nullptr; Matroska::AttachedFile::UID uid = 0; - auto attachedFile = element_cast(element); + const auto attachedFile = element_cast(element); for(const auto &attachedFileChild : *attachedFile) { - Id id = attachedFileChild->getId(); - if(id == Id::MkAttachedFileName) - filename = &(element_cast(attachedFileChild)->getValue()); + if(const Id id = attachedFileChild->getId(); id == Id::MkAttachedFileName) + filename = &element_cast(attachedFileChild)->getValue(); else if(id == Id::MkAttachedFileData) - data = &(element_cast(attachedFileChild)->getValue()); + data = &element_cast(attachedFileChild)->getValue(); else if(id == Id::MkAttachedFileDescription) - description = &(element_cast(attachedFileChild)->getValue()); + description = &element_cast(attachedFileChild)->getValue(); else if(id == Id::MkAttachedFileMediaType) - mediaType = &(element_cast(attachedFileChild)->getValue()); + mediaType = &element_cast(attachedFileChild)->getValue(); else if(id == Id::MkAttachedFileUID) uid = element_cast(attachedFileChild)->getValue(); } diff --git a/taglib/matroska/ebml/ebmlmkattachments.h b/taglib/matroska/ebml/ebmlmkattachments.h index 02f27648..cefc8e07 100644 --- a/taglib/matroska/ebml/ebmlmkattachments.h +++ b/taglib/matroska/ebml/ebmlmkattachments.h @@ -23,7 +23,6 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlmasterelement.h" -#include "ebmlutils.h" #include "taglib.h" namespace TagLib { @@ -35,18 +34,13 @@ namespace TagLib { { public: MkAttachments(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::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) - { - } + MasterElement(Id::MkAttachments, sizeLength, dataSize, offset) {} MkAttachments() : - MasterElement(Id::MkAttachments, 0, 0, 0) - { - } - std::unique_ptr parse(); + MasterElement(Id::MkAttachments, 0, 0, 0) {} + + std::unique_ptr parse() const; }; } } diff --git a/taglib/matroska/ebml/ebmlmkchapters.cpp b/taglib/matroska/ebml/ebmlmkchapters.cpp index 92c6258d..26d4386c 100644 --- a/taglib/matroska/ebml/ebmlmkchapters.cpp +++ b/taglib/matroska/ebml/ebmlmkchapters.cpp @@ -31,7 +31,7 @@ using namespace TagLib; -std::unique_ptr EBML::MkChapters::parse() +std::unique_ptr EBML::MkChapters::parse() const { auto chapters = std::make_unique(); chapters->setOffset(offset); @@ -45,10 +45,9 @@ std::unique_ptr EBML::MkChapters::parse() Matroska::ChapterEdition::UID editionUid = 0; bool editionIsDefault = false; bool editionIsOrdered = false; - auto edition = element_cast(element); + const auto edition = element_cast(element); for(const auto &editionChild : *edition) { - Id id = editionChild->getId(); - if(id == Id::MkEditionUID) + if(const Id id = editionChild->getId(); id == Id::MkEditionUID) editionUid = element_cast(editionChild)->getValue(); else if(id == Id::MkEditionFlagDefault) editionIsDefault = element_cast(editionChild)->getValue() != 0; @@ -60,10 +59,9 @@ std::unique_ptr EBML::MkChapters::parse() Matroska::Chapter::Time chapterTimeEnd = 0; List chapterDisplays; bool chapterHidden = false; - auto chapterAtom = element_cast(editionChild); + const auto chapterAtom = element_cast(editionChild); for(const auto &chapterChild : *chapterAtom) { - Id cid = chapterChild->getId(); - if(cid == Id::MkChapterUID) + if(const Id cid = chapterChild->getId(); cid == Id::MkChapterUID) chapterUid = element_cast(chapterChild)->getValue(); else if(cid == Id::MkChapterTimeStart) chapterTimeStart = element_cast(chapterChild)->getValue(); @@ -72,12 +70,11 @@ std::unique_ptr EBML::MkChapters::parse() else if(cid == Id::MkChapterFlagHidden) chapterHidden = element_cast(chapterChild)->getValue() != 0; else if(cid == Id::MkChapterDisplay) { - auto display = element_cast(chapterChild); + const auto display = element_cast(chapterChild); String displayString; String displayLanguage; for(const auto &displayChild : *display) { - Id did = displayChild->getId(); - if(did == Id::MkChapString) + if(const Id did = displayChild->getId(); did == Id::MkChapString) displayString = element_cast(displayChild)->getValue(); else if(did == Id::MkChapLanguage) displayLanguage = element_cast(displayChild)->getValue(); diff --git a/taglib/matroska/ebml/ebmlmkchapters.h b/taglib/matroska/ebml/ebmlmkchapters.h index e8aba3a4..462b57a8 100644 --- a/taglib/matroska/ebml/ebmlmkchapters.h +++ b/taglib/matroska/ebml/ebmlmkchapters.h @@ -39,18 +39,13 @@ namespace TagLib { { public: MkChapters(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::MkChapters, sizeLength, dataSize, offset) - { - } + MasterElement(Id::MkChapters, sizeLength, dataSize, offset) {} MkChapters(Id, int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::MkChapters, sizeLength, dataSize, offset) - { - } + MasterElement(Id::MkChapters, sizeLength, dataSize, offset) {} MkChapters() : - MasterElement(Id::MkChapters, 0, 0, 0) - { - } - std::unique_ptr parse(); + MasterElement(Id::MkChapters, 0, 0, 0) {} + + std::unique_ptr parse() const; }; } } diff --git a/taglib/matroska/ebml/ebmlmkcues.cpp b/taglib/matroska/ebml/ebmlmkcues.cpp index 4ba50b3e..005337a0 100644 --- a/taglib/matroska/ebml/ebmlmkcues.cpp +++ b/taglib/matroska/ebml/ebmlmkcues.cpp @@ -24,7 +24,7 @@ using namespace TagLib; -std::unique_ptr EBML::MkCues::parse(offset_t segmentDataOffset) +std::unique_ptr EBML::MkCues::parse(offset_t segmentDataOffset) const { auto cues = std::make_unique(segmentDataOffset); cues->setOffset(offset); @@ -34,19 +34,17 @@ std::unique_ptr EBML::MkCues::parse(offset_t segmentDataOffset) for(const auto &cuesChild : elements) { if(cuesChild->getId() != Id::MkCuePoint) continue; - auto cuePointElement = element_cast(cuesChild); + const auto cuePointElement = element_cast(cuesChild); auto cuePoint = std::make_unique(); for(const auto &cuePointChild : *cuePointElement) { - Id id = cuePointChild->getId(); - if(id == Id::MkCueTime) + if(const Id id = cuePointChild->getId(); id == Id::MkCueTime) cuePoint->setTime(element_cast(cuePointChild)->getValue()); else if(id == Id::MkCueTrackPositions) { auto cueTrack = std::make_unique(); - auto cueTrackElement = element_cast(cuePointChild); + const auto cueTrackElement = element_cast(cuePointChild); for(const auto &cueTrackChild : *cueTrackElement) { - Id trackId = cueTrackChild->getId(); - if(trackId == Id::MkCueTrack) + if(const Id trackId = cueTrackChild->getId(); trackId == Id::MkCueTrack) cueTrack->setTrackNumber(element_cast(cueTrackChild)->getValue()); else if(trackId == Id::MkCueClusterPosition) cueTrack->setClusterPosition(element_cast(cueTrackChild)->getValue()); @@ -59,7 +57,7 @@ std::unique_ptr EBML::MkCues::parse(offset_t segmentDataOffset) else if(trackId == Id::MkCueCodecState) cueTrack->setCodecState(element_cast(cueTrackChild)->getValue()); else if(trackId == Id::MkCueReference) { - auto cueReference = element_cast(cueTrackChild); + const auto cueReference = element_cast(cueTrackChild); for(const auto &cueReferenceChild : *cueReference) { if(cueReferenceChild->getId() != Id::MkCueRefTime) continue; diff --git a/taglib/matroska/ebml/ebmlmkcues.h b/taglib/matroska/ebml/ebmlmkcues.h index edb2b428..388ec354 100644 --- a/taglib/matroska/ebml/ebmlmkcues.h +++ b/taglib/matroska/ebml/ebmlmkcues.h @@ -23,32 +23,25 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlmasterelement.h" -#include "ebmlutils.h" #include "taglib.h" namespace TagLib { namespace Matroska { class Cues; } - //class Matroska::Tag; + namespace EBML { class MkCues : public MasterElement { public: MkCues(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::MkCues, sizeLength, dataSize, offset) - { - } + MasterElement(Id::MkCues, sizeLength, dataSize, offset) {} MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::MkCues, sizeLength, dataSize, offset) - { - } + MasterElement(Id::MkCues, sizeLength, dataSize, offset) {} MkCues() : - MasterElement(Id::MkCues, 0, 0, 0) - { - } + MasterElement(Id::MkCues, 0, 0, 0) {} - std::unique_ptr parse(offset_t segmentDataOffset); + std::unique_ptr parse(offset_t segmentDataOffset) const; }; } } diff --git a/taglib/matroska/ebml/ebmlmkinfo.cpp b/taglib/matroska/ebml/ebmlmkinfo.cpp index d9228b40..b0ea7e63 100644 --- a/taglib/matroska/ebml/ebmlmkinfo.cpp +++ b/taglib/matroska/ebml/ebmlmkinfo.cpp @@ -31,7 +31,7 @@ using namespace TagLib; -void EBML::MkInfo::parse(Matroska::Properties *properties) +void EBML::MkInfo::parse(Matroska::Properties *properties) const { if(!properties) return; @@ -40,14 +40,13 @@ void EBML::MkInfo::parse(Matroska::Properties *properties) double duration = 0.0; String title; for(const auto &element : elements) { - Id id = element->getId(); - if (id == Id::MkTimestampScale) { + if(const Id id = element->getId(); id == Id::MkTimestampScale) { timestampScale = element_cast(element)->getValue(); } - else if (id == Id::MkDuration) { + else if(id == Id::MkDuration) { duration = element_cast(element)->getValueAsDouble(); } - else if (id == Id::MkTitle) { + else if(id == Id::MkTitle) { title = element_cast(element)->getValue(); } } diff --git a/taglib/matroska/ebml/ebmlmkinfo.h b/taglib/matroska/ebml/ebmlmkinfo.h index 672ea217..294342bb 100644 --- a/taglib/matroska/ebml/ebmlmkinfo.h +++ b/taglib/matroska/ebml/ebmlmkinfo.h @@ -28,7 +28,6 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlmasterelement.h" -#include "ebmlutils.h" #include "taglib.h" namespace TagLib { @@ -40,18 +39,13 @@ namespace TagLib { { public: MkInfo(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::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) - { - } + MasterElement(Id::MkInfo, sizeLength, dataSize, offset) {} MkInfo() : - MasterElement(Id::MkInfo, 0, 0, 0) - { - } - void parse(Matroska::Properties * properties); + MasterElement(Id::MkInfo, 0, 0, 0) {} + + void parse(Matroska::Properties * properties) const; }; } } diff --git a/taglib/matroska/ebml/ebmlmkseekhead.cpp b/taglib/matroska/ebml/ebmlmkseekhead.cpp index dccca140..71250cc3 100644 --- a/taglib/matroska/ebml/ebmlmkseekhead.cpp +++ b/taglib/matroska/ebml/ebmlmkseekhead.cpp @@ -25,7 +25,7 @@ using namespace TagLib; -std::unique_ptr EBML::MkSeekHead::parse(offset_t segmentDataOffset) +std::unique_ptr EBML::MkSeekHead::parse(offset_t segmentDataOffset) const { auto seekHead = std::make_unique(segmentDataOffset); seekHead->setOffset(offset); @@ -34,14 +34,13 @@ std::unique_ptr EBML::MkSeekHead::parse(offset_t segmentData for(const auto &element : elements) { if(element->getId() != Id::MkSeek) continue; - auto seekElement = element_cast(element); + const auto seekElement = element_cast(element); Matroska::Element::ID entryId = 0; offset_t offset = 0; for(const auto &seekElementChild : *seekElement) { - Id id = seekElementChild->getId(); - if(id == Id::MkSeekID && !entryId) { - auto data = element_cast(seekElementChild)->getValue(); - if(data.size() == 4) + if(const Id id = seekElementChild->getId(); id == Id::MkSeekID && !entryId) { + if(auto data = element_cast(seekElementChild)->getValue(); + data.size() == 4) entryId = data.toUInt(true); } else if(id == Id::MkSeekPosition && !offset) diff --git a/taglib/matroska/ebml/ebmlmkseekhead.h b/taglib/matroska/ebml/ebmlmkseekhead.h index da7b3071..c7c47acf 100644 --- a/taglib/matroska/ebml/ebmlmkseekhead.h +++ b/taglib/matroska/ebml/ebmlmkseekhead.h @@ -34,19 +34,13 @@ namespace TagLib { { public: MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::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) - { - } + MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset) {} MkSeekHead() : - MasterElement(Id::MkSeekHead, 0, 0, 0) - { - } + MasterElement(Id::MkSeekHead, 0, 0, 0) {} - std::unique_ptr parse(offset_t segmentDataOffset); + std::unique_ptr parse(offset_t segmentDataOffset) const; }; } } diff --git a/taglib/matroska/ebml/ebmlmksegment.cpp b/taglib/matroska/ebml/ebmlmksegment.cpp index 1eb1e8de..1222360b 100644 --- a/taglib/matroska/ebml/ebmlmksegment.cpp +++ b/taglib/matroska/ebml/ebmlmksegment.cpp @@ -39,13 +39,12 @@ offset_t EBML::MkSegment::segmentDataOffset() const bool EBML::MkSegment::read(File &file) { - offset_t maxOffset = file.tell() + dataSize; + const offset_t maxOffset = file.tell() + dataSize; std::unique_ptr element; int i = 0; int seekHeadIndex = -1; while((element = findNextElement(file, maxOffset))) { - Id id = element->getId(); - if(id == Id::MkSeekHead) { + if(const Id id = element->getId(); id == Id::MkSeekHead) { seekHeadIndex = i; seekHead = element_cast(std::move(element)); if(!seekHead->read(file)) @@ -94,46 +93,46 @@ bool EBML::MkSegment::read(File &file) return true; } -std::unique_ptr EBML::MkSegment::parseTag() +std::unique_ptr EBML::MkSegment::parseTag() const { return tags ? tags->parse() : nullptr; } -std::unique_ptr EBML::MkSegment::parseAttachments() +std::unique_ptr EBML::MkSegment::parseAttachments() const { return attachments ? attachments->parse() : nullptr; } -std::unique_ptr EBML::MkSegment::parseChapters() +std::unique_ptr EBML::MkSegment::parseChapters() const { return chapters ? chapters->parse() : nullptr; } -std::unique_ptr EBML::MkSegment::parseSeekHead() +std::unique_ptr EBML::MkSegment::parseSeekHead() const { return seekHead ? seekHead->parse(segmentDataOffset()) : nullptr; } -std::unique_ptr EBML::MkSegment::parseCues() +std::unique_ptr EBML::MkSegment::parseCues() const { return cues ? cues->parse(segmentDataOffset()) : nullptr; } -std::unique_ptr EBML::MkSegment::parseSegment() +std::unique_ptr EBML::MkSegment::parseSegment() const { return std::make_unique(sizeLength, dataSize, offset + idSize(id)); } -void EBML::MkSegment::parseInfo(Matroska::Properties *properties) +void EBML::MkSegment::parseInfo(Matroska::Properties *properties) const { if(info) { info->parse(properties); } } -void EBML::MkSegment::parseTracks(Matroska::Properties *properties) +void EBML::MkSegment::parseTracks(Matroska::Properties *properties) const { - if (tracks) { + if(tracks) { tracks->parse(properties); } } diff --git a/taglib/matroska/ebml/ebmlmksegment.h b/taglib/matroska/ebml/ebmlmksegment.h index 1b8b91ea..f1164a49 100644 --- a/taglib/matroska/ebml/ebmlmksegment.h +++ b/taglib/matroska/ebml/ebmlmksegment.h @@ -49,20 +49,19 @@ namespace TagLib { { } MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::MkSegment, sizeLength, dataSize, offset) - { - } + MasterElement(Id::MkSegment, sizeLength, dataSize, offset) {} ~MkSegment() override; + offset_t segmentDataOffset() const; bool read(File &file) override; - std::unique_ptr parseTag(); - std::unique_ptr parseAttachments(); - std::unique_ptr parseChapters(); - std::unique_ptr parseSeekHead(); - std::unique_ptr parseCues(); - std::unique_ptr parseSegment(); - void parseInfo(Matroska::Properties *properties); - void parseTracks(Matroska::Properties *properties); + std::unique_ptr parseTag() const; + std::unique_ptr parseAttachments() const; + std::unique_ptr parseChapters() const; + std::unique_ptr parseSeekHead() const; + std::unique_ptr parseCues() const; + std::unique_ptr parseSegment() const; + void parseInfo(Matroska::Properties *properties) const; + void parseTracks(Matroska::Properties *properties) const; private: std::unique_ptr tags; diff --git a/taglib/matroska/ebml/ebmlmktags.cpp b/taglib/matroska/ebml/ebmlmktags.cpp index ffee7e5c..339d80db 100644 --- a/taglib/matroska/ebml/ebmlmktags.cpp +++ b/taglib/matroska/ebml/ebmlmktags.cpp @@ -28,7 +28,7 @@ using namespace TagLib; -std::unique_ptr EBML::MkTags::parse() +std::unique_ptr EBML::MkTags::parse() const { auto mTag = std::make_unique(); mTag->setOffset(offset); @@ -39,14 +39,13 @@ std::unique_ptr EBML::MkTags::parse() for(const auto &tagsChild : elements) { if(tagsChild->getId() != Id::MkTag) continue; - auto tag = element_cast(tagsChild); + const auto tag = element_cast(tagsChild); List simpleTags; const MasterElement *targets = nullptr; // Identify the element and the elements for(const auto &tagChild : *tag) { - Id tagChildId = tagChild->getId(); - if(!targets && tagChildId == Id::MkTagTargets) + if(const Id tagChildId = tagChild->getId(); !targets && tagChildId == Id::MkTagTargets) targets = element_cast(tagChild); else if(tagChildId == Id::MkSimpleTag) simpleTags.append(element_cast(tagChild)); @@ -57,8 +56,7 @@ std::unique_ptr EBML::MkTags::parse() unsigned long long trackUid = 0; if(targets) { for(const auto &targetsChild : *targets) { - Id id = targetsChild->getId(); - if(id == Id::MkTagTargetTypeValue + if(const Id id = targetsChild->getId(); id == Id::MkTagTargetTypeValue && targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None) { targetTypeValue = static_cast( element_cast(targetsChild)->getValue() @@ -71,7 +69,7 @@ std::unique_ptr EBML::MkTags::parse() } // Parse each - for(auto simpleTag : simpleTags) { + for(const auto simpleTag : simpleTags) { const String *tagValueString = nullptr; const ByteVector *tagValueBinary = nullptr; String tagName; @@ -79,13 +77,12 @@ std::unique_ptr EBML::MkTags::parse() bool defaultLanguageFlag = true; for(const auto &simpleTagChild : *simpleTag) { - Id id = simpleTagChild->getId(); - if(id == Id::MkTagName && tagName.isEmpty()) + if(const Id id = simpleTagChild->getId(); id == Id::MkTagName && tagName.isEmpty()) tagName = element_cast(simpleTagChild)->getValue(); else if(id == Id::MkTagString && !tagValueString) - tagValueString = &(element_cast(simpleTagChild)->getValue()); + tagValueString = &element_cast(simpleTagChild)->getValue(); else if(id == Id::MkTagBinary && !tagValueBinary) - tagValueBinary = &(element_cast(simpleTagChild)->getValue()); + tagValueBinary = &element_cast(simpleTagChild)->getValue(); else if(id == Id::MkTagsTagLanguage && language.isEmpty()) language = element_cast(simpleTagChild)->getValue(); else if(id == Id::MkTagsLanguageDefault) diff --git a/taglib/matroska/ebml/ebmlmktags.h b/taglib/matroska/ebml/ebmlmktags.h index dea4e2eb..cea61f80 100644 --- a/taglib/matroska/ebml/ebmlmktags.h +++ b/taglib/matroska/ebml/ebmlmktags.h @@ -23,32 +23,25 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlmasterelement.h" -#include "ebmlutils.h" #include "taglib.h" namespace TagLib { namespace Matroska { class Tag; } - //class Matroska::Tag; + namespace EBML { class MkTags : public MasterElement { public: MkTags(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::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) - { - } + MasterElement(Id::MkTags, sizeLength, dataSize, offset) {} MkTags() : - MasterElement(Id::MkTags, 0, 0, 0) - { - } + MasterElement(Id::MkTags, 0, 0, 0) {} - std::unique_ptr parse(); + std::unique_ptr parse() const; }; } } diff --git a/taglib/matroska/ebml/ebmlmktracks.cpp b/taglib/matroska/ebml/ebmlmktracks.cpp index febdaad2..b3491b71 100644 --- a/taglib/matroska/ebml/ebmlmktracks.cpp +++ b/taglib/matroska/ebml/ebmlmktracks.cpp @@ -31,7 +31,7 @@ using namespace TagLib; -void EBML::MkTracks::parse(Matroska::Properties *properties) +void EBML::MkTracks::parse(Matroska::Properties *properties) const { if(!properties) return; @@ -44,16 +44,14 @@ void EBML::MkTracks::parse(Matroska::Properties *properties) double samplingFrequency = 0.0; unsigned long long bitDepth = 0; unsigned long long channels = 0; - auto trackEntry = element_cast(element); + const auto trackEntry = element_cast(element); for(const auto &trackEntryChild : *trackEntry) { - Id trackEntryChildId = trackEntryChild->getId(); - if(trackEntryChildId == Id::MkCodecID) + if(const Id trackEntryChildId = trackEntryChild->getId(); trackEntryChildId == Id::MkCodecID) codecId = element_cast(trackEntryChild)->getValue(); else if(trackEntryChildId == Id::MkAudio) { - auto audio = element_cast(trackEntryChild); + const auto audio = element_cast(trackEntryChild); for(const auto &audioChild : *audio) { - Id audioChildId = audioChild->getId(); - if(audioChildId == Id::MkSamplingFrequency) + if(const Id audioChildId = audioChild->getId(); audioChildId == Id::MkSamplingFrequency) samplingFrequency = element_cast(audioChild)->getValueAsDouble(); else if(audioChildId == Id::MkBitDepth) bitDepth = element_cast(audioChild)->getValue(); diff --git a/taglib/matroska/ebml/ebmlmktracks.h b/taglib/matroska/ebml/ebmlmktracks.h index 1f8ebb2f..2ba2a4b1 100644 --- a/taglib/matroska/ebml/ebmlmktracks.h +++ b/taglib/matroska/ebml/ebmlmktracks.h @@ -28,7 +28,6 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlmasterelement.h" -#include "ebmlutils.h" #include "taglib.h" namespace TagLib { @@ -40,18 +39,13 @@ namespace TagLib { { public: MkTracks(int sizeLength, offset_t dataSize, offset_t offset) : - MasterElement(Id::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) - { - } + MasterElement(Id::MkTracks, sizeLength, dataSize, offset) {} MkTracks() : - MasterElement(Id::MkTracks, 0, 0, 0) - { - } - void parse(Matroska::Properties *properties); + MasterElement(Id::MkTracks, 0, 0, 0) {} + + void parse(Matroska::Properties *properties) const; }; } } diff --git a/taglib/matroska/ebml/ebmlstringelement.cpp b/taglib/matroska/ebml/ebmlstringelement.cpp index 77526c24..5d8fd9cf 100644 --- a/taglib/matroska/ebml/ebmlstringelement.cpp +++ b/taglib/matroska/ebml/ebmlstringelement.cpp @@ -21,15 +21,13 @@ #include "ebmlstringelement.h" #include #include "tfile.h" -#include "tstring.h" #include "tbytevector.h" #include "tdebug.h" #include "ebmlutils.h" using namespace TagLib; -template -bool EBML::StringElement::read(File &file) +bool EBML::StringElement::read(File &file) { ByteVector buffer = file.readBlock(dataSize); if(buffer.size() != dataSize) { @@ -39,24 +37,18 @@ bool EBML::StringElement::read(File &file) // The EBML strings aren't supposed to be null-terminated, // but we'll check for it and strip the null terminator if found - int nullByte = buffer.find('\0'); - if(nullByte >= 0) + if(const int nullByte = buffer.find('\0'); nullByte >= 0) buffer = ByteVector(buffer.data(), nullByte); - value = String(buffer, t); + value = String(buffer, encoding); return true; } -template bool EBML::StringElement::read(File &file); -template bool EBML::StringElement::read(File &file); -template -ByteVector EBML::StringElement::render() +ByteVector EBML::StringElement::render() { ByteVector buffer = renderId(); - std::string string = value.to8Bit(t == String::UTF8); + const std::string string = value.to8Bit(encoding == String::UTF8); dataSize = string.size(); buffer.append(renderVINT(dataSize, 0)); buffer.append(ByteVector(string.data(), static_cast(dataSize))); return buffer; } -template ByteVector EBML::StringElement::render(); -template ByteVector EBML::StringElement::render(); diff --git a/taglib/matroska/ebml/ebmlstringelement.h b/taglib/matroska/ebml/ebmlstringelement.h index 258eb553..2aca07e7 100644 --- a/taglib/matroska/ebml/ebmlstringelement.h +++ b/taglib/matroska/ebml/ebmlstringelement.h @@ -23,40 +23,48 @@ #ifndef DO_NOT_DOCUMENT #include "ebmlelement.h" -#include "tbytevector.h" #include "tstring.h" namespace TagLib { class File; + class ByteVector; + namespace EBML { - template class StringElement : public Element { public: - StringElement(Id id, int sizeLength, offset_t dataSize) : - Element(id, sizeLength, dataSize) - { - } - StringElement(Id id, int sizeLength, offset_t dataSize, offset_t) : - Element(id, sizeLength, dataSize) - { - } + StringElement(String::Type stringEncoding, Id id, int sizeLength, offset_t dataSize) : + Element(id, sizeLength, dataSize), encoding(stringEncoding) {} - explicit StringElement(Id id) : - Element(id, 0, 0) - { - } const String &getValue() const { return value; } - void setValue(const String &value) { this->value = value; } + void setValue(const String &val) { value = val; } bool read(File &file) override; ByteVector render() override; private: String value; + String::Type encoding; }; - using UTF8StringElement = StringElement; - using Latin1StringElement = StringElement; + class UTF8StringElement : public StringElement { + public: + UTF8StringElement(Id id, int sizeLength, offset_t dataSize) : + StringElement(String::UTF8, id, sizeLength, dataSize) {} + UTF8StringElement(Id id, int sizeLength, offset_t dataSize, offset_t) : + UTF8StringElement(id, sizeLength, dataSize) {} + explicit UTF8StringElement(Id id) : + UTF8StringElement(id, 0, 0) {} + }; + + class Latin1StringElement : public StringElement { + public: + Latin1StringElement(Id id, int sizeLength, offset_t dataSize) : + StringElement(String::Latin1, id, sizeLength, dataSize) {} + Latin1StringElement(Id id, int sizeLength, offset_t dataSize, offset_t) : + Latin1StringElement(id, sizeLength, dataSize) {} + explicit Latin1StringElement(Id id) : + Latin1StringElement(id, 0, 0) {} + }; } } diff --git a/taglib/matroska/ebml/ebmluintelement.cpp b/taglib/matroska/ebml/ebmluintelement.cpp index 39c38f0f..b78473ab 100644 --- a/taglib/matroska/ebml/ebmluintelement.cpp +++ b/taglib/matroska/ebml/ebmluintelement.cpp @@ -28,7 +28,7 @@ using namespace TagLib; bool EBML::UIntElement::read(File &file) { - ByteVector buffer = file.readBlock(dataSize); + const ByteVector buffer = file.readBlock(dataSize); if(buffer.size() != dataSize) { debug("Failed to read EBML Uint element"); return false; @@ -59,11 +59,11 @@ ByteVector EBML::UIntElement::render() ByteVector buffer = renderId(); buffer.append(renderVINT(dataSize, 0)); - uint64_t value = this->value; + uint64_t val = value; static const auto byteOrder = Utils::systemByteOrder(); if(byteOrder == Utils::LittleEndian) - value = Utils::byteSwap(value); + val = Utils::byteSwap(val); - buffer.append(ByteVector(reinterpret_cast(&value) + (sizeof(value) - dataSize), dataSize)); + buffer.append(ByteVector(reinterpret_cast(&val) + (sizeof(val) - dataSize), dataSize)); return buffer; } diff --git a/taglib/matroska/ebml/ebmluintelement.h b/taglib/matroska/ebml/ebmluintelement.h index efd6f32f..72f2dc1c 100644 --- a/taglib/matroska/ebml/ebmluintelement.h +++ b/taglib/matroska/ebml/ebmluintelement.h @@ -32,20 +32,14 @@ namespace TagLib { { public: UIntElement(Id id, int sizeLength, offset_t dataSize) : - Element(id, sizeLength, dataSize) - { - } + Element(id, sizeLength, dataSize) {} UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t) : - Element(id, sizeLength, dataSize) - { - } - + Element(id, sizeLength, dataSize) {} explicit UIntElement(Id id) : - UIntElement(id, 0, 0) - { - } + UIntElement(id, 0, 0) {} + unsigned long long getValue() const { return value; } - void setValue(unsigned long long value) { this->value = value; } + void setValue(unsigned long long val) { value = val; } bool read(File &file) override; ByteVector render() override; diff --git a/taglib/matroska/ebml/ebmlutils.cpp b/taglib/matroska/ebml/ebmlutils.cpp index 149109a1..d7b3c578 100644 --- a/taglib/matroska/ebml/ebmlutils.cpp +++ b/taglib/matroska/ebml/ebmlutils.cpp @@ -18,16 +18,11 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ -#include #include "ebmlutils.h" -#include "ebmlelement.h" +#include #include "tbytevector.h" #include "matroskafile.h" -#include "tdebug.h" -#include "tutils.h" -#include "taglib.h" - using namespace TagLib; std::unique_ptr EBML::findElement(File &file, Element::Id id, offset_t maxOffset) @@ -63,8 +58,8 @@ std::pair EBML::readVINT(File &file) if(nb_bytes > 1) buffer.append(file.readBlock(nb_bytes - 1)); - int bits_to_shift = static_cast(sizeof(T) * 8) - 7 * nb_bytes; - offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift; + const int bitsToShift = static_cast(sizeof(T) * 8) - 7 * nb_bytes; + offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift; return { nb_bytes, static_cast(buffer.toLongLong(true)) & mask }; } namespace TagLib::EBML { @@ -82,8 +77,8 @@ std::pair EBML::parseVINT(const ByteVector &buffer) if(!numBytes) return {0, 0}; - int bits_to_shift = static_cast(sizeof(T) * 8) - 7 * numBytes; - offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift; + const int bitsToShift = static_cast(sizeof(T) * 8) - 7 * numBytes; + offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift; return { numBytes, static_cast(buffer.toLongLong(true)) & mask }; } namespace TagLib::EBML { @@ -93,7 +88,7 @@ namespace TagLib::EBML { ByteVector EBML::renderVINT(uint64_t number, int minSizeLength) { - int numBytes = std::max(minSizeLength, minSize(number)); + const int numBytes = std::max(minSizeLength, minSize(number)); number |= 1ULL << (numBytes * 7); static const auto byteOrder = Utils::systemByteOrder(); if(byteOrder == Utils::LittleEndian) diff --git a/taglib/matroska/ebml/ebmlutils.h b/taglib/matroska/ebml/ebmlutils.h index c418d632..20fd6cf9 100644 --- a/taglib/matroska/ebml/ebmlutils.h +++ b/taglib/matroska/ebml/ebmlutils.h @@ -27,7 +27,6 @@ #include "tutils.h" #include "tdebug.h" #include "ebmlelement.h" -#include "tbytevector.h" namespace TagLib { class File; @@ -68,29 +67,27 @@ namespace TagLib { { if(data <= 0x7Fu) return 1; - else if(data <= 0x3FFFu) + if(data <= 0x3FFFu) return 2; - else if(data <= 0x1FFFFFu) + if(data <= 0x1FFFFFu) return 3; - else if(data <= 0xFFFFFFFu) + if(data <= 0xFFFFFFFu) return 4; - else if(data <= 0x7FFFFFFFFu) + if(data <= 0x7FFFFFFFFu) return 5; - else - return 0; + return 0; } constexpr int idSize(Element::Id id) { - auto uintId = static_cast(id); + const auto uintId = static_cast(id); if(uintId <= 0xFF) return 1; - else if(uintId <= 0xFFFF) + if(uintId <= 0xFFFF) return 2; - else if(uintId <= 0xFFFFFF) + if(uintId <= 0xFFFFFF) return 3; - else - return 4; + return 4; } } } diff --git a/taglib/matroska/ebml/ebmlvoidelement.cpp b/taglib/matroska/ebml/ebmlvoidelement.cpp index 3377c327..d764e4a2 100644 --- a/taglib/matroska/ebml/ebmlvoidelement.cpp +++ b/taglib/matroska/ebml/ebmlvoidelement.cpp @@ -19,11 +19,10 @@ ***************************************************************************/ #include "ebmlvoidelement.h" +#include #include "ebmlutils.h" #include "tbytevector.h" -#include - using namespace TagLib; ByteVector EBML::VoidElement::render() @@ -46,9 +45,9 @@ offset_t EBML::VoidElement::getTargetSize() const return targetSize; } -void EBML::VoidElement::setTargetSize(offset_t targetSize) +void EBML::VoidElement::setTargetSize(offset_t size) { - this->targetSize = std::max(targetSize, MIN_VOID_ELEMENT_SIZE); + this->targetSize = std::max(size, MIN_VOID_ELEMENT_SIZE); } ByteVector EBML::VoidElement::renderSize(offset_t targetSize) diff --git a/taglib/matroska/ebml/ebmlvoidelement.h b/taglib/matroska/ebml/ebmlvoidelement.h index 9b6864ac..d4e4e57f 100644 --- a/taglib/matroska/ebml/ebmlvoidelement.h +++ b/taglib/matroska/ebml/ebmlvoidelement.h @@ -33,17 +33,15 @@ namespace TagLib { { public: VoidElement(int sizeLength, offset_t dataSize) : - Element(Id::VoidElement, sizeLength, dataSize) - {} + Element(Id::VoidElement, sizeLength, dataSize) {} VoidElement(Id, int sizeLength, offset_t dataSize, offset_t) : - Element(Id::VoidElement, sizeLength, dataSize) - {} + Element(Id::VoidElement, sizeLength, dataSize) {} VoidElement() : - Element(Id::VoidElement, 0, 0) - {} + Element(Id::VoidElement, 0, 0) {} + ByteVector render() override; offset_t getTargetSize() const; - void setTargetSize(offset_t targetSize); + void setTargetSize(offset_t size); static ByteVector renderSize(offset_t targetSize); private: diff --git a/taglib/matroska/matroskaattachedfile.cpp b/taglib/matroska/matroskaattachedfile.cpp index 06c6f4f3..f9fdf9bf 100644 --- a/taglib/matroska/matroskaattachedfile.cpp +++ b/taglib/matroska/matroskaattachedfile.cpp @@ -1,5 +1,5 @@ /*************************************************************************** -* This library is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License version * * 2.1 as published by the Free Software Foundation. * * * @@ -50,11 +50,11 @@ Matroska::AttachedFile::AttachedFile(const AttachedFile &other) : { } -Matroska::AttachedFile::AttachedFile(AttachedFile&& other) noexcept = default; +Matroska::AttachedFile::AttachedFile(AttachedFile &&other) noexcept = default; Matroska::AttachedFile::~AttachedFile() = default; -Matroska::AttachedFile &Matroska::AttachedFile::operator=(AttachedFile &&other) = default; +Matroska::AttachedFile &Matroska::AttachedFile::operator=(AttachedFile &&other) noexcept = default; Matroska::AttachedFile &Matroska::AttachedFile::operator=(const AttachedFile &other) { diff --git a/taglib/matroska/matroskaattachedfile.h b/taglib/matroska/matroskaattachedfile.h index 14cb5475..b7afcd16 100644 --- a/taglib/matroska/matroskaattachedfile.h +++ b/taglib/matroska/matroskaattachedfile.h @@ -32,7 +32,12 @@ namespace TagLib { class TAGLIB_EXPORT AttachedFile { public: + //! Unique identifier. using UID = unsigned long long; + + /*! + * Construct an attached file. + */ AttachedFile(); /*! @@ -58,7 +63,7 @@ namespace TagLib { /*! * Moves the contents of \a other into this object. */ - AttachedFile &operator=(AttachedFile &&other); + AttachedFile &operator=(AttachedFile &&other) noexcept; /*! * Exchanges the content of the object with the content of \a other. diff --git a/taglib/matroska/matroskaattachments.cpp b/taglib/matroska/matroskaattachments.cpp index 2a0ad9d7..5bdee484 100644 --- a/taglib/matroska/matroskaattachments.cpp +++ b/taglib/matroska/matroskaattachments.cpp @@ -1,5 +1,5 @@ /*************************************************************************** -* This library is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License version * * 2.1 as published by the Free Software Foundation. * * * @@ -19,13 +19,13 @@ ***************************************************************************/ #include "matroskaattachments.h" -#include #include "matroskaattachedfile.h" #include "ebmlmkattachments.h" #include "ebmlmasterelement.h" #include "ebmlstringelement.h" #include "ebmlbinaryelement.h" #include "ebmluintelement.h" +#include "ebmlutils.h" #include "tlist.h" #include "tbytevector.h" @@ -53,7 +53,7 @@ Matroska::Attachments::Attachments() : Matroska::Attachments::~Attachments() = default; -void Matroska::Attachments::addAttachedFile(const AttachedFile& file) +void Matroska::Attachments::addAttachedFile(const AttachedFile &file) { d->files.append(file); setNeedsRender(true); @@ -61,8 +61,8 @@ void Matroska::Attachments::addAttachedFile(const AttachedFile& file) void Matroska::Attachments::removeAttachedFile(unsigned long long uid) { - auto it = std::find_if(d->files.begin(), d->files.end(), - [uid](const AttachedFile& file) { + const auto it = std::find_if(d->files.begin(), d->files.end(), + [uid](const AttachedFile &file) { return file.uid() == uid; }); if(it != d->files.end()) { @@ -109,14 +109,15 @@ ByteVector Matroska::Attachments::renderInternal() attachedFileElement->appendElement(std::move(fileNameElement)); // Media/MIME type - auto mediaTypeElement = EBML::make_unique_element(); + auto mediaTypeElement = + EBML::make_unique_element(); mediaTypeElement->setValue(attachedFile.mediaType()); attachedFileElement->appendElement(std::move(mediaTypeElement)); // Description - const String &description = attachedFile.description(); - if(!description.isEmpty()) { - auto descriptionElement = EBML::make_unique_element(); + if(const String &description = attachedFile.description(); !description.isEmpty()) { + auto descriptionElement = + EBML::make_unique_element(); descriptionElement->setValue(description); attachedFileElement->appendElement(std::move(descriptionElement)); } diff --git a/taglib/matroska/matroskaattachments.h b/taglib/matroska/matroskaattachments.h index d7296057..ba586684 100644 --- a/taglib/matroska/matroskaattachments.h +++ b/taglib/matroska/matroskaattachments.h @@ -42,11 +42,13 @@ namespace TagLib { #endif { public: + //! List of attached files. using AttachedFileList = List; + //! Construct attachments. Attachments(); - //! Destroy attachements. + //! Destroy attachments. virtual ~Attachments(); //! Add an attached file. @@ -55,7 +57,7 @@ namespace TagLib { //! Remove an attached file. void removeAttachedFile(unsigned long long uid); - //! Remove an attached file. + //! Remove all attached files. void clear(); //! Get list of all attached files. diff --git a/taglib/matroska/matroskachapter.cpp b/taglib/matroska/matroskachapter.cpp index 6e4c1b4e..4867ec25 100644 --- a/taglib/matroska/matroskachapter.cpp +++ b/taglib/matroska/matroskachapter.cpp @@ -4,7 +4,7 @@ ***************************************************************************/ /*************************************************************************** -* This library is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License version * * 2.1 as published by the Free Software Foundation. * * * @@ -109,7 +109,7 @@ bool Matroska::Chapter::isHidden() const return d->hidden; } -const List& Matroska::Chapter::displayList() const +const List &Matroska::Chapter::displayList() const { return d->displayList; } @@ -130,13 +130,14 @@ Matroska::Chapter::Display::Display(Display &&other) noexcept = default; Matroska::Chapter::Display::~Display() = default; -Matroska::Chapter::Display& Matroska::Chapter::Display::operator=(const Display &other) +Matroska::Chapter::Display &Matroska::Chapter::Display::operator=(const Display &other) { Display(other).swap(*this); return *this; } -Matroska::Chapter::Display& Matroska::Chapter::Display::operator=(Display &&other) noexcept = default; +Matroska::Chapter::Display &Matroska::Chapter::Display::operator=( + Display &&other) noexcept = default; void Matroska::Chapter::Display::swap(Display &other) noexcept { @@ -145,12 +146,12 @@ void Matroska::Chapter::Display::swap(Display &other) noexcept swap(d, other.d); } -const String& Matroska::Chapter::Display::string() const +const String &Matroska::Chapter::Display::string() const { return d->string; } -const String& Matroska::Chapter::Display::language() const +const String &Matroska::Chapter::Display::language() const { return d->language; } diff --git a/taglib/matroska/matroskachapter.h b/taglib/matroska/matroskachapter.h index 9135b54f..df030d8a 100644 --- a/taglib/matroska/matroskachapter.h +++ b/taglib/matroska/matroskachapter.h @@ -31,18 +31,22 @@ #include "tlist.h" namespace TagLib { + class String; + class ByteVector; + namespace EBML { class MkChapters; } - class String; - class ByteVector; namespace Matroska { //! Matroska chapter. class TAGLIB_EXPORT Chapter { public: + //! Unique identifier. using UID = unsigned long long; + + //! Timestamp in nanoseconds. using Time = unsigned long long; /*! diff --git a/taglib/matroska/matroskachapteredition.cpp b/taglib/matroska/matroskachapteredition.cpp index 2a2293a5..2e9f733c 100644 --- a/taglib/matroska/matroskachapteredition.cpp +++ b/taglib/matroska/matroskachapteredition.cpp @@ -4,7 +4,7 @@ ***************************************************************************/ /*************************************************************************** -* This library is free software; you can redistribute it and/or modify * + * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License version * * 2.1 as published by the Free Software Foundation. * * * @@ -61,11 +61,12 @@ Matroska::ChapterEdition::ChapterEdition(const ChapterEdition &other) : { } -Matroska::ChapterEdition::ChapterEdition(ChapterEdition&& other) noexcept = default; +Matroska::ChapterEdition::ChapterEdition(ChapterEdition &&other) noexcept = default; Matroska::ChapterEdition::~ChapterEdition() = default; -Matroska::ChapterEdition &Matroska::ChapterEdition::operator=(ChapterEdition &&other) = default; +Matroska::ChapterEdition &Matroska::ChapterEdition::operator=( + ChapterEdition &&other) noexcept = default; Matroska::ChapterEdition &Matroska::ChapterEdition::operator=(const ChapterEdition &other) { diff --git a/taglib/matroska/matroskachapteredition.h b/taglib/matroska/matroskachapteredition.h index 6ed4c789..3d8758f3 100644 --- a/taglib/matroska/matroskachapteredition.h +++ b/taglib/matroska/matroskachapteredition.h @@ -31,11 +31,13 @@ namespace TagLib { class String; class ByteVector; + namespace Matroska { //! Edition of chapters. class TAGLIB_EXPORT ChapterEdition { public: + //! Unique identifier. using UID = unsigned long long; /*! @@ -67,7 +69,7 @@ namespace TagLib { /*! * Moves the contents of \a other into this object. */ - ChapterEdition &operator=(ChapterEdition &&other); + ChapterEdition &operator=(ChapterEdition &&other) noexcept; /*! * Exchanges the content of the object with the content of \a other. diff --git a/taglib/matroska/matroskachapters.cpp b/taglib/matroska/matroskachapters.cpp index 8f94525e..4b88cecc 100644 --- a/taglib/matroska/matroskachapters.cpp +++ b/taglib/matroska/matroskachapters.cpp @@ -24,7 +24,6 @@ ***************************************************************************/ #include "matroskachapters.h" -#include #include "matroskachapteredition.h" #include "ebmlstringelement.h" #include "ebmlbinaryelement.h" @@ -58,7 +57,7 @@ Matroska::Chapters::Chapters() : Matroska::Chapters::~Chapters() = default; -void Matroska::Chapters::addChapterEdition(const ChapterEdition& edition) +void Matroska::Chapters::addChapterEdition(const ChapterEdition &edition) { d->editions.append(edition); setNeedsRender(true); @@ -66,8 +65,8 @@ void Matroska::Chapters::addChapterEdition(const ChapterEdition& edition) void Matroska::Chapters::removeChapterEdition(unsigned long long uid) { - auto it = std::find_if(d->editions.begin(), d->editions.end(), - [uid](const ChapterEdition& file) { + const auto it = std::find_if(d->editions.begin(), d->editions.end(), + [uid](const ChapterEdition &file) { return file.uid() == uid; }); if(it != d->editions.end()) { @@ -101,7 +100,7 @@ ByteVector Matroska::Chapters::renderInternal() for(const auto &chapterEdition : std::as_const(d->editions)) { auto chapterEditionElement = EBML::make_unique_element(); - if(auto uid = chapterEdition.uid()) { + if(const auto uid = chapterEdition.uid()) { auto uidElement = EBML::make_unique_element(); uidElement->setValue(uid); chapterEditionElement->appendElement(std::move(uidElement)); @@ -117,7 +116,7 @@ ByteVector Matroska::Chapters::renderInternal() auto chapterElement = EBML::make_unique_element(); auto cuidElement = EBML::make_unique_element(); - auto cuid = chapter.uid(); + const auto cuid = chapter.uid(); cuidElement->setValue(cuid ? cuid : EBML::randomUID()); chapterElement->appendElement(std::move(cuidElement)); auto timeStartElement = EBML::make_unique_element(); @@ -130,7 +129,7 @@ ByteVector Matroska::Chapters::renderInternal() hiddenElement->setValue(chapter.isHidden()); chapterElement->appendElement(std::move(hiddenElement)); - for(const auto& display : chapter.displayList()) { + for(const auto &display : chapter.displayList()) { auto displayElement = EBML::make_unique_element(); auto stringElement = EBML::make_unique_element(); diff --git a/taglib/matroska/matroskachapters.h b/taglib/matroska/matroskachapters.h index c235b74f..f033340f 100644 --- a/taglib/matroska/matroskachapters.h +++ b/taglib/matroska/matroskachapters.h @@ -33,6 +33,7 @@ namespace TagLib { class File; + namespace EBML { class MkChapters; } @@ -47,7 +48,9 @@ namespace TagLib { #endif { public: + //! List of chapter editions. using ChapterEditionList = List; + //! Construct chapters. Chapters(); diff --git a/taglib/matroska/matroskacues.cpp b/taglib/matroska/matroskacues.cpp index d4390a5c..6be02904 100644 --- a/taglib/matroska/matroskacues.cpp +++ b/taglib/matroska/matroskacues.cpp @@ -38,7 +38,7 @@ Matroska::Cues::Cues(offset_t segmentDataOffset) : ByteVector Matroska::Cues::renderInternal() { - auto beforeSize = sizeRenderedOrWritten(); + const auto beforeSize = sizeRenderedOrWritten(); EBML::MkCues cues; cues.setMinRenderSize(beforeSize); for(const auto &cuePoint : cuePoints) { @@ -90,10 +90,9 @@ ByteVector Matroska::Cues::renderInternal() } // Reference times - auto referenceTimes = cueTrack->referenceTimes(); - if(!referenceTimes.isEmpty()) { + if(auto referenceTimes = cueTrack->referenceTimes(); !referenceTimes.isEmpty()) { auto cueReference = EBML::make_unique_element(); - for(auto reference : referenceTimes) { + for(const auto reference : referenceTimes) { auto refTime = EBML::make_unique_element(); refTime->setValue(reference); cueReference->appendElement(std::move(refTime)); @@ -107,7 +106,7 @@ ByteVector Matroska::Cues::renderInternal() return cues.render(); } -void Matroska::Cues::write(TagLib::File& file) +void Matroska::Cues::write(TagLib::File &file) { if(!data().isEmpty()) Element::write(file); @@ -119,8 +118,8 @@ bool Matroska::Cues::sizeChanged(Element &caller, offset_t delta) if(!Element::sizeChanged(caller, delta)) return false; - offset_t offset = caller.offset() - segmentDataOffset; - for(auto &cuePoint : cuePoints) { + const offset_t offset = caller.offset() - segmentDataOffset; + for(const auto &cuePoint : cuePoints) { if(cuePoint->adjustOffset(offset, delta)) { setNeedsRender(true); } @@ -142,9 +141,7 @@ void Matroska::Cues::addCuePoint(std::unique_ptr &&cuePoint) cuePoints.push_back(std::move(cuePoint)); } -Matroska::CuePoint::CuePoint() -{ -} +Matroska::CuePoint::CuePoint() = default; bool Matroska::CuePoint::isValid(TagLib::File &file, offset_t segmentDataOffset) const { @@ -163,7 +160,7 @@ void Matroska::CuePoint::addCueTrack(std::unique_ptr &&cueTrack) bool Matroska::CuePoint::adjustOffset(offset_t offset, offset_t delta) { bool ret = false; - for(auto &cueTrack : cueTracks) + for(const auto &cueTrack : cueTracks) ret |= cueTrack->adjustOffset(offset, delta); return ret; @@ -201,8 +198,8 @@ bool Matroska::CueTrack::adjustOffset(offset_t offset, offset_t delta) clusterPosition += delta; ret = true; } - offset_t codecStateValue; - if(codecState.has_value() && (codecStateValue = codecState.value()) != 0 && + if(offset_t codecStateValue; + codecState.has_value() && (codecStateValue = codecState.value()) != 0 && codecStateValue > offset) { codecState = codecStateValue + delta; ret = true; diff --git a/taglib/matroska/matroskacues.h b/taglib/matroska/matroskacues.h index ee971d04..7241f8f3 100644 --- a/taglib/matroska/matroskacues.h +++ b/taglib/matroska/matroskacues.h @@ -29,6 +29,7 @@ namespace TagLib { class File; + namespace EBML { class MkCues; } @@ -36,6 +37,7 @@ namespace TagLib { namespace Matroska { class CuePoint; class CueTrack; + class Cues : public Element { public: @@ -66,7 +68,7 @@ namespace TagLib { bool isValid(TagLib::File &file, offset_t segmentDataOffset) const; void addCueTrack(std::unique_ptr &&cueTrack); const CueTrackList &cueTrackList() const { return cueTracks; } - void setTime(Time time) { this->time = time; } + void setTime(Time timestamp) { time = timestamp; } Time getTime() const { return time; } bool adjustOffset(offset_t offset, offset_t delta); @@ -82,17 +84,17 @@ namespace TagLib { CueTrack() = default; ~CueTrack() = default; bool isValid(TagLib::File &file, offset_t segmentDataOffset) const; - void setTrackNumber(unsigned long long trackNumber) { this->trackNumber = trackNumber; } + void setTrackNumber(unsigned long long trackNr) { trackNumber = trackNr; } unsigned long long getTrackNumber() const { return trackNumber; } - void setClusterPosition(offset_t clusterPosition) { this->clusterPosition = clusterPosition; } + void setClusterPosition(offset_t clusterPos) { clusterPosition = clusterPos; } offset_t getClusterPosition() const { return clusterPosition; } - void setRelativePosition(std::optional relativePosition) { this->relativePosition = relativePosition; } + void setRelativePosition(std::optional relativePos) { relativePosition = relativePos; } std::optional getRelativePosition() const { return relativePosition; } - void setCodecState(std::optional codecState) { this->codecState = codecState; } + void setCodecState(std::optional codecStatePos) { codecState = codecStatePos; } std::optional getCodecState() const { return codecState; } - void setBlockNumber(std::optional blockNumber) { this->blockNumber = blockNumber; } + void setBlockNumber(std::optional blockNr) { blockNumber = blockNr; } std::optional getBlockNumber() const { return blockNumber; } - void setDuration(std::optional duration) { this->duration = duration; } + void setDuration(std::optional segmentTicks) { duration = segmentTicks; } std::optional getDuration() const { return duration; } void addReferenceTime(unsigned long long refTime) { refTimes.append(refTime); } const ReferenceTimeList &referenceTimes() const { return refTimes; } diff --git a/taglib/matroska/matroskaelement.cpp b/taglib/matroska/matroskaelement.cpp index 17c978d1..f1f6b63a 100644 --- a/taglib/matroska/matroskaelement.cpp +++ b/taglib/matroska/matroskaelement.cpp @@ -17,8 +17,9 @@ * License Version 1.1. You may obtain a copy of the License at * * http://www.mozilla.org/MPL/ * ***************************************************************************/ -#include + #include "matroskaelement.h" +#include #include "tlist.h" #include "tfile.h" #include "tbytevector.h" @@ -48,6 +49,7 @@ Matroska::Element::Element(ID id) : { e->id = id; } + Matroska::Element::~Element() = default; offset_t Matroska::Element::size() const @@ -110,11 +112,10 @@ bool Matroska::Element::render() if(!needsRender()) return true; - auto beforeSize = sizeRenderedOrWritten(); - auto data = renderInternal(); + const auto beforeSize = sizeRenderedOrWritten(); + const auto data = renderInternal(); setNeedsRender(false); - auto afterSize = data.size(); - if(afterSize != beforeSize) { + if(const auto afterSize = data.size(); afterSize != beforeSize) { if(!emitSizeChanged(afterSize - beforeSize)) { return false; } @@ -136,7 +137,7 @@ bool Matroska::Element::needsRender() const bool Matroska::Element::emitSizeChanged(offset_t delta) { - for(auto element : e->sizeListeners) { + for(const auto element : e->sizeListeners) { if(!element->sizeChanged(*this, delta)) return false; } @@ -156,7 +157,7 @@ bool Matroska::Element::sizeChanged(Element &caller, offset_t delta) offset_t Matroska::Element::sizeRenderedOrWritten() const { - offset_t dataSize = e->data.size(); + const offset_t dataSize = e->data.size(); return dataSize != 0 ? dataSize : e->size; } diff --git a/taglib/matroska/matroskaelement.h b/taglib/matroska/matroskaelement.h index f78f8f56..ad5efdc8 100644 --- a/taglib/matroska/matroskaelement.h +++ b/taglib/matroska/matroskaelement.h @@ -25,11 +25,12 @@ #include #include "taglib_export.h" #include "taglib.h" -#include "tbytevector.h" #include "tlist.h" namespace TagLib { class File; + class ByteVector; + namespace Matroska { class TAGLIB_EXPORT Element { diff --git a/taglib/matroska/matroskafile.cpp b/taglib/matroska/matroskafile.cpp index 2cf83a4e..e27f389d 100644 --- a/taglib/matroska/matroskafile.cpp +++ b/taglib/matroska/matroskafile.cpp @@ -19,6 +19,7 @@ ***************************************************************************/ #include "matroskafile.h" +#include #include "matroskatag.h" #include "matroskaattachments.h" #include "matroskaattachedfile.h" @@ -38,8 +39,6 @@ #include "tagutils.h" #include "tpropertymap.h" -#include - using namespace TagLib; class Matroska::File::FilePrivate @@ -177,8 +176,8 @@ StringList Matroska::File::complexPropertyKeys() const if(d->attachments) { const auto &attachedFiles = d->attachments->attachedFileList(); for(const auto &attachedFile : attachedFiles) { - String key = keyForAttachedFile(attachedFile); - if(!key.isEmpty() && !keys.contains(key)) { + if(String key = keyForAttachedFile(attachedFile); + !key.isEmpty() && !keys.contains(key)) { keys.append(key); } } @@ -196,27 +195,27 @@ List Matroska::File::complexProperties(const String &key) const if(d->chapters) { for(const auto &edition : d->chapters->chapterEditionList()) { VariantMap property; - if(auto uid = edition.uid()) { + if(const auto uid = edition.uid()) { property.insert("uid", uid); } - if(auto isDefault = edition.isDefault()) { + if(const auto isDefault = edition.isDefault()) { property.insert("isDefault", isDefault); } - if(auto isOrdered = edition.isOrdered()) { + if(const auto isOrdered = edition.isOrdered()) { property.insert("isOrdered", isOrdered); } if(auto chapters = edition.chapterList(); !chapters.isEmpty()) { VariantList chaps; for(const auto &chapter : chapters) { VariantMap chap; - if(auto uid = chapter.uid()) { + if(const auto uid = chapter.uid()) { chap.insert("uid", uid); } - if(auto isHidden = chapter.isHidden()) { + if(const auto isHidden = chapter.isHidden()) { chap.insert("isHidden", isHidden); } chap.insert("timeStart", chapter.timeStart()); - if(auto timeEnd = chapter.timeEnd()) { + if(const auto timeEnd = chapter.timeEnd()) { chap.insert("timeEnd", timeEnd); } if(auto displays = chapter.displayList(); !displays.isEmpty()) { @@ -313,7 +312,6 @@ bool Matroska::File::setComplexProperties(const String &key, const List(); auto uid = property.value("uid").value(); bool ok; - unsigned long long uidKey; if(key.upper() == "PICTURE" && !mimeType.startsWith("image/")) { mimeType = data.startsWith("\x89PNG\x0d\x0a\x1a\x0a") ? "image/png" : "image/jpeg"; @@ -324,11 +322,12 @@ bool Matroska::File::setComplexProperties(const String &key, const List( + const auto head = EBML::element_cast( EBML::Element::factory(*this)); if(!head || head->getId() != EBML::Element::Id::EBMLHeader) { debug("Failed to find EBML head"); @@ -382,7 +381,7 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle) } // Find the Matroska segment in the file - std::unique_ptr segment( + const std::unique_ptr segment( EBML::element_cast( EBML::findElement(*this, EBML::Element::Id::MkSegment, fileLength - tell()) ) @@ -412,12 +411,11 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle) d->properties = std::make_unique(this); for(const auto &element : *head) { - auto id = element->getId(); - if (id == EBML::Element::Id::DocType) { + if(const auto id = element->getId(); id == EBML::Element::Id::DocType) { d->properties->setDocType( EBML::element_cast(element)->getValue()); } - else if (id == EBML::Element::Id::DocTypeVersion) { + else if(id == EBML::Element::Id::DocTypeVersion) { d->properties->setDocTypeVersion(static_cast( EBML::element_cast(element)->getValue())); } @@ -505,8 +503,8 @@ bool Matroska::File::save() // Add our new elements to the Seek Head (if the file has one) if(d->seekHead) { - auto segmentDataOffset = d->segment->dataOffset(); - for(auto element : newElements) + const auto segmentDataOffset = d->segment->dataOffset(); + for(const auto element : newElements) d->seekHead->addEntry(element->id(), element->offset() - segmentDataOffset); d->seekHead->sort(); } @@ -545,7 +543,7 @@ bool Matroska::File::save() bool rendering = true; while(rendering && renderRound < 5) { rendering = false; - for(auto element : renderList) { + for(const auto element : renderList) { if(element->needsRender()) { rendering = true; if(!element->render()) { @@ -558,7 +556,7 @@ bool Matroska::File::save() // Write out to file renderList.sort(sortAscending); - for(auto element : renderList) + for(const auto element : renderList) element->write(*this); return true; diff --git a/taglib/matroska/matroskafile.h b/taglib/matroska/matroskafile.h index 71cd9e7c..559be5aa 100644 --- a/taglib/matroska/matroskafile.h +++ b/taglib/matroska/matroskafile.h @@ -23,11 +23,9 @@ #include "taglib_export.h" #include "tfile.h" -#include "tag.h" #include "matroskaproperties.h" namespace TagLib::Matroska { - class Properties; class Tag; class Attachments; class Chapters; diff --git a/taglib/matroska/matroskaproperties.cpp b/taglib/matroska/matroskaproperties.cpp index c1c2a3c5..fe37defb 100644 --- a/taglib/matroska/matroskaproperties.cpp +++ b/taglib/matroska/matroskaproperties.cpp @@ -69,7 +69,7 @@ int Matroska::Properties::lengthInMilliseconds() const int Matroska::Properties::bitrate() const { - if (d->bitrate == -1) { + if(d->bitrate == -1) { d->bitrate = d->length != 0 ? static_cast(d->file->length() * 8 / d->length) : 0; } return d->bitrate; @@ -149,7 +149,7 @@ void Matroska::Properties::setCodecName(const String &codecName) d->codecName = codecName; } -void Matroska::Properties::setTitle(const String& title) +void Matroska::Properties::setTitle(const String &title) { d->title = title; } diff --git a/taglib/matroska/matroskaseekhead.cpp b/taglib/matroska/matroskaseekhead.cpp index f297335e..88ad1d7e 100644 --- a/taglib/matroska/matroskaseekhead.cpp +++ b/taglib/matroska/matroskaseekhead.cpp @@ -23,6 +23,8 @@ #include "ebmlbinaryelement.h" #include "ebmluintelement.h" #include "ebmlmasterelement.h" +#include "tfile.h" +#include "tutils.h" #include "tdebug.h" using namespace TagLib; @@ -34,7 +36,7 @@ Matroska::SeekHead::SeekHead(offset_t segmentDataOffset) : setNeedsRender(false); } -bool Matroska::SeekHead::isValid(TagLib::File& file) const +bool Matroska::SeekHead::isValid(TagLib::File &file) const { bool result = true; for(const auto &[id, offset] : entries) { @@ -62,7 +64,7 @@ void Matroska::SeekHead::addEntry(ID id, offset_t offset) ByteVector Matroska::SeekHead::renderInternal() { - auto beforeSize = sizeRenderedOrWritten(); + const auto beforeSize = sizeRenderedOrWritten(); EBML::MkSeekHead seekHead; seekHead.setMinRenderSize(beforeSize); for(const auto &[id, position] : entries) { @@ -98,34 +100,32 @@ bool Matroska::SeekHead::sizeChanged(Element &caller, offset_t delta) adjustOffset(delta); return true; } - else { - // The equal case is needed when multiple new elements are added - // (e.g. Attachments and Tags), they will start with the same offset - // and are updated via size change handling. - offset_t offset = caller.offset() - segmentDataOffset; - auto it = entries.begin(); - while(it != entries.end()) { - it = std::find_if(it, - entries.end(), - [offset, callerID](const auto &a) { - return a.second >= offset && a.first != callerID; - } - ); - if(it != entries.end()) { - it->second += delta; - setNeedsRender(true); - ++it; + // The equal case is needed when multiple new elements are added + // (e.g. Attachments and Tags), they will start with the same offset + // and are updated via size change handling. + offset_t offset = caller.offset() - segmentDataOffset; + auto it = entries.begin(); + while(it != entries.end()) { + it = std::find_if(it, + entries.end(), + [offset, callerID](const auto &a) { + return a.second >= offset && a.first != callerID; } + ); + if(it != entries.end()) { + it->second += delta; + setNeedsRender(true); + ++it; } - - if(caller.data().isEmpty() && caller.size() + delta == 0) { - // The caller element is removed, remove it from the seek head. - it = std::find_if(entries.begin(), entries.end(), - [callerID](const auto &a){ return a.first == callerID; }); - if(it != entries.end()) { - entries.erase(it); - } - } - return true; } + + if(caller.data().isEmpty() && caller.size() + delta == 0) { + // The caller element is removed, remove it from the seek head. + it = std::find_if(entries.begin(), entries.end(), + [callerID](const auto &a){ return a.first == callerID; }); + if(it != entries.end()) { + entries.erase(it); + } + } + return true; } diff --git a/taglib/matroska/matroskaseekhead.h b/taglib/matroska/matroskaseekhead.h index c9c23034..0775cf1e 100644 --- a/taglib/matroska/matroskaseekhead.h +++ b/taglib/matroska/matroskaseekhead.h @@ -23,17 +23,19 @@ #ifndef DO_NOT_DOCUMENT #include "matroskaelement.h" -#include "tbytevector.h" #include "tlist.h" namespace TagLib { class File; + class ByteVector; + namespace Matroska { class SeekHead : public Element { public: explicit SeekHead(offset_t segmentDataOffset); ~SeekHead() override = default; + bool isValid(TagLib::File &file) const; 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 19c32800..1c0e91b5 100644 --- a/taglib/matroska/matroskasegment.cpp +++ b/taglib/matroska/matroskasegment.cpp @@ -38,11 +38,10 @@ ByteVector Matroska::Segment::renderInternal() bool Matroska::Segment::render() { - auto beforeSize = sizeLength; + const auto beforeSize = sizeLength; auto data = renderInternal(); setNeedsRender(false); - auto afterSize = data.size(); - if(afterSize != beforeSize) { + if(auto afterSize = data.size(); afterSize != beforeSize) { sizeLength = 8; data = renderInternal(); setNeedsRender(false); diff --git a/taglib/matroska/matroskasimpletag.cpp b/taglib/matroska/matroskasimpletag.cpp index 2c5209fa..a76833bd 100644 --- a/taglib/matroska/matroskasimpletag.cpp +++ b/taglib/matroska/matroskasimpletag.cpp @@ -21,7 +21,6 @@ #include "matroskasimpletag.h" #include #include "matroskatag.h" -#include "tstring.h" #include "tbytevector.h" using namespace TagLib; @@ -29,16 +28,17 @@ using namespace TagLib; class Matroska::SimpleTag::SimpleTagPrivate { public: - explicit SimpleTagPrivate(const String &name, const String& value, + explicit SimpleTagPrivate(const String &name, const String &value, TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage, unsigned long long trackUid) : value(value), name(name), language(language), trackUid(trackUid), targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {} - explicit SimpleTagPrivate(const String &name, const ByteVector& value, + explicit SimpleTagPrivate(const String &name, const ByteVector &value, TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage, unsigned long long trackUid) : value(value), name(name), language(language), trackUid(trackUid), targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {} + const std::variant value; const String name; const String language; @@ -74,11 +74,11 @@ Matroska::SimpleTag::SimpleTag(const SimpleTag &other) : { } -Matroska::SimpleTag::SimpleTag(SimpleTag&& other) noexcept = default; +Matroska::SimpleTag::SimpleTag(SimpleTag &&other) noexcept = default; Matroska::SimpleTag::~SimpleTag() = default; -Matroska::SimpleTag &Matroska::SimpleTag::operator=(SimpleTag &&other) = default; +Matroska::SimpleTag &Matroska::SimpleTag::operator=(SimpleTag &&other) noexcept = default; Matroska::SimpleTag &Matroska::SimpleTag::operator=(const SimpleTag &other) { diff --git a/taglib/matroska/matroskasimpletag.h b/taglib/matroska/matroskasimpletag.h index faff96e0..4edd8b45 100644 --- a/taglib/matroska/matroskasimpletag.h +++ b/taglib/matroska/matroskasimpletag.h @@ -22,11 +22,13 @@ #define TAGLIB_MATROSKASIMPLETAG_H #include -#include "tag.h" + +#include "tstring.h" namespace TagLib { class String; class ByteVector; + namespace Matroska { //! Attribute of Matroska metadata. class TAGLIB_EXPORT SimpleTag @@ -89,7 +91,7 @@ namespace TagLib { /*! * Moves the contents of \a other into this item. */ - SimpleTag &operator=(SimpleTag &&other); + SimpleTag &operator=(SimpleTag &&other) noexcept; /*! * Exchanges the content of the simple tag with the content of \a other. diff --git a/taglib/matroska/matroskatag.cpp b/taglib/matroska/matroskatag.cpp index d2b5b6be..c9d260e7 100644 --- a/taglib/matroska/matroskatag.cpp +++ b/taglib/matroska/matroskatag.cpp @@ -22,7 +22,6 @@ #include #include #include -#include "matroskasimpletag.h" #include "ebmlmasterelement.h" #include "ebmlstringelement.h" #include "ebmlbinaryelement.h" @@ -30,7 +29,6 @@ #include "ebmluintelement.h" #include "ebmlutils.h" #include "tpropertymap.h" -#include "tlist.h" using namespace TagLib; @@ -95,7 +93,7 @@ void Matroska::Tag::removeSimpleTag(const String &name, SimpleTag::TargetTypeValue targetTypeValue, unsigned long long trackUid) { - auto it = std::find_if(d->tags.begin(), d->tags.end(), + const auto it = std::find_if(d->tags.begin(), d->tags.end(), [&name, targetTypeValue, trackUid](const SimpleTag &t) { return t.name() == name && t.targetTypeValue() == targetTypeValue && t.trackUid() == trackUid; @@ -118,14 +116,14 @@ const Matroska::SimpleTagsList &Matroska::Tag::simpleTagsList() const return d->tags; } -void Matroska::Tag::setSegmentTitle(const String& title) +void Matroska::Tag::setSegmentTitle(const String &title) { d->segmentTitle = title; } bool Matroska::Tag::setTag(const String &key, const String &value) { - bool found = d->setTag(key, value); + const bool found = d->setTag(key, value); if(found) { setNeedsRender(true); } @@ -198,7 +196,7 @@ String Matroska::Tag::genre() const unsigned int Matroska::Tag::year() const { - auto value = d->getTag("DATE"); + const auto value = d->getTag("DATE"); if(value.isEmpty()) return 0; auto list = value.split("-"); @@ -207,7 +205,7 @@ unsigned int Matroska::Tag::year() const unsigned int Matroska::Tag::track() const { - auto value = d->getTag("TRACKNUMBER"); + const auto value = d->getTag("TRACKNUMBER"); if(value.isEmpty()) return 0; auto list = value.split("-"); @@ -251,8 +249,8 @@ ByteVector Matroska::Tag::renderInternal() } for(const auto &list : targetList) { const auto &frontTag = list.front(); - auto targetTypeValue = frontTag.targetTypeValue(); - auto trackUid = frontTag.trackUid(); + const auto targetTypeValue = frontTag.targetTypeValue(); + const auto trackUid = frontTag.trackUid(); auto tag = EBML::make_unique_element(); // Build element @@ -326,7 +324,6 @@ namespace std::tuple("TRACKTOTAL", "TOTAL_PARTS", Matroska::SimpleTag::TargetTypeValue::Track, false), std::tuple("DISCTOTAL", "TOTAL_PARTS", Matroska::SimpleTag::TargetTypeValue::Album, true), std::tuple("DATE", "DATE_RELEASED", Matroska::SimpleTag::TargetTypeValue::Album, false), - // Todo - original date std::tuple("TITLESORT", "TITLESORT", Matroska::SimpleTag::TargetTypeValue::Track, false), std::tuple("ALBUMSORT", "TITLESORT", Matroska::SimpleTag::TargetTypeValue::Album, true), std::tuple("ARTISTSORT", "ARTISTSORT", Matroska::SimpleTag::TargetTypeValue::Track, false), @@ -360,14 +357,14 @@ namespace ); if(it != simpleTagsTranslation.end()) return { std::get<1>(*it), std::get<2>(*it), std::get<3>(*it) }; - if (!key.isEmpty()) + if(!key.isEmpty()) return { key, Matroska::SimpleTag::TargetTypeValue::Track, false }; return { String(), Matroska::SimpleTag::TargetTypeValue::None, false }; } String translateTag(const String &name, Matroska::SimpleTag::TargetTypeValue targetTypeValue) { - auto it = std::find_if(simpleTagsTranslation.cbegin(), + const auto it = std::find_if(simpleTagsTranslation.cbegin(), simpleTagsTranslation.cend(), [&name, targetTypeValue](const auto &t) { return name == std::get<1>(t) @@ -378,8 +375,8 @@ namespace ); return it != simpleTagsTranslation.end() ? String(std::get<0>(*it), String::UTF8) - : (targetTypeValue == Matroska::SimpleTag::TargetTypeValue::Track || - targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None) + : targetTypeValue == Matroska::SimpleTag::TargetTypeValue::Track || + targetTypeValue == Matroska::SimpleTag::TargetTypeValue::None ? name : String(); } @@ -414,7 +411,7 @@ String Matroska::Tag::TagPrivate::getTag(const String &key) const bool strict = std::get<2>(tpl); if(name.isEmpty()) return {}; - auto it = std::find_if(tags.begin(), tags.end(), + const auto it = std::find_if(tags.begin(), tags.end(), [&name, targetTypeValue, strict] (const SimpleTag &t) { return t.name() == name && t.type() == SimpleTag::StringType @@ -431,8 +428,8 @@ PropertyMap Matroska::Tag::properties() const PropertyMap properties; for(const auto &simpleTag : std::as_const(d->tags)) { if(simpleTag.type() == SimpleTag::StringType && simpleTag.trackUid() == 0) { - String key = translateTag(simpleTag.name(), simpleTag.targetTypeValue()); - if(!key.isEmpty()) + if(String key = translateTag(simpleTag.name(), simpleTag.targetTypeValue()); + !key.isEmpty()) properties[key].append(simpleTag.toString()); else properties.addUnsupportedData(simpleTag.name()); @@ -445,10 +442,9 @@ PropertyMap Matroska::Tag::setProperties(const PropertyMap &propertyMap) { // Remove all simple tags which would be returned in properties() for(auto it = d->tags.begin(); it != d->tags.end();) { - String key; if(it->type() == SimpleTag::StringType && it->trackUid() == 0 && - !(key = translateTag(it->name(), it->targetTypeValue())).isEmpty()) { + !translateTag(it->name(), it->targetTypeValue()).isEmpty()) { it = d->tags.erase(it); setNeedsRender(true); } @@ -474,10 +470,10 @@ PropertyMap Matroska::Tag::setProperties(const PropertyMap &propertyMap) return unsupportedProperties; } -void Matroska::Tag::removeUnsupportedProperties(const StringList& properties) +void Matroska::Tag::removeUnsupportedProperties(const StringList &properties) { if(d->removeSimpleTags( - [&properties](const SimpleTag& t) { + [&properties](const SimpleTag &t) { return properties.contains(t.name()); }) > 0) { setNeedsRender(true); @@ -497,7 +493,7 @@ StringList Matroska::Tag::complexPropertyKeys() const return keys; } -List Matroska::Tag::complexProperties(const String& key) const +List Matroska::Tag::complexProperties(const String &key) const { List props; if(key.upper() != "PICTURE") { // Pictures are handled at the file level @@ -529,7 +525,7 @@ List Matroska::Tag::complexProperties(const String& key) const return props; } -bool Matroska::Tag::setComplexProperties(const String& key, const List& value) +bool Matroska::Tag::setComplexProperties(const String &key, const List &value) { if(key.upper() == "PICTURE") { // Pictures are handled at the file level @@ -549,8 +545,8 @@ bool Matroska::Tag::setComplexProperties(const String& key, const List() == key && (property.contains("data") || property.contains("value") )) { SimpleTag::TargetTypeValue targetTypeValue; - Variant targetTypeValueVar = property.value("targetTypeValue", 0); - switch(targetTypeValueVar.type()) { + switch(Variant targetTypeValueVar = property.value("targetTypeValue", 0); + targetTypeValueVar.type()) { case Variant::UInt: targetTypeValue = static_cast(targetTypeValueVar.value()); break; @@ -564,8 +560,8 @@ bool Matroska::Tag::setComplexProperties(const String& key, const List(targetTypeValueVar.value()); } auto language = property.value("language").value(); - bool defaultLanguage = property.value("defaultLanguage", true).value(); - auto trackUid = property.value("trackUid", 0ULL).value(); + const bool defaultLanguage = property.value("defaultLanguage", true).value(); + const auto trackUid = property.value("trackUid", 0ULL).value(); d->tags.append(property.contains("data") ? SimpleTag(key, property.value("data").value(), targetTypeValue, language, defaultLanguage, trackUid) diff --git a/taglib/matroska/matroskatag.h b/taglib/matroska/matroskatag.h index 7af36d41..57aba7d7 100644 --- a/taglib/matroska/matroskatag.h +++ b/taglib/matroska/matroskatag.h @@ -24,27 +24,33 @@ #include #include "tag.h" -#include "tstring.h" #include "tlist.h" -#include "matroskafile.h" #include "matroskaelement.h" #include "matroskasimpletag.h" namespace TagLib { class File; + namespace EBML { class MkTags; } namespace Matroska { + //! List of tag attributes. using SimpleTagsList = List; + + //! Matroska tag implementation. class TAGLIB_EXPORT Tag : public TagLib::Tag #ifndef DO_NOT_DOCUMENT , private Element #endif { public: + /*! + * Constructs a Matroska tag. + */ Tag(); + ~Tag() override; String title() const override; String artist() const override; @@ -63,7 +69,7 @@ namespace TagLib { bool isEmpty() const override; PropertyMap properties() const override; PropertyMap setProperties(const PropertyMap &propertyMap) override; - void removeUnsupportedProperties(const StringList& properties) override; + void removeUnsupportedProperties(const StringList &properties) override; /*! * Returns the names of the binary simple tags. @@ -86,12 +92,27 @@ namespace TagLib { * * Returns \c true if \c key can be stored as binary simple tags. */ - bool setComplexProperties(const String& key, const List& value) override; + bool setComplexProperties(const String &key, const List &value) override; + /*! + * Add a tag attribute. + */ void addSimpleTag(const SimpleTag &tag); + + /*! + * Remove a tag attribute. + */ void removeSimpleTag(const String &name, SimpleTag::TargetTypeValue targetTypeValue, unsigned long long trackUid = 0); + + /*! + * Remove all tag attributes. + */ void clearSimpleTags(); + + /*! + * Get list of all tag attributes. + */ const SimpleTagsList &simpleTagsList() const; private: diff --git a/tests/test_matroska.cpp b/tests/test_matroska.cpp index a9d178b3..f932039f 100644 --- a/tests/test_matroska.cpp +++ b/tests/test_matroska.cpp @@ -1002,7 +1002,7 @@ public: void testChapters() { const Matroska::ChapterEdition edition1( - List{ + List{ Matroska::Chapter( 0, 40000, List{