Matroska: Fix issues reported by static analysis, formatting, docs

This commit is contained in:
Urs Fleisch
2025-11-16 16:12:54 +01:00
parent b625be5690
commit 607cd5bdf4
57 changed files with 624 additions and 677 deletions

View File

@@ -20,6 +20,7 @@
#include "ebmlbinaryelement.h"
#include "ebmlutils.h"
#include "tfile.h"
using namespace TagLib;

View File

@@ -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;

View File

@@ -36,8 +36,6 @@
#include "tdebug.h"
#include "tutils.h"
#include <cstdint>
using namespace TagLib;
#define RETURN_ELEMENT_FOR_CASE(eid) \
@@ -46,7 +44,7 @@ using namespace TagLib;
std::unique_ptr<EBML::Element> 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<uint32_t>(id);
const auto uintId = static_cast<uint32_t>(id);
uint32_t data = byteOrder == Utils::LittleEndian ? Utils::byteSwap(uintId) : uintId;
return ByteVector(reinterpret_cast<char *>(&data) + (4 - numBytes), numBytes);
}

View File

@@ -22,233 +22,232 @@
#define TAGLIB_EBMLELEMENT_H
#ifndef DO_NOT_DOCUMENT
#include <cstdint>
#include <memory>
#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<Element> 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 <Element::Id ID>
struct GetElementTypeById;
template <> struct GetElementTypeById<Element::Id::EBMLHeader> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::DocType> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::DocTypeVersion> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkSegment> { using type = MkSegment; };
template <> struct GetElementTypeById<Element::Id::MkInfo> { using type = MkInfo; };
template <> struct GetElementTypeById<Element::Id::MkTracks> { using type = MkTracks; };
template <> struct GetElementTypeById<Element::Id::MkTags> { using type = MkTags; };
template <> struct GetElementTypeById<Element::Id::MkAttachments> { using type = MkAttachments; };
template <> struct GetElementTypeById<Element::Id::MkTag> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkTagTargets> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkSimpleTag> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFile> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkSeek> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkTrackEntry> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkAudio> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCuePoint> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCueTrackPositions> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCueReference> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCluster> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCues> { using type = MkCues; };
template <> struct GetElementTypeById<Element::Id::MkTagName> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkTagString> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileName> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileDescription> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkTagLanguage> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileMediaType> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::MkCodecID> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::MkTagTargetTypeValue> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkTagTrackUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkSeekPosition> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkTimestampScale> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkBitDepth> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChannels> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueTime> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueTrack> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueClusterPosition> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueRelativePosition> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueDuration> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueBlockNumber> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueCodecState> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueRefTime> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkTagsLanguageDefault> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileData> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkSeekID> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkTagBinary> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkCodecState> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkDuration> { using type = FloatElement; };
template <> struct GetElementTypeById<Element::Id::MkTitle> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkSamplingFrequency> { using type = FloatElement; };
template <> struct GetElementTypeById<Element::Id::MkSeekHead> { using type = MkSeekHead; };
template <> struct GetElementTypeById<Element::Id::MkChapters> { using type = MkChapters; };
template <> struct GetElementTypeById<Element::Id::MkEditionEntry> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkEditionUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkEditionFlagDefault> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkEditionFlagOrdered> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterAtom> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterTimeStart> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterTimeEnd> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterFlagHidden> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterDisplay> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkChapString> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkChapLanguage> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::VoidElement> { using type = VoidElement; };
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
const T *element_cast(const std::unique_ptr<Element> &ptr)
{
return static_cast<const T *>(ptr.get());
}
Element(Id id, int sizeLength, offset_t dataSize, offset_t) :
id(id), sizeLength(sizeLength), dataSize(dataSize)
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
std::unique_ptr<T> element_cast(std::unique_ptr<Element> &&ptr)
{
return std::unique_ptr<T>(static_cast<T *>(ptr.release()));
}
virtual ~Element() = default;
virtual bool read(File &file)
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
std::unique_ptr<T> make_unique_element(Element::Id id, int sizeLength, offset_t dataSize, offset_t offset)
{
skipData(file);
return true;
return std::make_unique<T>(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<Element> factory(File &file);
static unsigned int readId(File &file);
protected:
Id id;
int sizeLength;
offset_t dataSize;
};
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
std::unique_ptr<T> make_unique_element()
{
return std::make_unique<T>(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 <String::Type t>
class StringElement;
using UTF8StringElement = StringElement<String::UTF8>;
using Latin1StringElement = StringElement<String::Latin1>;
template <Element::Id ID>
struct GetElementTypeById;
template <> struct GetElementTypeById<Element::Id::EBMLHeader> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::DocType> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::DocTypeVersion> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkSegment> { using type = MkSegment; };
template <> struct GetElementTypeById<Element::Id::MkInfo> { using type = MkInfo; };
template <> struct GetElementTypeById<Element::Id::MkTracks> { using type = MkTracks; };
template <> struct GetElementTypeById<Element::Id::MkTags> { using type = MkTags; };
template <> struct GetElementTypeById<Element::Id::MkAttachments> { using type = MkAttachments; };
template <> struct GetElementTypeById<Element::Id::MkTag> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkTagTargets> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkSimpleTag> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFile> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkSeek> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkTrackEntry> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkAudio> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCuePoint> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCueTrackPositions> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCueReference> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCluster> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkCues> { using type = MkCues; };
template <> struct GetElementTypeById<Element::Id::MkTagName> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkTagString> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileName> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileDescription> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkTagLanguage> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileMediaType> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::MkCodecID> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::MkTagTargetTypeValue> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkTagTrackUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkSeekPosition> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkTimestampScale> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkBitDepth> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChannels> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueTime> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueTrack> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueClusterPosition> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueRelativePosition> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueDuration> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueBlockNumber> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueCodecState> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkCueRefTime> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkTagsLanguageDefault> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkAttachedFileData> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkSeekID> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkTagBinary> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkCodecState> { using type = BinaryElement; };
template <> struct GetElementTypeById<Element::Id::MkDuration> { using type = FloatElement; };
template <> struct GetElementTypeById<Element::Id::MkTitle> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkSamplingFrequency> { using type = FloatElement; };
template <> struct GetElementTypeById<Element::Id::MkSeekHead> { using type = MkSeekHead; };
template <> struct GetElementTypeById<Element::Id::MkChapters> { using type = MkChapters; };
template <> struct GetElementTypeById<Element::Id::MkEditionEntry> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkEditionUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkEditionFlagDefault> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkEditionFlagOrdered> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterAtom> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterUID> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterTimeStart> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterTimeEnd> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterFlagHidden> { using type = UIntElement; };
template <> struct GetElementTypeById<Element::Id::MkChapterDisplay> { using type = MasterElement; };
template <> struct GetElementTypeById<Element::Id::MkChapString> { using type = UTF8StringElement; };
template <> struct GetElementTypeById<Element::Id::MkChapLanguage> { using type = Latin1StringElement; };
template <> struct GetElementTypeById<Element::Id::VoidElement> { using type = VoidElement; };
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
const T *element_cast(const std::unique_ptr<Element> &ptr)
{
return static_cast<const T *>(ptr.get());
}
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
std::unique_ptr<T> element_cast(std::unique_ptr<Element> &&ptr)
{
return std::unique_ptr<T>(static_cast<T *>(ptr.release()));
}
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
std::unique_ptr<T> make_unique_element(Element::Id id, int sizeLength, offset_t dataSize, offset_t offset)
{
return std::make_unique<T>(id, sizeLength, dataSize, offset);
}
template <Element::Id ID, typename T=typename GetElementTypeById<ID>::type>
std::unique_ptr<T> make_unique_element()
{
return std::make_unique<T>(ID, 0, 0, 0);
}
}
#endif

View File

@@ -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;

View File

@@ -40,18 +40,12 @@ namespace TagLib {
using FloatVariantType = std::variant<std::monostate, float, double>;
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; }

View File

@@ -27,14 +27,14 @@ using namespace TagLib;
EBML::MasterElement::~MasterElement() = default;
void EBML::MasterElement::appendElement(std::unique_ptr<Element>&& element)
void EBML::MasterElement::appendElement(std::unique_ptr<Element> &&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> 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;

View File

@@ -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> &&element);
std::list<std::unique_ptr<Element>>::iterator begin() { return elements.begin(); }
std::list<std::unique_ptr<Element>>::iterator end() { return elements.end(); }
std::list<std::unique_ptr<Element>>::const_iterator begin() const { return elements.begin(); }
std::list<std::unique_ptr<Element>>::const_iterator end() const { return elements.end(); }
std::list<std::unique_ptr<Element>>::const_iterator cbegin() const { return elements.cbegin(); }
std::list<std::unique_ptr<Element>>::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> &&element);
std::list<std::unique_ptr<Element>>::iterator begin() { return elements.begin(); }
std::list<std::unique_ptr<Element>>::iterator end() { return elements.end(); }
std::list<std::unique_ptr<Element>>::const_iterator begin() const { return elements.begin(); }
std::list<std::unique_ptr<Element>>::const_iterator end() const { return elements.end(); }
std::list<std::unique_ptr<Element>>::const_iterator cbegin() const { return elements.cbegin(); }
std::list<std::unique_ptr<Element>>::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<std::unique_ptr<Element>> elements;
};
protected:
offset_t offset;
offset_t padding = 0;
offset_t minRenderSize = 0;
std::list<std::unique_ptr<Element>> elements;
};
}
}
#endif

