Restructure FieldMapBasedTag to use CRTP

This commit is contained in:
Martchus 2017-03-07 00:02:59 +01:00
parent 11d881a41e
commit 138fa32f29
11 changed files with 181 additions and 167 deletions

View File

@ -8,6 +8,16 @@
namespace Media {
/*!
* \class Media::FieldMapBasedTagTraits
* \brief Defines traits for the specified \a ImplementationType.
*
* A template specialization for each FieldMapBasedTag subclass must be provided.
*/
template<typename ImplementationType>
class FieldMapBasedTagTraits
{};
/*!
* \class Media::FieldMapBasedTag
* \brief The FieldMapBasedTag provides a generic implementation of Tag which stores
@ -21,38 +31,46 @@ namespace Media {
*
* \tparam Compare Specifies the key comparsion function. Default is std::less.
*/
template <class FieldType, class Compare = std::less<typename FieldType::identifierType> >
template <class ImplementationType>
class FieldMapBasedTag : public Tag
{
public:
friend class FieldMapBasedTagTraits<ImplementationType>;
typedef typename FieldMapBasedTagTraits<ImplementationType>::implementationType implementationType;
typedef typename FieldMapBasedTagTraits<ImplementationType>::fieldType fieldType;
typedef typename FieldMapBasedTagTraits<ImplementationType>::fieldType::identifierType identifierType;
typedef typename FieldMapBasedTagTraits<ImplementationType>::compare compare;
FieldMapBasedTag();
virtual const TagValue &value(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism
TagType type() const;
const char *typeName() const;
TagTextEncoding proposedTextEncoding() const;
virtual const TagValue &value(const identifierType &id) const; // FIXME: use static polymorphism
const TagValue &value(KnownField field) const;
std::vector<const TagValue *> values(const typename FieldType::identifierType &id) const;
std::vector<const TagValue *> values(const identifierType &id) const;
std::vector<const TagValue *> values(KnownField field) const;
virtual bool setValue(const typename FieldType::identifierType &id, const TagValue &value); // FIXME: use static polymorphism
virtual bool setValue(const identifierType &id, const TagValue &value); // FIXME: use static polymorphism
bool setValue(KnownField field, const TagValue &value);
bool setValues(const typename FieldType::identifierType &id, const std::vector<TagValue> &values);
bool setValues(const identifierType &id, const std::vector<TagValue> &values);
bool setValues(KnownField field, const std::vector<TagValue> &values);
bool hasField(KnownField field) const;
virtual bool hasField(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism
virtual bool hasField(const identifierType &id) const; // FIXME: use static polymorphism
void removeAllFields();
const std::multimap<typename FieldType::identifierType, FieldType, Compare> &fields() const;
std::multimap<typename FieldType::identifierType, FieldType, Compare> &fields();
const std::multimap<identifierType, fieldType, compare> &fields() const;
std::multimap<identifierType, fieldType, compare> &fields();
unsigned int fieldCount() const;
virtual typename FieldType::identifierType fieldId(KnownField value) const = 0; // FIXME: use static polymorphism
virtual KnownField knownField(const typename FieldType::identifierType &id) const = 0; // FIXME: use static polymorphism
virtual identifierType fieldId(KnownField value) const = 0; // FIXME: use static polymorphism
virtual KnownField knownField(const identifierType &id) const = 0; // FIXME: use static polymorphism
bool supportsField(KnownField field) const;
using Tag::proposedDataType;
virtual TagDataType proposedDataType(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism
int insertFields(const FieldMapBasedTag<FieldType, Compare> &from, bool overwrite);
virtual TagDataType proposedDataType(const identifierType &id) const; // FIXME: use static polymorphism
int insertFields(const FieldMapBasedTag<ImplementationType> &from, bool overwrite);
unsigned int insertValues(const Tag &from, bool overwrite);
void ensureTextValuesAreProperlyEncoded();
typedef FieldType fieldType;
private:
std::multimap<typename FieldType::identifierType, FieldType, Compare> m_fields;
std::multimap<identifierType, fieldType, compare> m_fields;
};
/*!
@ -72,23 +90,41 @@ private:
/*!
* \brief Constructs a new FieldMapBasedTag.
*/
template <class FieldType, class Compare>
FieldMapBasedTag<FieldType, Compare>::FieldMapBasedTag()
template <class ImplementationType>
FieldMapBasedTag<ImplementationType>::FieldMapBasedTag()
{}
template <class ImplementationType>
TagType FieldMapBasedTag<ImplementationType>::type() const
{
return ImplementationType::tagType;
}
template <class ImplementationType>
const char *FieldMapBasedTag<ImplementationType>::typeName() const
{
return ImplementationType::tagName;
}
template<class ImplementationType>
TagTextEncoding FieldMapBasedTag<ImplementationType>::proposedTextEncoding() const
{
return ImplementationType::defaultTextEncoding;
}
/*!
* \brief Returns the value of the field with the specified \a id.
* \sa Tag::value()
*/
template <class FieldType, class Compare>
inline const TagValue &FieldMapBasedTag<FieldType, Compare>::value(const typename FieldType::identifierType &id) const
template <class ImplementationType>
inline const TagValue &FieldMapBasedTag<ImplementationType>::value(const identifierType &id) const
{
auto i = m_fields.find(id);
return i != m_fields.end() ? i->second.value() : TagValue::empty();
}
template <class FieldType, class Compare>
inline const TagValue &FieldMapBasedTag<FieldType, Compare>::value(KnownField field) const
template <class ImplementationType>
inline const TagValue &FieldMapBasedTag<ImplementationType>::value(KnownField field) const
{
return value(fieldId(field));
}
@ -97,8 +133,8 @@ inline const TagValue &FieldMapBasedTag<FieldType, Compare>::value(KnownField fi
* \brief Returns the values of the field with the specified \a id.
* \sa Tag::values()
*/
template <class FieldType, class Compare>
inline std::vector<const TagValue *> FieldMapBasedTag<FieldType, Compare>::values(const typename FieldType::identifierType &id) const
template <class ImplementationType>
inline std::vector<const TagValue *> FieldMapBasedTag<ImplementationType>::values(const identifierType &id) const
{
auto range = m_fields.equal_range(id);
std::vector<const TagValue *> values;
@ -110,14 +146,14 @@ inline std::vector<const TagValue *> FieldMapBasedTag<FieldType, Compare>::value
return values;
}
template <class FieldType, class Compare>
inline std::vector<const TagValue *> FieldMapBasedTag<FieldType, Compare>::values(KnownField field) const
template <class ImplementationType>
inline std::vector<const TagValue *> FieldMapBasedTag<ImplementationType>::values(KnownField field) const
{
return values(fieldId(field));
}
template <class FieldType, class Compare>
inline bool FieldMapBasedTag<FieldType, Compare>::setValue(KnownField field, const TagValue &value)
template <class ImplementationType>
inline bool FieldMapBasedTag<ImplementationType>::setValue(KnownField field, const TagValue &value)
{
return setValue(fieldId(field), value);
}
@ -126,14 +162,14 @@ inline bool FieldMapBasedTag<FieldType, Compare>::setValue(KnownField field, con
* \brief Assigns the given \a value to the field with the specified \a id.
* \sa Tag::setValue()
*/
template <class FieldType, class Compare>
bool FieldMapBasedTag<FieldType, Compare>::setValue(const typename FieldType::identifierType &id, const Media::TagValue &value)
template <class ImplementationType>
bool FieldMapBasedTag<ImplementationType>::setValue(const identifierType &id, const Media::TagValue &value)
{
auto i = m_fields.find(id);
if(i != m_fields.end()) { // field already exists -> set its value
i->second.setValue(value);
} else if(!value.isEmpty()) { // field doesn't exist -> create new one if value is not null
m_fields.insert(std::make_pair(id, FieldType(id, value)));
m_fields.insert(std::make_pair(id, fieldType(id, value)));
} else { // otherwise return false
return false;
}
@ -146,8 +182,8 @@ bool FieldMapBasedTag<FieldType, Compare>::setValue(const typename FieldType::id
* method will replace all currently assigned values with the specified \a values.
* \sa Tag::setValues()
*/
template <class FieldType, class Compare>
bool FieldMapBasedTag<FieldType, Compare>::setValues(const typename FieldType::identifierType &id, const std::vector<TagValue> &values)
template <class ImplementationType>
bool FieldMapBasedTag<ImplementationType>::setValues(const identifierType &id, const std::vector<TagValue> &values)
{
auto valuesIterator = values.cbegin();
auto range = m_fields.equal_range(id);
@ -161,7 +197,7 @@ bool FieldMapBasedTag<FieldType, Compare>::setValues(const typename FieldType::i
}
// add remaining specified values (there are more specified values than existing ones)
for(; valuesIterator != values.cend(); ++valuesIterator) {
m_fields.insert(std::make_pair(id, FieldType(id, *valuesIterator)));
m_fields.insert(std::make_pair(id, fieldType(id, *valuesIterator)));
}
// remove remaining existing values (there are more existing values than specified ones)
for(; range.first != range.second; ++range.first) {
@ -176,14 +212,14 @@ bool FieldMapBasedTag<FieldType, Compare>::setValues(const typename FieldType::i
* method will replace all currently assigned values with the specified \a values.
* \sa Tag::setValues()
*/
template <class FieldType, class Compare>
bool FieldMapBasedTag<FieldType, Compare>::setValues(KnownField field, const std::vector<TagValue> &values)
template <class ImplementationType>
bool FieldMapBasedTag<ImplementationType>::setValues(KnownField field, const std::vector<TagValue> &values)
{
return setValues(fieldId(field), values);
}
template <class FieldType, class Compare>
inline bool FieldMapBasedTag<FieldType, Compare>::hasField(KnownField field) const
template <class ImplementationType>
inline bool FieldMapBasedTag<ImplementationType>::hasField(KnownField field) const
{
return hasField(fieldId(field));
}
@ -191,8 +227,8 @@ inline bool FieldMapBasedTag<FieldType, Compare>::hasField(KnownField field) con
/*!
* \brief Returns an indication whether the field with the specified \a id is present.
*/
template <class FieldType, class Compare>
inline bool FieldMapBasedTag<FieldType, Compare>::hasField(const typename FieldType::identifierType &id) const
template <class ImplementationType>
inline bool FieldMapBasedTag<ImplementationType>::hasField(const identifierType &id) const
{
for (auto range = m_fields.equal_range(id); range.first != range.second; ++range.first) {
if(!range.first->second.value().isEmpty()) {
@ -202,8 +238,8 @@ inline bool FieldMapBasedTag<FieldType, Compare>::hasField(const typename FieldT
return false;
}
template <class FieldType, class Compare>
inline void FieldMapBasedTag<FieldType, Compare>::removeAllFields()
template <class ImplementationType>
inline void FieldMapBasedTag<ImplementationType>::removeAllFields()
{
m_fields.clear();
}
@ -211,8 +247,8 @@ inline void FieldMapBasedTag<FieldType, Compare>::removeAllFields()
/*!
* \brief Returns the fields of the tag by providing direct access to the field map of the tag.
*/
template <class FieldType, class Compare>
inline const std::multimap<typename FieldType::identifierType, FieldType, Compare> &FieldMapBasedTag<FieldType, Compare>::fields() const
template <class ImplementationType>
inline auto FieldMapBasedTag<ImplementationType>::fields() const -> const std::multimap<identifierType, fieldType, compare> &
{
return m_fields;
}
@ -220,14 +256,14 @@ inline const std::multimap<typename FieldType::identifierType, FieldType, Compar
/*!
* \brief Returns the fields of the tag by providing direct access to the field map of the tag.
*/
template <class FieldType, class Compare>
inline std::multimap<typename FieldType::identifierType, FieldType, Compare> &FieldMapBasedTag<FieldType, Compare>::fields()
template <class ImplementationType>
inline auto FieldMapBasedTag<ImplementationType>::fields() -> std::multimap<identifierType, fieldType, compare> &
{
return m_fields;
}
template <class FieldType, class Compare>
unsigned int FieldMapBasedTag<FieldType, Compare>::fieldCount() const
template <class ImplementationType>
unsigned int FieldMapBasedTag<ImplementationType>::fieldCount() const
{
unsigned int count = 0;
for(const auto &field : m_fields) {
@ -238,18 +274,18 @@ unsigned int FieldMapBasedTag<FieldType, Compare>::fieldCount() const
return count;
}
template <class FieldType, class Compare>
inline bool FieldMapBasedTag<FieldType, Compare>::supportsField(KnownField field) const
template <class ImplementationType>
inline bool FieldMapBasedTag<ImplementationType>::supportsField(KnownField field) const
{
static typename FieldType::identifierType def;
static identifierType def;
return fieldId(field) != def;
}
/*!
* \brief Returns the proposed data type for the field with the specified \a id.
*/
template <class FieldType, class Compare>
inline TagDataType FieldMapBasedTag<FieldType, Compare>::proposedDataType(const typename FieldType::identifierType &id) const
template <class ImplementationType>
inline TagDataType FieldMapBasedTag<ImplementationType>::proposedDataType(const identifierType &id) const
{
return Tag::proposedDataType(knownField(id));
}
@ -260,18 +296,18 @@ inline TagDataType FieldMapBasedTag<FieldType, Compare>::proposedDataType(const
* \param overwrite Indicates whether existing fields should be overwritten.
* \return Returns the number of fields that have been inserted.
*/
template <class FieldType, class Compare>
int FieldMapBasedTag<FieldType, Compare>::insertFields(const FieldMapBasedTag<FieldType, Compare> &from, bool overwrite)
template <class ImplementationType>
int FieldMapBasedTag<ImplementationType>::insertFields(const FieldMapBasedTag<ImplementationType> &from, bool overwrite)
{
int fieldsInserted = 0;
for(const auto &pair : from.fields()) {
const FieldType &fromField = pair.second;
const fieldType &fromField = pair.second;
if(fromField.value().isEmpty())
continue;
bool fieldInserted = false;
auto range = fields().equal_range(fromField.id());
for(auto i = range.first; i != range.second; ++i) {
FieldType &ownField = i->second;
fieldType &ownField = i->second;
if((fromField.isTypeInfoAssigned() && ownField.isTypeInfoAssigned()
&& fromField.typeInfo() == ownField.typeInfo())
|| (!fromField.isTypeInfoAssigned() && ! ownField.isTypeInfoAssigned())) {
@ -291,19 +327,19 @@ int FieldMapBasedTag<FieldType, Compare>::insertFields(const FieldMapBasedTag<Fi
return fieldsInserted;
}
template <class FieldType, class Compare>
unsigned int FieldMapBasedTag<FieldType, Compare>::insertValues(const Tag &from, bool overwrite)
template <class ImplementationType>
unsigned int FieldMapBasedTag<ImplementationType>::insertValues(const Tag &from, bool overwrite)
{
if(type() == from.type()) {
// the tags are of the same type, we can insert the fields directly
return insertFields(static_cast<const FieldMapBasedTag<FieldType, Compare> &>(from), overwrite);
return insertFields(static_cast<const FieldMapBasedTag<ImplementationType> &>(from), overwrite);
} else {
return Tag::insertValues(from, overwrite);
}
}
template <class FieldType, class Compare>
void FieldMapBasedTag<FieldType, Compare>::ensureTextValuesAreProperlyEncoded()
template <class ImplementationType>
void FieldMapBasedTag<ImplementationType>::ensureTextValuesAreProperlyEncoded()
{
for(auto &field : fields()) {
field.second.value().convertDataEncodingForTag(this);

View File

@ -12,7 +12,7 @@ class TagField;
* \class Media::TagFieldTraits
* \brief Defines traits for the specified \a ImplementationType.
*
* A template specialization for each TagField derivat must be provided.
* A template specialization for each TagField subclass must be provided.
*/
template<typename ImplementationType>
class TagFieldTraits

View File

@ -30,7 +30,7 @@ TagType Id3v1Tag::type() const
const char *Id3v1Tag::typeName() const
{
return "ID3v1 tag";
return tagName;
}
bool Id3v1Tag::canEncodingBeUsed(TagTextEncoding encoding) const

View File

@ -12,6 +12,7 @@ public:
Id3v1Tag();
static constexpr TagType tagType = TagType::Id3v1Tag;
static constexpr const char *tagName = "ID3v1 tag";
TagType type() const;
const char *typeName() const;
bool canEncodingBeUsed(TagTextEncoding encoding) const;

View File

@ -147,16 +147,6 @@ TagDataType Id3v2Tag::proposedDataType(const uint32 &id) const
}
}
const TagValue &Id3v2Tag::value(const typename Id3v2Frame::identifierType &id) const
{
return FieldMapBasedTag<Id3v2Frame, FrameComparer>::value(id);
}
bool Id3v2Tag::setValue(const typename Id3v2Frame::identifierType &id, const TagValue &value)
{
return FieldMapBasedTag<Id3v2Frame, FrameComparer>::setValue(id, value);
}
/*!
* \brief Parses tag information from the specified \a stream.
*

View File

@ -52,23 +52,33 @@ inline uint64 Id3v2TagMaker::requiredSize() const
return m_requiredSize;
}
class TAG_PARSER_EXPORT Id3v2Tag : public FieldMapBasedTag<Id3v2Frame, FrameComparer>
/*!
* \brief Defines traits for the TagField implementation of the Id3v2Tag class.
*/
template <>
class TAG_PARSER_EXPORT FieldMapBasedTagTraits<Id3v2Tag>
{
public:
typedef Id3v2Tag implementationType;
typedef Id3v2Frame fieldType;
typedef FrameComparer compare;
};
class TAG_PARSER_EXPORT Id3v2Tag : public FieldMapBasedTag<Id3v2Tag>
{
public:
Id3v2Tag();
static constexpr TagType tagType = TagType::Id3v2Tag;
TagType type() const;
const char *typeName() const;
static constexpr const char *tagName = "ID3v2 tag";
static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf16LittleEndian;
TagTextEncoding proposedTextEncoding() const;
bool canEncodingBeUsed(TagTextEncoding encoding) const;
uint32 fieldId(KnownField value) const;
KnownField knownField(const uint32 &id) const;
TagDataType proposedDataType(const uint32 &id) const;
using FieldMapBasedTag<Id3v2Frame, FrameComparer>::value;
const TagValue &value(const typename Id3v2Frame::identifierType &id) const;
using FieldMapBasedTag<Id3v2Frame, FrameComparer>::setValue;
bool setValue(const typename Id3v2Frame::identifierType &id, const TagValue &value);
using FieldMapBasedTag<Id3v2Tag>::value;
using FieldMapBasedTag<Id3v2Tag>::setValue;
bool supportsDescription(KnownField field) const;
bool supportsMimeType(KnownField field) const;
@ -109,16 +119,6 @@ inline Id3v2Tag::Id3v2Tag() :
m_paddingSize(0)
{}
inline TagType Id3v2Tag::type() const
{
return TagType::Id3v2Tag;
}
inline const char *Id3v2Tag::typeName() const
{
return "ID3v2 tag";
}
inline TagTextEncoding Id3v2Tag::proposedTextEncoding() const
{
return m_majorVersion > 3 ? TagTextEncoding::Utf8 : TagTextEncoding::Utf16LittleEndian;

View File

@ -47,16 +47,26 @@ inline uint64 MatroskaTagMaker::requiredSize() const
return m_totalSize;
}
class TAG_PARSER_EXPORT MatroskaTag : public FieldMapBasedTag<MatroskaTagField>
/*!
* \brief Defines traits for the TagField implementation of the MatroskaTag class.
*/
template <>
class TAG_PARSER_EXPORT FieldMapBasedTagTraits<MatroskaTag>
{
public:
typedef MatroskaTag implementationType;
typedef MatroskaTagField fieldType;
typedef std::less<typename fieldType::identifierType> compare;
};
class TAG_PARSER_EXPORT MatroskaTag : public FieldMapBasedTag<MatroskaTag>
{
public:
MatroskaTag();
static constexpr TagType tagType = TagType::MatroskaTag;
// FIXME: implement type() and typeName() in FieldMapBasedTag
TagType type() const;
const char *typeName() const;
TagTextEncoding proposedTextEncoding() const;
static constexpr const char *tagName = "Matroska tag";
static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf8;
bool canEncodingBeUsed(TagTextEncoding encoding) const;
bool supportsTarget() const;
TagTargetLevel targetLevel() const;
@ -88,21 +98,6 @@ inline TagTargetLevel MatroskaTag::targetLevel() const
return matroskaTagTargetLevel(m_target.level());
}
inline TagType MatroskaTag::type() const
{
return TagType::MatroskaTag;
}
inline const char *MatroskaTag::typeName() const
{
return "Matroska tag";
}
inline TagTextEncoding MatroskaTag::proposedTextEncoding() const
{
return TagTextEncoding::Utf8;
}
inline bool MatroskaTag::canEncodingBeUsed(TagTextEncoding encoding) const
{
return encoding == TagTextEncoding::Utf8;

View File

@ -59,16 +59,16 @@ const TagValue &Mp4Tag::value(KnownField field) const
{
switch(field) {
case KnownField::Genre: {
const TagValue &value = FieldMapBasedTag<fieldType>::value(Mp4TagAtomIds::Genre);
const TagValue &value = FieldMapBasedTag<Mp4Tag>::value(Mp4TagAtomIds::Genre);
if(!value.isEmpty()) {
return value;
} else {
return FieldMapBasedTag<fieldType>::value(Mp4TagAtomIds::PreDefinedGenre);
return FieldMapBasedTag<Mp4Tag>::value(Mp4TagAtomIds::PreDefinedGenre);
}
} case KnownField::EncoderSettings:
return this->value(Mp4TagExtendedMeanIds::iTunes, Mp4TagExtendedNameIds::cdec);
case KnownField::RecordLabel: {
const TagValue &value = FieldMapBasedTag<fieldType>::value(Mp4TagAtomIds::RecordLabel);
const TagValue &value = FieldMapBasedTag<Mp4Tag>::value(Mp4TagAtomIds::RecordLabel);
if(!value.isEmpty()) {
return value;
} else {
@ -76,13 +76,13 @@ const TagValue &Mp4Tag::value(KnownField field) const
}
}
default:
return FieldMapBasedTag<fieldType>::value(field);
return FieldMapBasedTag<Mp4Tag>::value(field);
}
}
std::vector<const TagValue *> Mp4Tag::values(KnownField field) const
{
auto values = FieldMapBasedTag<fieldType>::values(field);
auto values = FieldMapBasedTag<Mp4Tag>::values(field);
const Mp4ExtendedFieldId extendedId(field);
if(extendedId) {
auto range = fields().equal_range(Mp4TagAtomIds::Extended);
@ -180,10 +180,10 @@ bool Mp4Tag::setValue(KnownField field, const TagValue &value)
switch(value.type()) {
case TagDataType::StandardGenreIndex:
fields().erase(Mp4TagAtomIds::Genre);
return FieldMapBasedTag<fieldType>::setValue(Mp4TagAtomIds::PreDefinedGenre, value);
return FieldMapBasedTag<Mp4Tag>::setValue(Mp4TagAtomIds::PreDefinedGenre, value);
default:
fields().erase(Mp4TagAtomIds::PreDefinedGenre);
return FieldMapBasedTag<fieldType>::setValue(Mp4TagAtomIds::Genre, value);
return FieldMapBasedTag<Mp4Tag>::setValue(Mp4TagAtomIds::Genre, value);
}
case KnownField::EncoderSettings:
return setValue(Mp4TagExtendedMeanIds::iTunes, Mp4TagExtendedNameIds::cdec, value);
@ -193,7 +193,7 @@ bool Mp4Tag::setValue(KnownField field, const TagValue &value)
}
FALLTHROUGH;
default:
return FieldMapBasedTag<fieldType>::setValue(field, value);
return FieldMapBasedTag<Mp4Tag>::setValue(field, value);
}
}
@ -225,7 +225,7 @@ bool Mp4Tag::setValues(KnownField field, const std::vector<TagValue> &values)
range.first->second.setValue(TagValue());
}
}
return FieldMapBasedTag<fieldType>::setValues(field, values);
return FieldMapBasedTag<Mp4Tag>::setValues(field, values);
}
/*!
@ -260,10 +260,10 @@ bool Mp4Tag::hasField(KnownField field) const
{
switch(field) {
case KnownField::Genre:
return FieldMapBasedTag<fieldType>::hasField(Mp4TagAtomIds::PreDefinedGenre)
|| FieldMapBasedTag<fieldType>::hasField(Mp4TagAtomIds::Genre);
return FieldMapBasedTag<Mp4Tag>::hasField(Mp4TagAtomIds::PreDefinedGenre)
|| FieldMapBasedTag<Mp4Tag>::hasField(Mp4TagAtomIds::Genre);
default:
return FieldMapBasedTag<fieldType>::hasField(field);
return FieldMapBasedTag<Mp4Tag>::hasField(field);
}
}

View File

@ -87,39 +87,50 @@ inline uint64 Mp4TagMaker::requiredSize() const
return m_metaSize;
}
class TAG_PARSER_EXPORT Mp4Tag : public FieldMapBasedTag<Mp4TagField>
/*!
* \brief Defines traits for the TagField implementation of the Mp4Tag class.
*/
template <>
class TAG_PARSER_EXPORT FieldMapBasedTagTraits<Mp4Tag>
{
public:
typedef Mp4Tag implementationType;
typedef Mp4TagField fieldType;
typedef std::less<typename fieldType::identifierType> compare;
};
class TAG_PARSER_EXPORT Mp4Tag : public FieldMapBasedTag<Mp4Tag>
{
public:
Mp4Tag();
static constexpr TagType tagType = TagType::Mp4Tag;
TagType type() const;
const char *typeName() const;
TagTextEncoding proposedTextEncoding() const;
static constexpr const char *tagName = "MP4/iTunes tag";
static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf8;
bool canEncodingBeUsed(TagTextEncoding encoding) const;
uint32 fieldId(KnownField field) const;
KnownField knownField(const uint32 &id) const;
bool supportsField(KnownField field) const;
using FieldMapBasedTag<Mp4TagField>::value;
using FieldMapBasedTag<Mp4Tag>::value;
const TagValue &value(KnownField value) const;
using FieldMapBasedTag<Mp4TagField>::values;
using FieldMapBasedTag<Mp4Tag>::values;
std::vector<const TagValue *> values(KnownField field) const;
#ifdef LEGACY_API
const TagValue &value(const std::string mean, const std::string name) const;
#endif
const TagValue &value(const std::string &mean, const std::string &name) const;
const TagValue &value(const char *mean, const char *name) const;
using FieldMapBasedTag<Mp4TagField>::setValue;
using FieldMapBasedTag<Mp4Tag>::setValue;
bool setValue(KnownField field, const TagValue &value);
using FieldMapBasedTag<Mp4TagField>::setValues;
using FieldMapBasedTag<Mp4Tag>::setValues;
bool setValues(KnownField field, const std::vector<TagValue> &values);
#ifdef LEGACY_API
bool setValue(const std::string mean, const std::string name, const TagValue &value);
#endif
bool setValue(const std::string &mean, const std::string &name, const TagValue &value);
bool setValue(const char *mean, const char *name, const TagValue &value);
using FieldMapBasedTag<Mp4TagField>::hasField;
using FieldMapBasedTag<Mp4Tag>::hasField;
bool hasField(KnownField value) const;
void parse(Mp4Atom &metaAtom);
@ -133,28 +144,13 @@ public:
inline Mp4Tag::Mp4Tag()
{}
inline TagType Mp4Tag::type() const
{
return TagType::Mp4Tag;
}
inline const char *Mp4Tag::typeName() const
{
return "MP4/iTunes tag";
}
inline TagTextEncoding Mp4Tag::proposedTextEncoding() const
{
return TagTextEncoding::Utf8;
}
inline bool Mp4Tag::supportsField(KnownField field) const
{
switch(field) {
case KnownField::EncoderSettings:
return true;
default:
return FieldMapBasedTag<Mp4TagField>::supportsField(field);
return FieldMapBasedTag<Mp4Tag>::supportsField(field);
}
}

View File

@ -29,7 +29,7 @@ const TagValue &VorbisComment::value(KnownField field) const
case KnownField::Vendor:
return vendor();
default:
return FieldMapBasedTag<VorbisCommentField, CaseInsensitiveStringComparer>::value(field);
return FieldMapBasedTag<VorbisComment>::value(field);
}
}
@ -40,7 +40,7 @@ bool VorbisComment::setValue(KnownField field, const TagValue &value)
setVendor(value);
return true;
default:
return FieldMapBasedTag<VorbisCommentField, CaseInsensitiveStringComparer>::setValue(field, value);
return FieldMapBasedTag<VorbisComment>::setValue(field, value);
}
}

View File

@ -12,15 +12,26 @@ namespace Media {
class OggIterator;
class VorbisComment;
class TAG_PARSER_EXPORT VorbisComment : public FieldMapBasedTag<VorbisCommentField, CaseInsensitiveStringComparer>
/*!
* \brief Defines traits for the TagField implementation of the VorbisComment class.
*/
template <>
class TAG_PARSER_EXPORT FieldMapBasedTagTraits<VorbisComment>
{
public:
typedef VorbisComment implementationType;
typedef VorbisCommentField fieldType;
typedef CaseInsensitiveStringComparer compare;
};
class TAG_PARSER_EXPORT VorbisComment : public FieldMapBasedTag<VorbisComment>
{
public:
VorbisComment();
static constexpr TagType tagType = TagType::VorbisComment;
TagType type() const;
const char *typeName() const;
TagTextEncoding proposedTextEncoding() const;
static constexpr const char *tagName = "Vorbis comment";
static constexpr TagTextEncoding defaultTextEncoding = TagTextEncoding::Utf8;
bool canEncodingBeUsed(TagTextEncoding encoding) const;
const TagValue &value(KnownField field) const;
@ -49,21 +60,6 @@ private:
inline VorbisComment::VorbisComment()
{}
inline TagType VorbisComment::type() const
{
return TagType::VorbisComment;
}
inline const char *VorbisComment::typeName() const
{
return "Vorbis comment";
}
inline TagTextEncoding VorbisComment::proposedTextEncoding() const
{
return TagTextEncoding::Utf8;
}
inline bool VorbisComment::canEncodingBeUsed(TagTextEncoding encoding) const
{
return encoding == TagTextEncoding::Utf8;