Matroska: Avoid inlined header methods, only install public headers

This commit is contained in:
Urs Fleisch
2025-11-22 12:34:48 +01:00
parent 607cd5bdf4
commit 68a514f4a0
44 changed files with 624 additions and 180 deletions

View File

@@ -72,6 +72,7 @@ if(WITH_MATROSKA)
endif()
include_directories(${tag_HDR_DIRS})
set(tag_PRIVATE_HDRS)
set(tag_HDRS
tag.h
fileref.h
@@ -233,14 +234,13 @@ if(WITH_MATROSKA)
matroska/matroskachapter.h
matroska/matroskachapteredition.h
matroska/matroskachapters.h
matroska/matroskacues.h
matroska/matroskaelement.h
matroska/matroskafile.h
matroska/matroskaproperties.h
matroska/matroskaseekhead.h
matroska/matroskasegment.h
matroska/matroskasimpletag.h
matroska/matroskatag.h
)
set(tag_PRIVATE_HDRS ${tag_PRIVATE_HDRS}
matroska/ebml/ebmlbinaryelement.h
matroska/ebml/ebmlelement.h
matroska/ebml/ebmlmasterelement.h
@@ -257,6 +257,9 @@ if(WITH_MATROSKA)
matroska/ebml/ebmlfloatelement.h
matroska/ebml/ebmlutils.h
matroska/ebml/ebmlvoidelement.h
matroska/matroskacues.h
matroska/matroskaseekhead.h
matroska/matroskasegment.h
)
endif()
@@ -517,7 +520,7 @@ set(tag_LIB_SRCS
tagutils.cpp
)
add_library(tag ${tag_LIB_SRCS} ${tag_HDRS})
add_library(tag ${tag_LIB_SRCS} ${tag_HDRS} ${tag_PRIVATE_HDRS})
target_include_directories(tag INTERFACE
$<INSTALL_INTERFACE:include>

View File

@@ -21,9 +21,35 @@
#include "ebmlbinaryelement.h"
#include "ebmlutils.h"
#include "tfile.h"
#include "tdebug.h"
using namespace TagLib;
EBML::BinaryElement::BinaryElement(Id id, int sizeLength, offset_t dataSize):
Element(id, sizeLength, dataSize)
{
}
EBML::BinaryElement::BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t):
Element(id, sizeLength, dataSize)
{
}
EBML::BinaryElement::BinaryElement(Id id):
Element(id, 0, 0)
{
}
const ByteVector& EBML::BinaryElement::getValue() const
{
return value;
}
void EBML::BinaryElement::setValue(const ByteVector& val)
{
value = val;
}
bool EBML::BinaryElement::read(File &file)
{
value = file.readBlock(dataSize);

View File

@@ -27,19 +27,17 @@
namespace TagLib {
class File;
namespace EBML {
class BinaryElement : public Element
{
public:
BinaryElement(Id id, int sizeLength, offset_t dataSize) :
Element(id, sizeLength, dataSize) {}
BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
Element(id, sizeLength, dataSize) {}
explicit BinaryElement(Id id) :
Element(id, 0, 0) {}
BinaryElement(Id id, int sizeLength, offset_t dataSize);
BinaryElement(Id id, int sizeLength, offset_t dataSize, offset_t);
explicit BinaryElement(Id id);
const ByteVector &getValue() const { return value; }
void setValue(const ByteVector &val) { value = val; }
const ByteVector &getValue() const;
void setValue(const ByteVector &val);
bool read(File &file) override;
ByteVector render() override;

View File

@@ -148,16 +148,54 @@ unsigned int EBML::Element::readId(File &file)
return buffer.toUInt(true);
}
EBML::Element::Element(Id id, int sizeLength, offset_t dataSize):
id(id), sizeLength(sizeLength), dataSize(dataSize)
{
}
EBML::Element::Element(Id id, int sizeLength, offset_t dataSize, offset_t):
id(id), sizeLength(sizeLength), dataSize(dataSize)
{
}
EBML::Element::~Element() = default;
bool EBML::Element::read(File& file)
{
skipData(file);
return true;
}
void EBML::Element::skipData(File &file)
{
file.seek(dataSize, File::Position::Current);
}
EBML::Element::Id EBML::Element::getId() const
{
return id;
}
offset_t EBML::Element::headSize() const
{
return idSize(id) + sizeLength;
}
offset_t EBML::Element::getSize() const
{
return headSize() + dataSize;
}
int EBML::Element::getSizeLength() const
{
return sizeLength;
}
int64_t EBML::Element::getDataSize() const
{
return dataSize;
}
ByteVector EBML::Element::render()
{
ByteVector buffer = renderId();

View File

@@ -106,22 +106,17 @@ namespace TagLib
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;
}
Element(Id id, int sizeLength, offset_t dataSize);
Element(Id id, int sizeLength, offset_t dataSize, offset_t);
virtual ~Element();
virtual bool read(File &file);
void skipData(File &file);
Id getId() const { return id; }
Id getId() const;
offset_t headSize() const;
offset_t getSize() const { return headSize() + dataSize; }
int getSizeLength() const { return sizeLength; }
int64_t getDataSize() const { return dataSize; }
offset_t getSize() const;
int getSizeLength() const;
int64_t getDataSize() const;
ByteVector renderId() const;
virtual ByteVector render();
static std::unique_ptr<Element> factory(File &file);

View File

@@ -31,6 +31,24 @@
using namespace TagLib;
EBML::FloatElement::FloatElement(Id id, int sizeLength, offset_t dataSize):
Element(id, sizeLength, dataSize)
{
}
EBML::FloatElement::FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t):
Element(id, sizeLength, dataSize)
{
}
EBML::FloatElement::FloatElement(Id id):
FloatElement(id, 0, 0)
{
}
EBML::FloatElement::FloatVariantType EBML::FloatElement::getValue() const
{ return value; }
double EBML::FloatElement::getValueAsDouble(double defaultValue) const
{
if(std::holds_alternative<double>(value)) {
@@ -42,6 +60,11 @@ double EBML::FloatElement::getValueAsDouble(double defaultValue) const
return defaultValue;
}
void EBML::FloatElement::setValue(FloatVariantType val)
{
value = val;
}
bool EBML::FloatElement::read(File &file)
{
const ByteVector buffer = file.readBlock(dataSize);

View File

@@ -39,16 +39,13 @@ namespace TagLib {
public:
using FloatVariantType = std::variant<std::monostate, float, double>;
FloatElement(Id id, int sizeLength, offset_t dataSize) :
Element(id, sizeLength, dataSize) {}
FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
Element(id, sizeLength, dataSize) {}
explicit FloatElement(Id id) :
FloatElement(id, 0, 0) {}
FloatElement(Id id, int sizeLength, offset_t dataSize);
FloatElement(Id id, int sizeLength, offset_t dataSize, offset_t);
explicit FloatElement(Id id);
FloatVariantType getValue() const { return value; }
FloatVariantType getValue() const;
double getValueAsDouble(double defaultValue = 0.0) const;
void setValue(FloatVariantType val) { value = val; }
void setValue(FloatVariantType val);
bool read(File &file) override;
ByteVector render() override;

View File

@@ -25,13 +25,78 @@
using namespace TagLib;
EBML::MasterElement::MasterElement(Id id, int sizeLength, offset_t dataSize, offset_t offset):
Element(id, sizeLength, dataSize), offset(offset)
{
}
EBML::MasterElement::MasterElement(Id id):
Element(id, 0, 0), offset(0)
{
}
EBML::MasterElement::~MasterElement() = default;
offset_t EBML::MasterElement::getOffset() const
{
return offset;
}
void EBML::MasterElement::appendElement(std::unique_ptr<Element> &&element)
{
elements.push_back(std::move(element));
}
std::list<std::unique_ptr<EBML::Element>>::iterator EBML::MasterElement::begin()
{
return elements.begin();
}
std::list<std::unique_ptr<EBML::Element>>::iterator EBML::MasterElement::end()
{
return elements.end();
}
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::begin() const
{
return elements.begin();
}
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::end() const
{
return elements.end();
}
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::cbegin() const
{
return elements.cbegin();
}
std::list<std::unique_ptr<EBML::Element>>::const_iterator EBML::MasterElement::cend() const
{
return elements.cend();
}
offset_t EBML::MasterElement::getPadding() const
{
return padding;
}
void EBML::MasterElement::setPadding(offset_t numBytes)
{
padding = numBytes;
}
offset_t EBML::MasterElement::getMinRenderSize() const
{
return minRenderSize;
}
void EBML::MasterElement::setMinRenderSize(offset_t minimumSize)
{
minRenderSize = minimumSize;
}
bool EBML::MasterElement::read(File &file)
{
const offset_t maxOffset = file.tell() + dataSize;

View File

@@ -22,9 +22,10 @@
#define TAGLIB_EBMLMASTERELEMENT_H
#ifndef DO_NOT_DOCUMENT
#include <list>
#include "ebmlelement.h"
#include "taglib.h"
#include "tlist.h"
namespace TagLib
{
@@ -34,26 +35,24 @@ namespace TagLib
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(Id id, int sizeLength, offset_t dataSize, offset_t offset);
explicit MasterElement(Id id);
~MasterElement() override;
offset_t getOffset() const { return offset; }
offset_t getOffset() const;
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; }
std::list<std::unique_ptr<Element>>::iterator begin();
std::list<std::unique_ptr<Element>>::iterator end();
std::list<std::unique_ptr<Element>>::const_iterator begin() const;
std::list<std::unique_ptr<Element>>::const_iterator end() const;
std::list<std::unique_ptr<Element>>::const_iterator cbegin() const;
std::list<std::unique_ptr<Element>>::const_iterator cend() const;
offset_t getPadding() const;
void setPadding(offset_t numBytes);
offset_t getMinRenderSize() const;
void setMinRenderSize(offset_t minimumSize);
protected:
offset_t offset;

View File

@@ -27,6 +27,21 @@
using namespace TagLib;
EBML::MkAttachments::MkAttachments(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset)
{
}
EBML::MkAttachments::MkAttachments(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset)
{
}
EBML::MkAttachments::MkAttachments():
MasterElement(Id::MkAttachments, 0, 0, 0)
{
}
std::unique_ptr<Matroska::Attachments> EBML::MkAttachments::parse() const
{
auto attachments = std::make_unique<Matroska::Attachments>();

View File

@@ -29,16 +29,14 @@ namespace TagLib {
namespace Matroska {
class Attachments;
}
namespace EBML {
class MkAttachments : public MasterElement
{
public:
MkAttachments(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset) {}
MkAttachments(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkAttachments, sizeLength, dataSize, offset) {}
MkAttachments() :
MasterElement(Id::MkAttachments, 0, 0, 0) {}
MkAttachments(int sizeLength, offset_t dataSize, offset_t offset);
MkAttachments(Id, int sizeLength, offset_t dataSize, offset_t offset);
MkAttachments();
std::unique_ptr<Matroska::Attachments> parse() const;
};

View File

@@ -31,6 +31,21 @@
using namespace TagLib;
EBML::MkChapters::MkChapters(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkChapters, sizeLength, dataSize, offset)
{
}
EBML::MkChapters::MkChapters(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkChapters, sizeLength, dataSize, offset)
{
}
EBML::MkChapters::MkChapters():
MasterElement(Id::MkChapters, 0, 0, 0)
{
}
std::unique_ptr<Matroska::Chapters> EBML::MkChapters::parse() const
{
auto chapters = std::make_unique<Matroska::Chapters>();

View File

@@ -34,16 +34,14 @@ namespace TagLib {
namespace Matroska {
class Chapters;
}
namespace EBML {
class MkChapters : public MasterElement
{
public:
MkChapters(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkChapters, sizeLength, dataSize, offset) {}
MkChapters(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkChapters, sizeLength, dataSize, offset) {}
MkChapters() :
MasterElement(Id::MkChapters, 0, 0, 0) {}
MkChapters(int sizeLength, offset_t dataSize, offset_t offset);
MkChapters(Id, int sizeLength, offset_t dataSize, offset_t offset);
MkChapters();
std::unique_ptr<Matroska::Chapters> parse() const;
};

View File

@@ -24,6 +24,21 @@
using namespace TagLib;
EBML::MkCues::MkCues(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
{
}
EBML::MkCues::MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkCues, sizeLength, dataSize, offset)
{
}
EBML::MkCues::MkCues():
MasterElement(Id::MkCues, 0, 0, 0)
{
}
std::unique_ptr<Matroska::Cues> EBML::MkCues::parse(offset_t segmentDataOffset) const
{
auto cues = std::make_unique<Matroska::Cues>(segmentDataOffset);

View File

@@ -34,12 +34,9 @@ namespace TagLib {
class MkCues : public MasterElement
{
public:
MkCues(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkCues, sizeLength, dataSize, offset) {}
MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkCues, sizeLength, dataSize, offset) {}
MkCues() :
MasterElement(Id::MkCues, 0, 0, 0) {}
MkCues(int sizeLength, offset_t dataSize, offset_t offset);
MkCues(Id, int sizeLength, offset_t dataSize, offset_t offset);
MkCues();
std::unique_ptr<Matroska::Cues> parse(offset_t segmentDataOffset) const;
};

View File

@@ -31,6 +31,21 @@
using namespace TagLib;
EBML::MkInfo::MkInfo(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkInfo, sizeLength, dataSize, offset)
{
}
EBML::MkInfo::MkInfo(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkInfo, sizeLength, dataSize, offset)
{
}
EBML::MkInfo::MkInfo():
MasterElement(Id::MkInfo, 0, 0, 0)
{
}
void EBML::MkInfo::parse(Matroska::Properties *properties) const
{
if(!properties)

View File

@@ -34,16 +34,14 @@ namespace TagLib {
namespace Matroska {
class Properties;
}
namespace EBML {
class MkInfo : public MasterElement
{
public:
MkInfo(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkInfo, sizeLength, dataSize, offset) {}
MkInfo(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkInfo, sizeLength, dataSize, offset) {}
MkInfo() :
MasterElement(Id::MkInfo, 0, 0, 0) {}
MkInfo(int sizeLength, offset_t dataSize, offset_t offset);
MkInfo(Id, int sizeLength, offset_t dataSize, offset_t offset);
MkInfo();
void parse(Matroska::Properties * properties) const;
};

View File

@@ -25,6 +25,21 @@
using namespace TagLib;
EBML::MkSeekHead::MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset)
{
}
EBML::MkSeekHead::MkSeekHead(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset)
{
}
EBML::MkSeekHead::MkSeekHead():
MasterElement(Id::MkSeekHead, 0, 0, 0)
{
}
std::unique_ptr<Matroska::SeekHead> EBML::MkSeekHead::parse(offset_t segmentDataOffset) const
{
auto seekHead = std::make_unique<Matroska::SeekHead>(segmentDataOffset);

View File

@@ -29,16 +29,14 @@ namespace TagLib {
namespace Matroska {
class SeekHead;
}
namespace EBML {
class MkSeekHead : public MasterElement
{
public:
MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset) {}
MkSeekHead(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkSeekHead, sizeLength, dataSize, offset) {}
MkSeekHead() :
MasterElement(Id::MkSeekHead, 0, 0, 0) {}
MkSeekHead(int sizeLength, offset_t dataSize, offset_t offset);
MkSeekHead(Id, int sizeLength, offset_t dataSize, offset_t offset);
MkSeekHead();
std::unique_ptr<Matroska::SeekHead> parse(offset_t segmentDataOffset) const;
};

View File

@@ -30,6 +30,16 @@
using namespace TagLib;
EBML::MkSegment::MkSegment(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkSegment, sizeLength, dataSize, offset)
{
}
EBML::MkSegment::MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkSegment, sizeLength, dataSize, offset)
{
}
EBML::MkSegment::~MkSegment() = default;
offset_t EBML::MkSegment::segmentDataOffset() const

View File

@@ -40,16 +40,13 @@ namespace TagLib {
class SeekHead;
class Segment;
}
namespace EBML {
class MkSegment : public MasterElement
{
public:
MkSegment(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkSegment, sizeLength, dataSize, offset)
{
}
MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkSegment, sizeLength, dataSize, offset) {}
MkSegment(int sizeLength, offset_t dataSize, offset_t offset);
MkSegment(Id, int sizeLength, offset_t dataSize, offset_t offset);
~MkSegment() override;
offset_t segmentDataOffset() const;

View File

@@ -28,6 +28,21 @@
using namespace TagLib;
EBML::MkTags::MkTags(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkTags, sizeLength, dataSize, offset)
{
}
EBML::MkTags::MkTags(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkTags, sizeLength, dataSize, offset)
{
}
EBML::MkTags::MkTags():
MasterElement(Id::MkTags, 0, 0, 0)
{
}
std::unique_ptr<Matroska::Tag> EBML::MkTags::parse() const
{
auto mTag = std::make_unique<Matroska::Tag>();

View File

@@ -34,12 +34,9 @@ namespace TagLib {
class MkTags : public MasterElement
{
public:
MkTags(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkTags, sizeLength, dataSize, offset) {}
MkTags(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkTags, sizeLength, dataSize, offset) {}
MkTags() :
MasterElement(Id::MkTags, 0, 0, 0) {}
MkTags(int sizeLength, offset_t dataSize, offset_t offset);
MkTags(Id, int sizeLength, offset_t dataSize, offset_t offset);
MkTags();
std::unique_ptr<Matroska::Tag> parse() const;
};

View File

@@ -31,6 +31,21 @@
using namespace TagLib;
EBML::MkTracks::MkTracks(int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkTracks, sizeLength, dataSize, offset)
{
}
EBML::MkTracks::MkTracks(Id, int sizeLength, offset_t dataSize, offset_t offset):
MasterElement(Id::MkTracks, sizeLength, dataSize, offset)
{
}
EBML::MkTracks::MkTracks():
MasterElement(Id::MkTracks, 0, 0, 0)
{
}
void EBML::MkTracks::parse(Matroska::Properties *properties) const
{
if(!properties)

View File

@@ -34,16 +34,14 @@ namespace TagLib {
namespace Matroska {
class Properties;
}
namespace EBML {
class MkTracks : public MasterElement
{
public:
MkTracks(int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkTracks, sizeLength, dataSize, offset) {}
MkTracks(Id, int sizeLength, offset_t dataSize, offset_t offset) :
MasterElement(Id::MkTracks, sizeLength, dataSize, offset) {}
MkTracks() :
MasterElement(Id::MkTracks, 0, 0, 0) {}
MkTracks(int sizeLength, offset_t dataSize, offset_t offset);
MkTracks(Id, int sizeLength, offset_t dataSize, offset_t offset);
MkTracks();
void parse(Matroska::Properties *properties) const;
};

View File

@@ -27,6 +27,22 @@
using namespace TagLib;
EBML::StringElement::StringElement(
String::Type stringEncoding, Id id, int sizeLength, offset_t dataSize):
Element(id, sizeLength, dataSize), encoding(stringEncoding)
{
}
const String& EBML::StringElement::getValue() const
{
return value;
}
void EBML::StringElement::setValue(const String& val)
{
value = val;
}
bool EBML::StringElement::read(File &file)
{
ByteVector buffer = file.readBlock(dataSize);
@@ -52,3 +68,33 @@ ByteVector EBML::StringElement::render()
buffer.append(ByteVector(string.data(), static_cast<unsigned int>(dataSize)));
return buffer;
}
EBML::UTF8StringElement::UTF8StringElement(Id id, int sizeLength, offset_t dataSize):
StringElement(String::UTF8, id, sizeLength, dataSize)
{
}
EBML::UTF8StringElement::UTF8StringElement(Id id, int sizeLength, offset_t dataSize, offset_t):
UTF8StringElement(id, sizeLength, dataSize)
{
}
EBML::UTF8StringElement::UTF8StringElement(Id id):
UTF8StringElement(id, 0, 0)
{
}
EBML::Latin1StringElement::Latin1StringElement(Id id, int sizeLength, offset_t dataSize):
StringElement(String::Latin1, id, sizeLength, dataSize)
{
}
EBML::Latin1StringElement::Latin1StringElement(Id id, int sizeLength, offset_t dataSize, offset_t):
Latin1StringElement(id, sizeLength, dataSize)
{
}
EBML::Latin1StringElement::Latin1StringElement(Id id):
Latin1StringElement(id, 0, 0)
{
}

View File

@@ -33,11 +33,10 @@ namespace TagLib {
class StringElement : public Element
{
public:
StringElement(String::Type stringEncoding, Id id, int sizeLength, offset_t dataSize) :
Element(id, sizeLength, dataSize), encoding(stringEncoding) {}
StringElement(String::Type stringEncoding, Id id, int sizeLength, offset_t dataSize);
const String &getValue() const { return value; }
void setValue(const String &val) { value = val; }
const String &getValue() const;
void setValue(const String &val);
bool read(File &file) override;
ByteVector render() override;
@@ -48,22 +47,16 @@ namespace TagLib {
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) {}
UTF8StringElement(Id id, int sizeLength, offset_t dataSize);
UTF8StringElement(Id id, int sizeLength, offset_t dataSize, offset_t);
explicit UTF8StringElement(Id id);
};
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) {}
Latin1StringElement(Id id, int sizeLength, offset_t dataSize);
Latin1StringElement(Id id, int sizeLength, offset_t dataSize, offset_t);
explicit Latin1StringElement(Id id);
};
}
}

View File

@@ -22,10 +22,36 @@
#include "ebmlutils.h"
#include "tbytevector.h"
#include "tfile.h"
#include "tutils.h"
#include "tdebug.h"
using namespace TagLib;
EBML::UIntElement::UIntElement(Id id, int sizeLength, offset_t dataSize):
Element(id, sizeLength, dataSize)
{
}
EBML::UIntElement::UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t):
Element(id, sizeLength, dataSize)
{
}
EBML::UIntElement::UIntElement(Id id):
UIntElement(id, 0, 0)
{
}
unsigned long long EBML::UIntElement::getValue() const
{
return value;
}
void EBML::UIntElement::setValue(unsigned long long val)
{
value = val;
}
bool EBML::UIntElement::read(File &file)
{
const ByteVector buffer = file.readBlock(dataSize);

View File

@@ -31,15 +31,12 @@ namespace TagLib {
class UIntElement : public Element
{
public:
UIntElement(Id id, int sizeLength, offset_t dataSize) :
Element(id, sizeLength, dataSize) {}
UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t) :
Element(id, sizeLength, dataSize) {}
explicit UIntElement(Id id) :
UIntElement(id, 0, 0) {}
UIntElement(Id id, int sizeLength, offset_t dataSize);
UIntElement(Id id, int sizeLength, offset_t dataSize, offset_t);
explicit UIntElement(Id id);
unsigned long long getValue() const { return value; }
void setValue(unsigned long long val) { value = val; }
unsigned long long getValue() const;
void setValue(unsigned long long val);
bool read(File &file) override;
ByteVector render() override;

View File

@@ -22,6 +22,8 @@
#include <random>
#include "tbytevector.h"
#include "matroskafile.h"
#include "tutils.h"
#include "tdebug.h"
using namespace TagLib;
@@ -43,6 +45,32 @@ std::unique_ptr<EBML::Element> EBML::findNextElement(File &file, offset_t maxOff
return file.tell() < maxOffset ? Element::factory(file) : nullptr;
}
template <int maxSizeLength>
unsigned int EBML::VINTSizeLength(uint8_t firstByte)
{
static_assert(maxSizeLength >= 1 && maxSizeLength <= 8);
if(!firstByte) {
debug("VINT with greater than 8 bytes not allowed");
return 0;
}
uint8_t mask = 0b10000000;
unsigned int numBytes = 1;
while(!(mask & firstByte)) {
numBytes++;
mask >>= 1;
}
if(numBytes > maxSizeLength) {
debug(Utils::formatString("VINT size length exceeds %i bytes", maxSizeLength));
return 0;
}
return numBytes;
}
namespace TagLib::EBML {
template unsigned int VINTSizeLength<4>(uint8_t firstByte);
template unsigned int VINTSizeLength<8>(uint8_t firstByte);
}
template <typename T>
std::pair<int, T> EBML::readVINT(File &file)
{
@@ -62,6 +90,7 @@ std::pair<int, T> EBML::readVINT(File &file)
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
return { nb_bytes, static_cast<T>(buffer.toLongLong(true)) & mask };
}
namespace TagLib::EBML {
template std::pair<int, offset_t> readVINT<offset_t>(File &file);
template std::pair<int, uint64_t> readVINT<uint64_t>(File &file);
@@ -81,6 +110,7 @@ std::pair<int, T> EBML::parseVINT(const ByteVector &buffer)
offset_t mask = 0xFFFFFFFFFFFFFFFF >> bitsToShift;
return { numBytes, static_cast<T>(buffer.toLongLong(true)) & mask };
}
namespace TagLib::EBML {
template std::pair<int, offset_t> parseVINT<offset_t>(const ByteVector &buffer);
template std::pair<int, uint64_t> parseVINT<uint64_t>(const ByteVector &buffer);

View File

@@ -24,8 +24,6 @@
#include <utility>
#include "taglib.h"
#include "tutils.h"
#include "tdebug.h"
#include "ebmlelement.h"
namespace TagLib {
@@ -33,34 +31,20 @@ namespace TagLib {
class ByteVector;
namespace EBML {
std::unique_ptr<Element> findElement(File &file, Element::Id id, offset_t maxOffset);
std::unique_ptr<Element> findNextElement(File &file, offset_t maxOffset);
template <int maxSizeLength>
constexpr unsigned int VINTSizeLength(uint8_t firstByte)
{
static_assert(maxSizeLength >= 1 && maxSizeLength <= 8);
if(!firstByte) {
debug("VINT with greater than 8 bytes not allowed");
return 0;
}
uint8_t mask = 0b10000000;
unsigned int numBytes = 1;
while(!(mask & firstByte)) {
numBytes++;
mask >>= 1;
}
if(numBytes > maxSizeLength) {
debug(Utils::formatString("VINT size length exceeds %i bytes", maxSizeLength));
return 0;
}
return numBytes;
}
unsigned int VINTSizeLength(uint8_t firstByte);
template <typename T>
std::pair<int, T> readVINT(File &file);
template <typename T>
std::pair<int, T> parseVINT(const ByteVector &buffer);
std::unique_ptr<Element> findElement(File &file, Element::Id id, offset_t maxOffset);
std::unique_ptr<Element> findNextElement(File &file, offset_t maxOffset);
ByteVector renderVINT(uint64_t number, int minSizeLength);
unsigned long long randomUID();
constexpr int minSize(uint64_t data)

View File

@@ -25,6 +25,21 @@
using namespace TagLib;
EBML::VoidElement::VoidElement(int sizeLength, offset_t dataSize):
Element(Id::VoidElement, sizeLength, dataSize)
{
}
EBML::VoidElement::VoidElement(Id, int sizeLength, offset_t dataSize, offset_t):
Element(Id::VoidElement, sizeLength, dataSize)
{
}
EBML::VoidElement::VoidElement():
Element(Id::VoidElement, 0, 0)
{
}
ByteVector EBML::VoidElement::render()
{
offset_t bytesNeeded = targetSize;

View File

@@ -32,12 +32,9 @@ namespace TagLib {
class VoidElement : public Element
{
public:
VoidElement(int sizeLength, offset_t dataSize) :
Element(Id::VoidElement, sizeLength, dataSize) {}
VoidElement(Id, int sizeLength, offset_t dataSize, offset_t) :
Element(Id::VoidElement, sizeLength, dataSize) {}
VoidElement() :
Element(Id::VoidElement, 0, 0) {}
VoidElement(int sizeLength, offset_t dataSize);
VoidElement(Id, int sizeLength, offset_t dataSize, offset_t);
VoidElement();
ByteVector render() override;
offset_t getTargetSize() const;

View File

@@ -27,6 +27,7 @@
namespace TagLib {
class String;
class ByteVector;
namespace Matroska {
//! Attached file embedded into a Matroska file.
class TAGLIB_EXPORT AttachedFile

View File

@@ -28,9 +28,11 @@
namespace TagLib {
class File;
namespace EBML {
class MkAttachments;
}
namespace Matroska {
class AttachedFile;
class File;

View File

@@ -37,6 +37,7 @@ namespace TagLib {
namespace EBML {
class MkChapters;
}
namespace Matroska {
class ChapterEdition;
class File;

View File

@@ -36,6 +36,8 @@ Matroska::Cues::Cues(offset_t segmentDataOffset) :
setNeedsRender(false);
}
Matroska::Cues::~Cues() = default;
ByteVector Matroska::Cues::renderInternal()
{
const auto beforeSize = sizeRenderedOrWritten();
@@ -141,8 +143,15 @@ void Matroska::Cues::addCuePoint(std::unique_ptr<CuePoint> &&cuePoint)
cuePoints.push_back(std::move(cuePoint));
}
const Matroska::Cues::CuePointList &Matroska::Cues::cuePointList()
{
return cuePoints;
}
Matroska::CuePoint::CuePoint() = default;
Matroska::CuePoint::~CuePoint() = default;
bool Matroska::CuePoint::isValid(TagLib::File &file, offset_t segmentDataOffset) const
{
for(const auto &track : cueTracks) {
@@ -157,6 +166,21 @@ void Matroska::CuePoint::addCueTrack(std::unique_ptr<CueTrack> &&cueTrack)
cueTracks.push_back(std::move(cueTrack));
}
const Matroska::CuePoint::CueTrackList &Matroska::CuePoint::cueTrackList() const
{
return cueTracks;
}
void Matroska::CuePoint::setTime(Time timestamp)
{
time = timestamp;
}
Matroska::CuePoint::Time Matroska::CuePoint::getTime() const
{
return time;
}
bool Matroska::CuePoint::adjustOffset(offset_t offset, offset_t delta)
{
bool ret = false;
@@ -166,6 +190,10 @@ bool Matroska::CuePoint::adjustOffset(offset_t offset, offset_t delta)
return ret;
}
Matroska::CueTrack::CueTrack() = default;
Matroska::CueTrack::~CueTrack() = default;
bool Matroska::CueTrack::isValid(TagLib::File &file, offset_t segmentDataOffset) const
{
if(!trackNumber) {
@@ -191,6 +219,76 @@ bool Matroska::CueTrack::isValid(TagLib::File &file, offset_t segmentDataOffset)
return true;
}
void Matroska::CueTrack::setTrackNumber(unsigned long long trackNr)
{
trackNumber = trackNr;
}
unsigned long long Matroska::CueTrack::getTrackNumber() const
{
return trackNumber;
}
void Matroska::CueTrack::setClusterPosition(offset_t clusterPos)
{
clusterPosition = clusterPos;
}
offset_t Matroska::CueTrack::getClusterPosition() const
{
return clusterPosition;
}
void Matroska::CueTrack::setRelativePosition(std::optional<offset_t> relativePos)
{
relativePosition = relativePos;
}
std::optional<offset_t> Matroska::CueTrack::getRelativePosition() const
{
return relativePosition;
}
void Matroska::CueTrack::setCodecState(std::optional<offset_t> codecStatePos)
{
codecState = codecStatePos;
}
std::optional<offset_t> Matroska::CueTrack::getCodecState() const
{
return codecState;
}
void Matroska::CueTrack::setBlockNumber(std::optional<unsigned long long> blockNr)
{
blockNumber = blockNr;
}
std::optional<unsigned long long> Matroska::CueTrack::getBlockNumber() const
{
return blockNumber;
}
void Matroska::CueTrack::setDuration(std::optional<unsigned long long> segmentTicks)
{
duration = segmentTicks;
}
std::optional<unsigned long long> Matroska::CueTrack::getDuration() const
{
return duration;
}
void Matroska::CueTrack::addReferenceTime(unsigned long long refTime)
{
refTimes.append(refTime);
}
const Matroska::CueTrack::ReferenceTimeList &Matroska::CueTrack::referenceTimes() const
{
return refTimes;
}
bool Matroska::CueTrack::adjustOffset(offset_t offset, offset_t delta)
{
bool ret = false;

View File

@@ -43,10 +43,10 @@ namespace TagLib {
public:
using CuePointList = std::list<std::unique_ptr<CuePoint>>;
explicit Cues(offset_t segmentDataOffset);
~Cues() override = default;
~Cues() override;
bool isValid(TagLib::File &file) const;
void addCuePoint(std::unique_ptr<CuePoint> &&cuePoint);
const CuePointList &cuePointList() { return cuePoints; }
const CuePointList &cuePointList();
bool sizeChanged(Element &caller, offset_t delta) override;
void write(TagLib::File &file) override;
@@ -64,12 +64,12 @@ namespace TagLib {
using CueTrackList = std::list<std::unique_ptr<CueTrack>>;
using Time = unsigned long long;
CuePoint();
~CuePoint() = default;
~CuePoint();
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 timestamp) { time = timestamp; }
Time getTime() const { return time; }
const CueTrackList &cueTrackList() const;
void setTime(Time timestamp);
Time getTime() const;
bool adjustOffset(offset_t offset, offset_t delta);
private:
@@ -81,23 +81,23 @@ namespace TagLib {
{
public:
using ReferenceTimeList = List<unsigned long long>;
CueTrack() = default;
~CueTrack() = default;
CueTrack();
~CueTrack();
bool isValid(TagLib::File &file, offset_t segmentDataOffset) const;
void setTrackNumber(unsigned long long trackNr) { trackNumber = trackNr; }
unsigned long long getTrackNumber() const { return trackNumber; }
void setClusterPosition(offset_t clusterPos) { clusterPosition = clusterPos; }
offset_t getClusterPosition() const { return clusterPosition; }
void setRelativePosition(std::optional<offset_t> relativePos) { relativePosition = relativePos; }
std::optional<offset_t> getRelativePosition() const { return relativePosition; }
void setCodecState(std::optional<offset_t> codecStatePos) { codecState = codecStatePos; }
std::optional<offset_t> getCodecState() const { return codecState; }
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> 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; }
void setTrackNumber(unsigned long long trackNr);
unsigned long long getTrackNumber() const;
void setClusterPosition(offset_t clusterPos);
offset_t getClusterPosition() const;
void setRelativePosition(std::optional<offset_t> relativePos);
std::optional<offset_t> getRelativePosition() const;
void setCodecState(std::optional<offset_t> codecStatePos);
std::optional<offset_t> getCodecState() const;
void setBlockNumber(std::optional<unsigned long long> blockNr);
std::optional<unsigned long long> getBlockNumber() const;
void setDuration(std::optional<unsigned long long> segmentTicks);
std::optional<unsigned long long> getDuration() const;
void addReferenceTime(unsigned long long refTime);
const ReferenceTimeList &referenceTimes() const;
bool adjustOffset(offset_t offset, offset_t delta);
private:

View File

@@ -33,6 +33,7 @@ namespace TagLib::EBML {
class MkTracks;
class MkInfo;
}
namespace TagLib::Matroska {
class File;

View File

@@ -36,6 +36,8 @@ Matroska::SeekHead::SeekHead(offset_t segmentDataOffset) :
setNeedsRender(false);
}
Matroska::SeekHead::~SeekHead() = default;
bool Matroska::SeekHead::isValid(TagLib::File &file) const
{
bool result = true;

View File

@@ -34,7 +34,7 @@ namespace TagLib {
{
public:
explicit SeekHead(offset_t segmentDataOffset);
~SeekHead() override = default;
~SeekHead() override;
bool isValid(TagLib::File &file) const;
void addEntry(const Element &element);

View File

@@ -20,6 +20,7 @@
#include "matroskasegment.h"
#include "ebmlutils.h"
#include "tbytevector.h"
using namespace TagLib;
@@ -31,6 +32,8 @@ Matroska::Segment::Segment(offset_t sizeLength, offset_t dataSize, offset_t leng
setSize(sizeLength);
}
Matroska::Segment::~Segment() = default;
ByteVector Matroska::Segment::renderInternal()
{
return EBML::renderVINT(dataSize, static_cast<int>(sizeLength));
@@ -61,3 +64,8 @@ bool Matroska::Segment::sizeChanged(Element &, offset_t delta)
setNeedsRender(true);
return true;
}
offset_t Matroska::Segment::dataOffset() const
{
return offset() + sizeLength;
}

View File

@@ -29,10 +29,10 @@ namespace TagLib::Matroska {
{
public:
Segment(offset_t sizeLength, offset_t dataSize, offset_t lengthOffset);
~Segment() override = default;
~Segment() override;
bool render() override;
bool sizeChanged(Element &caller, offset_t delta) override;
offset_t dataOffset() const { return offset() + sizeLength; }
offset_t dataOffset() const;
private:
ByteVector renderInternal() override;

View File

@@ -149,6 +149,10 @@
#include "trueaudioproperties.h"
#endif
#ifdef TAGLIB_WITH_MATROSKA
#include "matroskaattachedfile.h"
#include "matroskaattachments.h"
#include "matroskachapteredition.h"
#include "matroskachapters.h"
#include "matroskafile.h"
#include "matroskaproperties.h"
#include "matroskatag.h"
@@ -156,10 +160,6 @@
#include <cppunit/extensions/HelperMacros.h>
#include "matroskaattachedfile.h"
#include "matroskaattachments.h"
#include "matroskachapters.h"
using namespace std;
using namespace TagLib;
@@ -314,6 +314,9 @@ public:
CPPUNIT_ASSERT_EQUAL(classSize(0, true), sizeof(TagLib::Matroska::Element));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Matroska::Attachments));
CPPUNIT_ASSERT_EQUAL(classSize(1, true), sizeof(TagLib::Matroska::Chapters));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::Matroska::ChapterEdition));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::Matroska::Chapter));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::Matroska::Chapter::Display));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::Matroska::SimpleTag));
CPPUNIT_ASSERT_EQUAL(classSize(0, false), sizeof(TagLib::Matroska::AttachedFile));
#endif