View File

@@ -27,7 +27,7 @@
using namespace TagLib;
std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse()
std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse() const
{
auto attachments = std::make_unique<Matroska::Attachments>();
attachments->setOffset(offset);
@@ -42,17 +42,16 @@ std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse()
const String *mediaType = nullptr;
const ByteVector *data = nullptr;
Matroska::AttachedFile::UID uid = 0;
auto attachedFile = element_cast<Id::MkAttachedFile>(element);
const auto attachedFile = element_cast<Id::MkAttachedFile>(element);
for(const auto &attachedFileChild : *attachedFile) {
Id id = attachedFileChild->getId();
if(id == Id::MkAttachedFileName)
filename = &(element_cast<Id::MkAttachedFileName>(attachedFileChild)->getValue());
if(const Id id = attachedFileChild->getId(); id == Id::MkAttachedFileName)
filename = &element_cast<Id::MkAttachedFileName>(attachedFileChild)->getValue();
else if(id == Id::MkAttachedFileData)
data = &(element_cast<Id::MkAttachedFileData>(attachedFileChild)->getValue());
data = &element_cast<Id::MkAttachedFileData>(attachedFileChild)->getValue();
else if(id == Id::MkAttachedFileDescription)
description = &(element_cast<Id::MkAttachedFileDescription>(attachedFileChild)->getValue());
description = &element_cast<Id::MkAttachedFileDescription>(attachedFileChild)->getValue();
else if(id == Id::MkAttachedFileMediaType)
mediaType = &(element_cast<Id::MkAttachedFileMediaType>(attachedFileChild)->getValue());
mediaType = &element_cast<Id::MkAttachedFileMediaType>(attachedFileChild)->getValue();
else if(id == Id::MkAttachedFileUID)
uid = element_cast<Id::MkAttachedFileUID>(attachedFileChild)->getValue();
}

View File

@@ -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<Matroska::Attachments> parse();
MasterElement(Id::MkAttachments, 0, 0, 0) {}
std::unique_ptr<Matroska::Attachments> parse() const;
};
}
}

