Tag Parser  6.3.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
fieldbasedtag.h
Go to the documentation of this file.
1 #ifndef FIELDBASEDTAG_H
2 #define FIELDBASEDTAG_H
3 
4 #include "./tag.h"
5 
6 #include <map>
7 #include <functional>
8 
9 namespace Media {
10 
24 template <class FieldType, class Compare = std::less<typename FieldType::identifierType> >
25 class FieldMapBasedTag : public Tag
26 {
27 public:
29 
30  virtual const TagValue &value(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism
31  const TagValue &value(KnownField field) const;
32  std::vector<const TagValue *> values(const typename FieldType::identifierType &id) const;
33  std::vector<const TagValue *> values(KnownField field) const;
34  virtual bool setValue(const typename FieldType::identifierType &id, const TagValue &value); // FIXME: use static polymorphism
35  bool setValue(KnownField field, const TagValue &value);
36  bool setValues(const typename FieldType::identifierType &id, const std::vector<TagValue> &values);
37  bool setValues(KnownField field, const std::vector<TagValue> &values);
38  bool hasField(KnownField field) const;
39  virtual bool hasField(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism
40  void removeAllFields();
41  const std::multimap<typename FieldType::identifierType, FieldType, Compare> &fields() const;
42  std::multimap<typename FieldType::identifierType, FieldType, Compare> &fields();
43  unsigned int fieldCount() const;
44  virtual typename FieldType::identifierType fieldId(KnownField value) const = 0; // FIXME: use static polymorphism
45  virtual KnownField knownField(const typename FieldType::identifierType &id) const = 0; // FIXME: use static polymorphism
46  bool supportsField(KnownField field) const;
48  virtual TagDataType proposedDataType(const typename FieldType::identifierType &id) const; // FIXME: use static polymorphism
49  int insertFields(const FieldMapBasedTag<FieldType, Compare> &from, bool overwrite);
50  unsigned int insertValues(const Tag &from, bool overwrite);
52  typedef FieldType fieldType;
53 
54 private:
55  std::multimap<typename FieldType::identifierType, FieldType, Compare> m_fields;
56 };
57 
75 template <class FieldType, class Compare>
77 {}
78 
83 template <class FieldType, class Compare>
84 inline const TagValue &FieldMapBasedTag<FieldType, Compare>::value(const typename FieldType::identifierType &id) const
85 {
86  auto i = m_fields.find(id);
87  return i != m_fields.end() ? i->second.value() : TagValue::empty();
88 }
89 
90 template <class FieldType, class Compare>
92 {
93  return value(fieldId(field));
94 }
95 
100 template <class FieldType, class Compare>
101 inline std::vector<const TagValue *> FieldMapBasedTag<FieldType, Compare>::values(const typename FieldType::identifierType &id) const
102 {
103  auto range = m_fields.equal_range(id);
104  std::vector<const TagValue *> values;
105  for(auto i = range.first; i != range.second; ++i) {
106  if(!i->second.value().isEmpty()) {
107  values.push_back(&i->second.value());
108  }
109  }
110  return values;
111 }
112 
113 template <class FieldType, class Compare>
114 inline std::vector<const TagValue *> FieldMapBasedTag<FieldType, Compare>::values(KnownField field) const
115 {
116  return values(fieldId(field));
117 }
118 
119 template <class FieldType, class Compare>
121 {
122  return setValue(fieldId(field), value);
123 }
124 
129 template <class FieldType, class Compare>
130 bool FieldMapBasedTag<FieldType, Compare>::setValue(const typename FieldType::identifierType &id, const Media::TagValue &value)
131 {
132  auto i = m_fields.find(id);
133  if(i != m_fields.end()) { // field already exists -> set its value
134  i->second.setValue(value);
135  } else if(!value.isEmpty()) { // field doesn't exist -> create new one if value is not null
136  m_fields.insert(std::make_pair(id, FieldType(id, value)));
137  } else { // otherwise return false
138  return false;
139  }
140  return true;
141 }
142 
149 template <class FieldType, class Compare>
150 bool FieldMapBasedTag<FieldType, Compare>::setValues(const typename FieldType::identifierType &id, const std::vector<TagValue> &values)
151 {
152  auto valuesIterator = values.cbegin();
153  auto range = m_fields.equal_range(id);
154  for(; valuesIterator != values.cend() && range.first != range.second; ++valuesIterator) {
155  if(!valuesIterator->isEmpty()) {
156  range.first->second.setValue(*valuesIterator);
157  ++range.first;
158  }
159  }
160  for(; valuesIterator != values.cend(); ++valuesIterator) {
161  m_fields.insert(std::make_pair(id, FieldType(id, *valuesIterator)));
162  }
163  for(; range.first != range.second; ++range.first) {
164  range.first->second.setValue(TagValue());
165  }
166  return true;
167 }
168 
175 template <class FieldType, class Compare>
176 bool FieldMapBasedTag<FieldType, Compare>::setValues(KnownField field, const std::vector<TagValue> &values)
177 {
178  return setValues(fieldId(field), values);
179 }
180 
181 template <class FieldType, class Compare>
183 {
184  return hasField(fieldId(field));
185 }
186 
190 template <class FieldType, class Compare>
191 inline bool FieldMapBasedTag<FieldType, Compare>::hasField(const typename FieldType::identifierType &id) const
192 {
193  for (auto range = m_fields.equal_range(id); range.first != range.second; ++range.first) {
194  if(!range.first->second.value().isEmpty()) {
195  return true;
196  }
197  }
198  return false;
199 }
200 
201 template <class FieldType, class Compare>
203 {
204  m_fields.clear();
205 }
206 
210 template <class FieldType, class Compare>
211 inline const std::multimap<typename FieldType::identifierType, FieldType, Compare> &FieldMapBasedTag<FieldType, Compare>::fields() const
212 {
213  return m_fields;
214 }
215 
219 template <class FieldType, class Compare>
220 inline std::multimap<typename FieldType::identifierType, FieldType, Compare> &FieldMapBasedTag<FieldType, Compare>::fields()
221 {
222  return m_fields;
223 }
224 
225 template <class FieldType, class Compare>
227 {
228  unsigned int count = 0;
229  for(const auto &field : m_fields) {
230  if(!field.second.value().isEmpty()) {
231  ++count;
232  }
233  }
234  return count;
235 }
236 
237 template <class FieldType, class Compare>
239 {
240  static typename FieldType::identifierType def;
241  return fieldId(field) != def;
242 }
243 
247 template <class FieldType, class Compare>
248 inline TagDataType FieldMapBasedTag<FieldType, Compare>::proposedDataType(const typename FieldType::identifierType &id) const
249 {
250  return Tag::proposedDataType(knownField(id));
251 }
252 
259 template <class FieldType, class Compare>
261 {
262  int fieldsInserted = 0;
263  for(const auto &pair : from.fields()) {
264  const FieldType &fromField = pair.second;
265  if(fromField.value().isEmpty())
266  continue;
267  bool fieldInserted = false;
268  auto range = fields().equal_range(fromField.id());
269  for(auto i = range.first; i != range.second; ++i) {
270  FieldType &ownField = i->second;
271  if((fromField.isTypeInfoAssigned() && ownField.isTypeInfoAssigned()
272  && fromField.typeInfo() == ownField.typeInfo())
273  || (!fromField.isTypeInfoAssigned() && ! ownField.isTypeInfoAssigned())) {
274  if(overwrite || ownField.value().isEmpty()) {
275  ownField = fromField;
276  ++fieldsInserted;
277  }
278  fieldInserted = true;
279  continue;
280  }
281  }
282  if(!fieldInserted) {
283  fields().insert(std::make_pair(fromField.id(), fromField));
284  ++fieldsInserted;
285  }
286  }
287  return fieldsInserted;
288 }
289 
290 template <class FieldType, class Compare>
291 unsigned int FieldMapBasedTag<FieldType, Compare>::insertValues(const Tag &from, bool overwrite)
292 {
293  if(type() == from.type()) {
294  // the tags are of the same type, we can insert the fields directly
295  return insertFields(static_cast<const FieldMapBasedTag<FieldType, Compare> &>(from), overwrite);
296  } else {
297  return Tag::insertValues(from, overwrite);
298  }
299 }
300 
301 template <class FieldType, class Compare>
303 {
304  for(auto &field : fields()) {
305  field.second.value().convertDataEncodingForTag(this);
306  }
307 }
308 
309 }
310 
311 #endif // FIELDBASEDTAG_H
virtual FieldType::identifierType fieldId(KnownField value) const =0
Returns the ID for the specified field.
The TagValue class wraps values of different types.
Definition: tagvalue.h:63
bool isEmpty() const
Returns an indication whether an value is assigned.
Definition: tagvalue.h:340
FieldMapBasedTag()
Constructs a new FieldMapBasedTag.
Definition: fieldbasedtag.h:76
KnownField
Specifies the field.
Definition: tag.h:42
virtual KnownField knownField(const typename FieldType::identifierType &id) const =0
Returns the field for the specified ID.
bool setValues(const typename FieldType::identifierType &id, const std::vector< TagValue > &values)
Assigns the given values to the field with the specified id.
std::vector< const TagValue * > values(const typename FieldType::identifierType &id) const
Returns the values of the field with the specified id.
int insertFields(const FieldMapBasedTag< FieldType, Compare > &from, bool overwrite)
Inserts all fields from another tag of the same field type and compare function.
virtual bool setValue(const typename FieldType::identifierType &id, const TagValue &value)
Assigns the given value to the field with the specified id.
virtual unsigned int insertValues(const Tag &from, bool overwrite)
Inserts all compatible values from another Tag.
Definition: tag.cpp:127
const std::multimap< typename FieldType::identifierType, FieldType, Compare > & fields() const
Returns the fields of the tag by providing direct access to the field map of the tag.
unsigned int insertValues(const Tag &from, bool overwrite)
Inserts all compatible values from another Tag.
virtual const TagValue & value(const typename FieldType::identifierType &id) const
Returns the value of the field with the specified id.
Definition: fieldbasedtag.h:84
virtual TagType type() const
Returns the type of the tag as Media::TagType.
Definition: tag.h:154
The Tag class is used to store, read and write tag information.
Definition: tag.h:98
The FieldMapBasedTag provides a generic implementation of Tag which stores the tag fields using std::...
Definition: fieldbasedtag.h:25
bool supportsField(KnownField field) const
Returns an indication whether the specified field is supported by the tag.
void removeAllFields()
Removes all fields from the tag.
TagDataType
Specifies the data type.
Definition: tagvalue.h:50
static const TagValue & empty()
Returns an empty TagValue.
Definition: tagvalue.cpp:699
virtual TagDataType proposedDataType(KnownField field) const
Returns the proposed data type for the specified field as TagDataType.
Definition: tag.h:314
Contains all classes and functions of the TagInfo library.
Definition: exceptions.h:9
virtual TagDataType proposedDataType(const typename FieldType::identifierType &id) const
Returns the proposed data type for the field with the specified id.
void ensureTextValuesAreProperlyEncoded()
Ensures the encoding of all assigned text values is supported by the tag by converting the character ...
bool hasField(KnownField field) const
Returns an indication whether the specified field is present.
unsigned int fieldCount() const
Returns the number of present fields.