View File

@@ -31,7 +31,7 @@
using namespace TagLib;
std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse() const
{
auto chapters = std::make_unique<Matroska::Chapters>();
chapters->setOffset(offset);
@@ -45,10 +45,9 @@ std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
Matroska::ChapterEdition::UID editionUid = 0;
bool editionIsDefault = false;
bool editionIsOrdered = false;
auto edition = element_cast<Id::MkEditionEntry>(element);
const auto edition = element_cast<Id::MkEditionEntry>(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<Id::MkEditionUID>(editionChild)->getValue();
else if(id == Id::MkEditionFlagDefault)
editionIsDefault = element_cast<Id::MkEditionFlagDefault>(editionChild)->getValue() != 0;
@@ -60,10 +59,9 @@ std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
Matroska::Chapter::Time chapterTimeEnd = 0;
List<Matroska::Chapter::Display> chapterDisplays;
bool chapterHidden = false;
auto chapterAtom = element_cast<Id::MkChapterAtom>(editionChild);
const auto chapterAtom = element_cast<Id::MkChapterAtom>(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<Id::MkChapterUID>(chapterChild)->getValue();
else if(cid == Id::MkChapterTimeStart)
chapterTimeStart = element_cast<Id::MkChapterTimeStart>(chapterChild)->getValue();
@@ -72,12 +70,11 @@ std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse()
else if(cid == Id::MkChapterFlagHidden)
chapterHidden = element_cast<Id::MkChapterFlagHidden>(chapterChild)->getValue() != 0;
else if(cid == Id::MkChapterDisplay) {
auto display = element_cast<Id::MkChapterDisplay>(chapterChild);
const auto display = element_cast<Id::MkChapterDisplay>(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<Id::MkChapString>(displayChild)->getValue();
else if(did == Id::MkChapLanguage)
displayLanguage = element_cast<Id::MkChapLanguage>(displayChild)->getValue();

View File

@@ -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<Matroska::Chapters> parse();
MasterElement(Id::MkChapters, 0, 0, 0) {}
std::unique_ptr<Matroska::Chapters> parse() const;
};
}
}

View File

@@ -24,7 +24,7 @@
using namespace TagLib;
std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset)
std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset) const
{
auto cues = std::make_unique<Matroska::Cues>(segmentDataOffset);
cues->setOffset(offset);
@@ -34,19 +34,17 @@ std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset)
for(const auto &cuesChild : elements) {
if(cuesChild->getId() != Id::MkCuePoint)
continue;
auto cuePointElement = element_cast<Id::MkCuePoint>(cuesChild);
const auto cuePointElement = element_cast<Id::MkCuePoint>(cuesChild);
auto cuePoint = std::make_unique<Matroska::CuePoint>();
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<Id::MkCueTime>(cuePointChild)->getValue());
else if(id == Id::MkCueTrackPositions) {
auto cueTrack = std::make_unique<Matroska::CueTrack>();
auto cueTrackElement = element_cast<Id::MkCueTrackPositions>(cuePointChild);
const auto cueTrackElement = element_cast<Id::MkCueTrackPositions>(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<Id::MkCueTrack>(cueTrackChild)->getValue());
else if(trackId == Id::MkCueClusterPosition)
cueTrack->setClusterPosition(element_cast<Id::MkCueClusterPosition>(cueTrackChild)->getValue());
@@ -59,7 +57,7 @@ std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset)
else if(trackId == Id::MkCueCodecState)
cueTrack->setCodecState(element_cast<Id::MkCueCodecState>(cueTrackChild)->getValue());
else if(trackId == Id::MkCueReference) {
auto cueReference = element_cast<Id::MkCueReference>(cueTrackChild);
const auto cueReference = element_cast<Id::MkCueReference>(cueTrackChild);
for(const auto &cueReferenceChild : *cueReference) {
if(cueReferenceChild->getId() != Id::MkCueRefTime)
continue;

View File

@@ -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<Matroska::Cues> parse(offset_t segmentDataOffset);
std::unique_ptr<Matroska::Cues> parse(offset_t segmentDataOffset) const;
};
}
}

View File

@@ -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<Id::MkTimestampScale>(element)->getValue();
}
else if (id == Id::MkDuration) {
else if(id == Id::MkDuration) {
duration = element_cast<Id::MkDuration>(element)->getValueAsDouble();
}
else if (id == Id::MkTitle) {
else if(id == Id::MkTitle) {
title = element_cast<Id::MkTitle>(element)->getValue();
}
}

View File

@@ -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;
};
}
}

View File

@@ -25,7 +25,7 @@
using namespace TagLib;
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentDataOffset)
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentDataOffset) const
{
auto seekHead = std::make_unique<Matroska::SeekHead>(segmentDataOffset);
seekHead->setOffset(offset);
@@ -34,14 +34,13 @@ std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentData
for(const auto &element : elements) {
if(element->getId() != Id::MkSeek)
continue;
auto seekElement = element_cast<Id::MkSeek>(element);
const auto seekElement = element_cast<Id::MkSeek>(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<Id::MkSeekID>(seekElementChild)->getValue();
if(data.size() == 4)
if(const Id id = seekElementChild->getId(); id == Id::MkSeekID && !entryId) {
if(auto data = element_cast<Id::MkSeekID>(seekElementChild)->getValue();
data.size() == 4)
entryId = data.toUInt(true);
}
else if(id == Id::MkSeekPosition && !offset)

View File

@@ -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<Matroska::SeekHead> parse(offset_t segmentDataOffset);
std::unique_ptr<Matroska::SeekHead> parse(offset_t segmentDataOffset) const;
};
}
}

View File

@@ -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> 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<Id::MkSeekHead>(std::move(element));
if(!seekHead->read(file))
@@ -94,46 +93,46 @@ bool EBML::MkSegment::read(File &file)
return true;
}
std::unique_ptr<Matroska::Tag> EBML::MkSegment::parseTag()
std::unique_ptr<Matroska::Tag> EBML::MkSegment::parseTag() const
{
return tags ? tags->parse() : nullptr;
}
std::unique_ptr<Matroska::Attachments> EBML::MkSegment::parseAttachments()
std::unique_ptr<Matroska::Attachments> EBML::MkSegment::parseAttachments() const
{
return attachments ? attachments->parse() : nullptr;
}
std::unique_ptr<Matroska::Chapters> EBML::MkSegment::parseChapters()
std::unique_ptr<Matroska::Chapters> EBML::MkSegment::parseChapters() const
{
return chapters ? chapters->parse() : nullptr;
}
std::unique_ptr<Matroska::SeekHead> EBML::MkSegment::parseSeekHead()
std::unique_ptr<Matroska::SeekHead> EBML::MkSegment::parseSeekHead() const
{
return seekHead ? seekHead->parse(segmentDataOffset()) : nullptr;
}
std::unique_ptr<Matroska::Cues> EBML::MkSegment::parseCues()
std::unique_ptr<Matroska::Cues> EBML::MkSegment::parseCues() const
{
return cues ? cues->parse(segmentDataOffset()) : nullptr;
}
std::unique_ptr<Matroska::Segment> EBML::MkSegment::parseSegment()
std::unique_ptr<Matroska::Segment> EBML::MkSegment::parseSegment() const
{
return std::make_unique<Matroska::Segment>(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);
}
}

View File

@@ -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<Matroska::Tag> parseTag();
std::unique_ptr<Matroska::Attachments> parseAttachments();
std::unique_ptr<Matroska::Chapters> parseChapters();
std::unique_ptr<Matroska::SeekHead> parseSeekHead();
std::unique_ptr<Matroska::Cues> parseCues();
std::unique_ptr<Matroska::Segment> parseSegment();
void parseInfo(Matroska::Properties *properties);
void parseTracks(Matroska::Properties *properties);
std::unique_ptr<Matroska::Tag> parseTag() const;
std::unique_ptr<Matroska::Attachments> parseAttachments() const;
std::unique_ptr<Matroska::Chapters> parseChapters() const;
std::unique_ptr<Matroska::SeekHead> parseSeekHead() const;
std::unique_ptr<Matroska::Cues> parseCues() const;
std::unique_ptr<Matroska::Segment> parseSegment() const;
void parseInfo(Matroska::Properties *properties) const;
void parseTracks(Matroska::Properties *properties) const;
private:
std::unique_ptr<MkTags> tags;

View File

@@ -28,7 +28,7 @@
using namespace TagLib;
std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
std::unique_ptr<Matroska::Tag> EBML::MkTags::parse() const
{
auto mTag = std::make_unique<Matroska::Tag>();
mTag->setOffset(offset);
@@ -39,14 +39,13 @@ std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
for(const auto &tagsChild : elements) {
if(tagsChild->getId() != Id::MkTag)
continue;
auto tag = element_cast<Id::MkTag>(tagsChild);
const auto tag = element_cast<Id::MkTag>(tagsChild);
List<const MasterElement *> simpleTags;
const MasterElement *targets = nullptr;
// Identify the <Targets> element and the <SimpleTag> 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<Id::MkTagTargets>(tagChild);
else if(tagChildId == Id::MkSimpleTag)
simpleTags.append(element_cast<Id::MkSimpleTag>(tagChild));
@@ -57,8 +56,7 @@ std::unique_ptr<Matroska::Tag> 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<Matroska::SimpleTag::TargetTypeValue>(
element_cast<Id::MkTagTargetTypeValue>(targetsChild)->getValue()
@@ -71,7 +69,7 @@ std::unique_ptr<Matroska::Tag> EBML::MkTags::parse()
}
// Parse each <SimpleTag>
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<Matroska::Tag> 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<Id::MkTagName>(simpleTagChild)->getValue();
else if(id == Id::MkTagString && !tagValueString)
tagValueString = &(element_cast<Id::MkTagString>(simpleTagChild)->getValue());
tagValueString = &element_cast<Id::MkTagString>(simpleTagChild)->getValue();
else if(id == Id::MkTagBinary && !tagValueBinary)
tagValueBinary = &(element_cast<Id::MkTagBinary>(simpleTagChild)->getValue());
tagValueBinary = &element_cast<Id::MkTagBinary>(simpleTagChild)->getValue();
else if(id == Id::MkTagsTagLanguage && language.isEmpty())
language = element_cast<Id::MkTagsTagLanguage>(simpleTagChild)->getValue();
else if(id == Id::MkTagsLanguageDefault)

View File

@@ -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<Matroska::Tag> parse();
std::unique_ptr<Matroska::Tag> parse() const;
};
}
}

View File

@@ -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<Id::MkTrackEntry>(element);
const auto trackEntry = element_cast<Id::MkTrackEntry>(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<Id::MkCodecID>(trackEntryChild)->getValue();
else if(trackEntryChildId == Id::MkAudio) {
auto audio = element_cast<Id::MkAudio>(trackEntryChild);
const auto audio = element_cast<Id::MkAudio>(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<Id::MkSamplingFrequency>(audioChild)->getValueAsDouble();
else if(audioChildId == Id::MkBitDepth)
bitDepth = element_cast<Id::MkBitDepth>(audioChild)->getValue();

View File

@@ -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;
};
}
}

View File

@@ -21,15 +21,13 @@
#include "ebmlstringelement.h"
#include <string>
#include "tfile.h"
#include "tstring.h"
#include "tbytevector.h"
#include "tdebug.h"
#include "ebmlutils.h"
using namespace TagLib;
template <String::Type t>
bool EBML::StringElement<t>::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<t>::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<String::UTF8>::read(File &file);
template bool EBML::StringElement<String::Latin1>::read(File &file);
template <String::Type t>
ByteVector EBML::StringElement<t>::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<unsigned int>(dataSize)));
return buffer;
}
template ByteVector EBML::StringElement<String::UTF8>::render();
template ByteVector EBML::StringElement<String::Latin1>::render();

View File

@@ -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 <String::Type t>
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<String::UTF8>;
using Latin1StringElement = StringElement<String::Latin1>;
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) {}
};
}
}

View File

@@ -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<char *>(&value) + (sizeof(value) - dataSize), dataSize));
buffer.append(ByteVector(reinterpret_cast<char *>(&val) + (sizeof(val) - dataSize), dataSize));
return buffer;
}

View File

@@ -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;

View File

@@ -18,16 +18,11 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <random>
#include "ebmlutils.h"
#include "ebmlelement.h"
#include <random>
#include "tbytevector.h"
#include "matroskafile.h"
#include "tdebug.h"
#include "tutils.h"
#include "taglib.h"
using namespace TagLib;
std::unique_ptr<EBML::Element> EBML::findElement(File &file, Element::Id id, offset_t maxOffset)
@@ -63,8 +58,8 @@ std::pair<int, T> EBML::readVINT(File &file)
if(nb_bytes > 1)
buffer.append(file.readBlock(nb_bytes - 1));
int bits_to_shift = static_cast<int>(sizeof(T) * 8) - 7 * nb_bytes;
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift;
const int bitsToShift = static_cast<int>(sizeof(T) * 8) - 7 * nb_bytes;
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
return { nb_bytes, static_cast<T>(buffer.toLongLong(true)) & mask };
}
namespace TagLib::EBML {
@@ -82,8 +77,8 @@ std::pair<int, T> EBML::parseVINT(const ByteVector &buffer)
if(!numBytes)
return {0, 0};
int bits_to_shift = static_cast<int>(sizeof(T) * 8) - 7 * numBytes;
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bits_to_shift;
const int bitsToShift = static_cast<int>(sizeof(T) * 8) - 7 * numBytes;
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
return { numBytes, static_cast<T>(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)

View File

@@ -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<unsigned int>(id);
const auto uintId = static_cast<unsigned int>(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;
}
}
}

View File

@@ -19,11 +19,10 @@
***************************************************************************/
#include "ebmlvoidelement.h"
#include <algorithm>
#include "ebmlutils.h"
#include "tbytevector.h"
#include <algorithm>
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)

View File

@@ -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:

View File

@@ -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)
{

View File

@@ -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.

View File

@@ -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 <memory>
#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<EBML::Element::Id::MkAttachedFileMediaType>();
auto mediaTypeElement =
EBML::make_unique_element<EBML::Element::Id::MkAttachedFileMediaType>();
mediaTypeElement->setValue(attachedFile.mediaType());
attachedFileElement->appendElement(std::move(mediaTypeElement));
// Description
const String &description = attachedFile.description();
if(!description.isEmpty()) {
auto descriptionElement = EBML::make_unique_element<EBML::Element::Id::MkAttachedFileDescription>();
if(const String &description = attachedFile.description(); !description.isEmpty()) {
auto descriptionElement =
EBML::make_unique_element<EBML::Element::Id::MkAttachedFileDescription>();
descriptionElement->setValue(description);
attachedFileElement->appendElement(std::move(descriptionElement));
}

View File

@@ -42,11 +42,13 @@ namespace TagLib {
#endif
{
public:
//! List of attached files.
using AttachedFileList = List<AttachedFile>;
//! 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.

View File

@@ -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::Display>& Matroska::Chapter::displayList() const
const List<Matroska::Chapter::Display> &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;
}

View File

@@ -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;
/*!

View File

@@ -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)
{

View File

@@ -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.

View File

@@ -24,7 +24,6 @@
***************************************************************************/
#include "matroskachapters.h"
#include <memory>
#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<EBML::Element::Id::MkEditionEntry>();
if(auto uid = chapterEdition.uid()) {
if(const auto uid = chapterEdition.uid()) {
auto uidElement = EBML::make_unique_element<EBML::Element::Id::MkEditionUID>();
uidElement->setValue(uid);
chapterEditionElement->appendElement(std::move(uidElement));
@@ -117,7 +116,7 @@ ByteVector Matroska::Chapters::renderInternal()
auto chapterElement = EBML::make_unique_element<EBML::Element::Id::MkChapterAtom>();
auto cuidElement = EBML::make_unique_element<EBML::Element::Id::MkChapterUID>();
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<EBML::Element::Id::MkChapterTimeStart>();
@@ -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<EBML::Element::Id::MkChapterDisplay>();
auto stringElement = EBML::make_unique_element<EBML::Element::Id::MkChapString>();

View File

@@ -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<ChapterEdition>;
//! Construct chapters.
Chapters();

View File

@@ -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<EBML::Element::Id::MkCueReference>();
for(auto reference : referenceTimes) {
for(const auto reference : referenceTimes) {
auto refTime = EBML::make_unique_element<EBML::Element::Id::MkCueRefTime>();
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> &&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> &&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;

View File

@@ -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> &&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<offset_t> relativePosition) { this->relativePosition = relativePosition; }
void setRelativePosition(std::optional<offset_t> relativePos) { relativePosition = relativePos; }
std::optional<offset_t> getRelativePosition() const { return relativePosition; }
void setCodecState(std::optional<offset_t> codecState) { this->codecState = codecState; }
void setCodecState(std::optional<offset_t> codecStatePos) { codecState = codecStatePos; }
std::optional<offset_t> getCodecState() const { return codecState; }
void setBlockNumber(std::optional<unsigned long long> blockNumber) { this->blockNumber = blockNumber; }
void setBlockNumber(std::optional<unsigned long long> blockNr) { blockNumber = blockNr; }
std::optional<unsigned long long> getBlockNumber() const { return blockNumber; }
void setDuration(std::optional<unsigned long long> duration) { this->duration = duration; }
void setDuration(std::optional<unsigned long long> segmentTicks) { duration = segmentTicks; }
std::optional<unsigned long long> getDuration() const { return duration; }
void addReferenceTime(unsigned long long refTime) { refTimes.append(refTime); }
const ReferenceTimeList &referenceTimes() const { return refTimes; }

View File

@@ -17,8 +17,9 @@
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <memory>
#include "matroskaelement.h"
#include <memory>
#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;
}

View File

@@ -25,11 +25,12 @@
#include <memory>
#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
{

View File

@@ -19,6 +19,7 @@
***************************************************************************/
#include "matroskafile.h"
#include <memory>
#include "matroskatag.h"
#include "matroskaattachments.h"
#include "matroskaattachedfile.h"
@@ -38,8 +39,6 @@
#include "tagutils.h"
#include "tpropertymap.h"
#include <memory>
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<VariantMap> 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<VariantM
auto fileName = property.value("fileName").value<String>();
auto uid = property.value("uid").value<unsigned long long>();
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<VariantM
else if(fileName.isEmpty() && key.find(".") != -1) {
fileName = key;
}
else if(!uid && ((uidKey = key.toULongLong(&ok))) && ok) {
else if(unsigned long long uidKey;
!uid && ((uidKey = key.toULongLong(&ok))) && ok) {
uid = uidKey;
}
if(fileName.isEmpty() && !mimeType.isEmpty()) {
int slashPos = mimeType.rfind('/');
const int slashPos = mimeType.rfind('/');
String ext = mimeType.substr(slashPos + 1);
if(ext == "jpeg") {
ext = "jpg";
@@ -364,10 +363,10 @@ Matroska::Chapters *Matroska::File::chapters(bool create) const
void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle)
{
offset_t fileLength = length();
const offset_t fileLength = length();
// Find the EBML Header
auto head = EBML::element_cast<EBML::Element::Id::EBMLHeader>(
const auto head = EBML::element_cast<EBML::Element::Id::EBMLHeader>(
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<EBML::MkSegment> segment(
const std::unique_ptr<EBML::MkSegment> segment(
EBML::element_cast<EBML::Element::Id::MkSegment>(
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<Properties>(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<EBML::Element::Id::DocType>(element)->getValue());
}
else if (id == EBML::Element::Id::DocTypeVersion) {
else if(id == EBML::Element::Id::DocTypeVersion) {
d->properties->setDocTypeVersion(static_cast<int>(
EBML::element_cast<EBML::Element::Id::DocTypeVersion>(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;

View File

@@ -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;

View File

@@ -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<int>(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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -21,7 +21,6 @@
#include "matroskasimpletag.h"
#include <variant>
#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<String, ByteVector> 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)
{

View File

@@ -22,11 +22,13 @@
#define TAGLIB_MATROSKASIMPLETAG_H
#include <memory>
#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.

View File

@@ -22,7 +22,6 @@
#include <algorithm>
#include <array>
#include <tuple>
#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<EBML::Element::Id::MkTag>();
// Build <Tag Targets> 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<VariantMap> Matroska::Tag::complexProperties(const String& key) const
List<VariantMap> Matroska::Tag::complexProperties(const String &key) const
{
List<VariantMap> props;
if(key.upper() != "PICTURE") { // Pictures are handled at the file level
@@ -529,7 +525,7 @@ List<VariantMap> Matroska::Tag::complexProperties(const String& key) const
return props;
}
bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMap>& value)
bool Matroska::Tag::setComplexProperties(const String &key, const List<VariantMap> &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<VariantMa
if(property.value("name").value<String>() == 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<SimpleTag::TargetTypeValue>(targetTypeValueVar.value<unsigned int>());
break;
@@ -564,8 +560,8 @@ bool Matroska::Tag::setComplexProperties(const String& key, const List<VariantMa
targetTypeValue = static_cast<SimpleTag::TargetTypeValue>(targetTypeValueVar.value<int>());
}
auto language = property.value("language").value<String>();
bool defaultLanguage = property.value("defaultLanguage", true).value<bool>();
auto trackUid = property.value("trackUid", 0ULL).value<unsigned long long>();
const bool defaultLanguage = property.value("defaultLanguage", true).value<bool>();
const auto trackUid = property.value("trackUid", 0ULL).value<unsigned long long>();
d->tags.append(property.contains("data")
? SimpleTag(key, property.value("data").value<ByteVector>(),
targetTypeValue, language, defaultLanguage, trackUid)

View File

@@ -24,27 +24,33 @@
#include <memory>
#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<SimpleTag>;
//! 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<VariantMap>& value) override;
bool setComplexProperties(const String &key, const List<VariantMap> &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:

View File

@@ -1002,7 +1002,7 @@ public:
void testChapters()
{
const Matroska::ChapterEdition edition1(
List{
List<Matroska::Chapter>{
Matroska::Chapter(
0, 40000,
List{