Tag Parser  10.0.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
tagvalue.h
Go to the documentation of this file.
1 #ifndef TAG_PARSER_TAGVALUE_H
2 #define TAG_PARSER_TAGVALUE_H
3 
4 #include "./localehelper.h"
5 #include "./positioninset.h"
6 
7 #include <c++utilities/chrono/datetime.h>
8 #include <c++utilities/chrono/timespan.h>
9 #include <c++utilities/conversion/binaryconversion.h>
10 #include <c++utilities/misc/flagenumclass.h>
11 #include <c++utilities/misc/traits.h>
12 
13 #include <cstdint>
14 #include <cstring>
15 #include <iosfwd>
16 #include <memory>
17 #include <string>
18 #include <unordered_map>
19 
20 namespace TagParser {
21 
22 class Tag;
23 class Id3v2Frame;
24 
28 enum class TagTextEncoding : unsigned int {
29  Latin1,
30  Utf8,
34 };
35 
42 enum class TagValueFlags : std::uint64_t {
43  None,
44  ReadOnly,
45 };
46 
47 } // namespace TagParser
48 
50 
51 namespace TagParser {
52 
57 constexpr int characterSize(TagTextEncoding encoding)
58 {
59  switch (encoding) {
62  return 1;
65  return 2;
66  default:
67  return 0;
68  }
69 }
70 
74 enum class TagDataType : unsigned int {
75  Text,
76  Integer,
79  TimeSpan,
80  DateTime,
81  Picture,
82  Binary,
83  Undefined
84 };
85 
89 enum class TagValueComparisionFlags : unsigned int {
90  None,
91  CaseInsensitive = 0x1,
92  IgnoreMetaData = 0x2,
93 };
94 
96 public:
97  // constructor, destructor
98  explicit TagValue();
99  explicit TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding = TagTextEncoding::Latin1,
101  explicit TagValue(
102  const char *text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
103  explicit TagValue(
104  const std::string &text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
105  explicit TagValue(
106  std::string_view text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
107  explicit TagValue(int value);
108  explicit TagValue(
109  const char *data, std::size_t length, TagDataType type = TagDataType::Undefined, TagTextEncoding encoding = TagTextEncoding::Latin1);
110  explicit TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type = TagDataType::Binary,
112  explicit TagValue(PositionInSet value);
113  explicit TagValue(CppUtilities::DateTime value);
114  explicit TagValue(CppUtilities::TimeSpan value);
115  TagValue(const TagValue &other);
116  TagValue(TagValue &&other) = default;
117  ~TagValue();
118 
119  // operators
120  TagValue &operator=(const TagValue &other);
121  TagValue &operator=(TagValue &&other) = default;
122  bool operator==(const TagValue &other) const;
123  bool operator!=(const TagValue &other) const;
124  operator bool() const;
125 
126  // methods
127  bool isNull() const;
128  bool isEmpty() const;
129  void clearData();
130  void clearMetadata();
131  void clearDataAndMetadata();
132  TagDataType type() const;
133  std::string toString(TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
134  void toString(std::string &result, TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
135  std::u16string toWString(TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
136  void toWString(std::u16string &result, TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
137  std::int32_t toInteger() const;
138  int toStandardGenreIndex() const;
139  PositionInSet toPositionInSet() const;
140  CppUtilities::TimeSpan toTimeSpan() const;
141  CppUtilities::DateTime toDateTime() const;
142  std::size_t dataSize() const;
143  char *dataPointer();
144  const char *dataPointer() const;
145  std::string_view data() const;
146  const std::string &description() const;
147  void setDescription(std::string_view value, TagTextEncoding encoding = TagTextEncoding::Latin1);
148  const std::string &mimeType() const;
149  void setMimeType(std::string_view mimeType);
150  const Locale &locale() const;
151  Locale &locale();
152  void setLocale(const Locale &locale);
153  TagValueFlags flags() const;
154  void setFlags(TagValueFlags flags);
155  bool isLabeledAsReadonly() const;
156  void setReadonly(bool readOnly);
157  const std::unordered_map<std::string, std::string> &nativeData() const;
158  std::unordered_map<std::string, std::string> &nativeData();
159  TagTextEncoding dataEncoding() const;
160  void convertDataEncoding(TagTextEncoding encoding);
161  void convertDataEncodingForTag(const Tag *tag);
162  TagTextEncoding descriptionEncoding() const;
163  void convertDescriptionEncoding(TagTextEncoding encoding);
164  static const TagValue &empty();
165 
166  void assignText(const char *text, std::size_t textSize, TagTextEncoding textEncoding = TagTextEncoding::Latin1,
168  void assignText(
169  const std::string &text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
170  void assignText(
171  std::string_view text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
172  void assignInteger(int value);
173  void assignStandardGenreIndex(int index);
174  void assignData(const char *data, std::size_t length, TagDataType type = TagDataType::Binary, TagTextEncoding encoding = TagTextEncoding::Latin1);
175  void assignData(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type = TagDataType::Binary,
177  void assignPosition(PositionInSet value);
178  void assignTimeSpan(CppUtilities::TimeSpan value);
179  void assignDateTime(CppUtilities::DateTime value);
180 
181  static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding);
182  static void ensureHostByteOrder(std::u16string &u16str, TagTextEncoding currentEncoding);
183  template <typename ContainerType,
184  CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsIteratable<ContainerType>,
185  std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>>
186  * = nullptr>
187  static std::vector<std::string> toStrings(const ContainerType &values, TagTextEncoding encoding = TagTextEncoding::Utf8);
188  bool compareTo(const TagValue &other, TagValueComparisionFlags options = TagValueComparisionFlags::None) const;
189  bool compareData(const TagValue &other, bool ignoreCase = false) const;
190  static bool compareData(const std::string &data1, const std::string &data2, bool ignoreCase = false);
191  static bool compareData(const char *data1, std::size_t size1, const char *data2, std::size_t size2, bool ignoreCase = false);
192 
193 private:
194  std::unique_ptr<char[]> m_ptr;
195  std::size_t m_size;
196  std::string m_desc;
197  std::string m_mimeType;
198  Locale m_locale;
199  std::unordered_map<std::string, std::string> m_nativeData;
200  TagDataType m_type;
201  TagTextEncoding m_encoding;
202  TagTextEncoding m_descEncoding;
203  TagValueFlags m_flags;
204 };
205 
210  : m_size(0)
211  , m_type(TagDataType::Undefined)
212  , m_encoding(TagTextEncoding::Latin1)
213  , m_descEncoding(TagTextEncoding::Latin1)
214  , m_flags(TagValueFlags::None)
215 {
216 }
217 
222 {
223 }
224 
235 inline TagValue::TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding, TagTextEncoding convertTo)
236  : m_descEncoding(TagTextEncoding::Latin1)
237  , m_flags(TagValueFlags::None)
238 {
239  assignText(text, textSize, textEncoding, convertTo);
240 }
241 
251 inline TagValue::TagValue(const char *text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
252 {
253  assignText(text, std::strlen(text), textEncoding, convertTo);
254 }
255 
265 inline TagValue::TagValue(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
266  : m_descEncoding(TagTextEncoding::Latin1)
267  , m_flags(TagValueFlags::None)
268 {
269  assignText(text, textEncoding, convertTo);
270 }
271 
281 inline TagValue::TagValue(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
282  : m_descEncoding(TagTextEncoding::Latin1)
283  , m_flags(TagValueFlags::None)
284 {
285  assignText(text, textEncoding, convertTo);
286 }
287 
291 inline TagValue::TagValue(int value)
292  : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::Integer)
293 {
294 }
295 
306 inline TagValue::TagValue(const char *data, std::size_t length, TagDataType type, TagTextEncoding encoding)
307  : m_size(length)
308  , m_type(type)
309  , m_encoding(encoding)
310  , m_descEncoding(TagTextEncoding::Latin1)
311  , m_flags(TagValueFlags::None)
312 {
313  if (length) {
314  if (type == TagDataType::Text) {
315  stripBom(data, m_size, encoding);
316  }
317  m_ptr = std::make_unique<char[]>(m_size);
318  std::copy(data, data + m_size, m_ptr.get());
319  }
320 }
321 
334 inline TagValue::TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type, TagTextEncoding encoding)
335  : m_size(length)
336  , m_type(type)
337  , m_encoding(encoding)
338  , m_descEncoding(TagTextEncoding::Latin1)
339  , m_flags(TagValueFlags::None)
340 {
341  if (length) {
342  m_ptr = move(data);
343  }
344 }
345 
350  : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::PositionInSet)
351 {
352 }
353 
357 inline TagValue::TagValue(CppUtilities::DateTime value)
358  : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime)
359 {
360 }
361 
365 inline TagValue::TagValue(CppUtilities::TimeSpan value)
366  : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan)
367 {
368 }
369 
374 inline bool TagValue::operator==(const TagValue &other) const
375 {
377 }
378 
383 inline bool TagValue::operator!=(const TagValue &other) const
384 {
386 }
387 
392 inline TagParser::TagValue::operator bool() const
393 {
394  return !isEmpty();
395 }
396 
406 inline void TagValue::assignText(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
407 {
408  assignText(text.data(), text.size(), textEncoding, convertTo);
409 }
410 
420 inline void TagValue::assignText(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
421 {
422  assignText(text.data(), text.size(), textEncoding, convertTo);
423 }
424 
429 {
430  if (value.isNull()) {
432  clearData();
433  } else {
434  assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::PositionInSet);
435  }
436 }
437 
441 inline void TagValue::assignTimeSpan(CppUtilities::TimeSpan value)
442 {
443  assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan);
444 }
445 
449 inline void TagValue::assignDateTime(CppUtilities::DateTime value)
450 {
451  assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime);
452 }
453 
460 {
461  assignInteger(index);
463 }
464 
469 {
470  return m_type;
471 }
472 
485 inline std::string TagValue::toString(TagTextEncoding encoding) const
486 {
487  std::string res;
488  toString(res, encoding);
489  return res;
490 }
491 
498 inline std::u16string TagValue::toWString(TagTextEncoding encoding) const
499 {
500  std::u16string res;
501  toWString(res, encoding);
502  return res;
503 }
504 
513 inline bool TagValue::isNull() const
514 {
515  return m_ptr == nullptr;
516 }
517 
527 inline bool TagValue::isEmpty() const
528 {
529  return m_ptr == nullptr || m_size == 0;
530 }
531 
538 inline void TagValue::clearData()
539 {
540  m_size = 0;
541  m_ptr.reset();
542 }
543 
550 {
551  clearData();
552  clearMetadata();
553 }
554 
559 inline std::size_t TagValue::dataSize() const
560 {
561  return m_size;
562 }
563 
570 inline char *TagValue::dataPointer()
571 {
572  return m_ptr.get();
573 }
574 
575 inline const char *TagValue::dataPointer() const
576 {
577  return m_ptr.get();
578 }
579 
583 inline std::string_view TagValue::data() const
584 {
585  return std::string_view(m_ptr.get(), m_size);
586 }
587 
598 inline const std::string &TagValue::description() const
599 {
600  return m_desc;
601 }
602 
614 inline void TagValue::setDescription(std::string_view value, TagTextEncoding encoding)
615 {
616  m_desc = value;
617  m_descEncoding = encoding;
618 }
619 
627 inline const std::string &TagValue::mimeType() const
628 {
629  return m_mimeType;
630 }
631 
639 inline void TagValue::setMimeType(std::string_view mimeType)
640 {
641  m_mimeType = mimeType;
642 }
643 
653 inline const Locale &TagValue::locale() const
654 {
655  return m_locale;
656 }
657 
668 {
669  return m_locale;
670 }
671 
681 inline void TagValue::setLocale(const Locale &locale)
682 {
683  m_locale = locale;
684 }
685 
691 {
692  return m_flags;
693 }
694 
700 {
701  m_flags = flags;
702 }
703 
713 inline bool TagValue::isLabeledAsReadonly() const
714 {
715  return m_flags & TagValueFlags::ReadOnly;
716 }
717 
727 inline void TagValue::setReadonly(bool readOnly)
728 {
729  CppUtilities::modFlagEnum(m_flags, TagValueFlags::ReadOnly, readOnly);
730 }
731 
736 inline const std::unordered_map<std::string, std::string> &TagValue::nativeData() const
737 {
738  return m_nativeData;
739 }
740 
745 inline std::unordered_map<std::string, std::string> &TagValue::nativeData()
746 {
747  return m_nativeData;
748 }
749 
756 {
757  return m_encoding;
758 }
759 
766 {
767  return m_descEncoding;
768 }
769 
775 template <typename ContainerType,
776  CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsIteratable<ContainerType>,
777  std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>> *>
778 std::vector<std::string> TagValue::toStrings(const ContainerType &values, TagTextEncoding encoding)
779 {
780  std::vector<std::string> res;
781  res.reserve(values.size());
782  for (const auto &value : values) {
783  res.emplace_back(CppUtilities::Traits::dereferenceMaybe(value).toString(encoding));
784  }
785  return res;
786 }
787 
791 inline bool TagValue::compareData(const TagValue &other, bool ignoreCase) const
792 {
793  return compareData(m_ptr.get(), m_size, other.m_ptr.get(), other.m_size, ignoreCase);
794 }
795 
799 inline bool TagValue::compareData(const std::string &data1, const std::string &data2, bool ignoreCase)
800 {
801  return compareData(data1.data(), data1.size(), data2.data(), data2.size(), ignoreCase);
802 }
803 
804 } // namespace TagParser
805 
807 
808 #endif // TAG_PARSER_TAGVALUE_H
The PositionInSet class describes the position of an element in a set which consists of a certain num...
Definition: positioninset.h:21
constexpr bool isNull() const
Returns an indication whether both the element position and total element count is 0.
Definition: positioninset.h:94
The TagValue class wraps values of different types.
Definition: tagvalue.h:95
bool compareData(const TagValue &other, bool ignoreCase=false) const
Returns whether the raw data of the current instance equals the raw data of other.
Definition: tagvalue.h:791
void setMimeType(std::string_view mimeType)
Sets the MIME type.
Definition: tagvalue.h:639
void setFlags(TagValueFlags flags)
Sets the flags.
Definition: tagvalue.h:699
const std::unordered_map< std::string, std::string > & nativeData() const
Holds tag format specific meta-data for that field which does not fit into any of the other meta-data...
Definition: tagvalue.h:736
void clearMetadata()
Wipes assigned meta data.
Definition: tagvalue.cpp:306
void assignText(const char *text, std::size_t textSize, TagTextEncoding textEncoding=TagTextEncoding::Latin1, TagTextEncoding convertTo=TagTextEncoding::Unspecified)
Assigns a copy of the given text.
Definition: tagvalue.cpp:770
const std::string & mimeType() const
Returns the MIME type.
Definition: tagvalue.h:627
void assignInteger(int value)
Assigns the given integer value.
Definition: tagvalue.cpp:821
bool compareTo(const TagValue &other, TagValueComparisionFlags options=TagValueComparisionFlags::None) const
Returns whether both instances are equal.
Definition: tagvalue.cpp:181
TagTextEncoding dataEncoding() const
Returns the data encoding.
Definition: tagvalue.h:755
void assignPosition(PositionInSet value)
Assigns the given PositionInSet value.
Definition: tagvalue.h:428
void assignData(const char *data, std::size_t length, TagDataType type=TagDataType::Binary, TagTextEncoding encoding=TagTextEncoding::Latin1)
TagValue(TagValue &&other)=default
bool operator==(const TagValue &other) const
Returns whether both instances are equal.
Definition: tagvalue.h:374
void setDescription(std::string_view value, TagTextEncoding encoding=TagTextEncoding::Latin1)
Sets the description.
Definition: tagvalue.h:614
TagDataType type() const
Returns the type of the assigned value.
Definition: tagvalue.h:468
void assignTimeSpan(CppUtilities::TimeSpan value)
Assigns the given TimeSpan value.
Definition: tagvalue.h:441
static std::vector< std::string > toStrings(const ContainerType &values, TagTextEncoding encoding=TagTextEncoding::Utf8)
Converts the specified values to string using the specified encoding.
Definition: tagvalue.h:778
void clearDataAndMetadata()
Wipes assigned data including meta data.
Definition: tagvalue.h:549
void assignData(std::unique_ptr< char[]> &&data, std::size_t length, TagDataType type=TagDataType::Binary, TagTextEncoding encoding=TagTextEncoding::Latin1)
void assignDateTime(CppUtilities::DateTime value)
Assigns the given DateTime value.
Definition: tagvalue.h:449
bool isLabeledAsReadonly() const
Returns an indication whether the value is labeled as read-only.
Definition: tagvalue.h:713
TagValueFlags flags() const
Returns the flags.
Definition: tagvalue.h:690
bool operator!=(const TagValue &other) const
Returns whether both instances are not equal.
Definition: tagvalue.h:383
~TagValue()
Destroys the TagValue.
Definition: tagvalue.h:221
std::string_view data() const
Returns the currently assigned raw data.
Definition: tagvalue.h:583
std::size_t dataSize() const
Returns the size of the assigned value in bytes.
Definition: tagvalue.h:559
std::u16string toWString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::wstring representation.
Definition: tagvalue.h:498
TagTextEncoding descriptionEncoding() const
Returns the description encoding.
Definition: tagvalue.h:765
void assignStandardGenreIndex(int index)
Assigns the given standard genre index to be assigned.
Definition: tagvalue.h:459
std::string toString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::string representation.
Definition: tagvalue.h:485
bool isNull() const
Returns whether no value is assigned at all.
Definition: tagvalue.h:513
void setLocale(const Locale &locale)
Sets the setLocale.
Definition: tagvalue.h:681
void setReadonly(bool readOnly)
Sets whether the TagValue is labeled as read-only.
Definition: tagvalue.h:727
static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding)
Strips the byte order mask from the specified text.
Definition: tagvalue.cpp:879
void clearData()
Clears the assigned data.
Definition: tagvalue.h:538
TagValue & operator=(TagValue &&other)=default
bool isEmpty() const
Returns whether no or an empty value is assigned.
Definition: tagvalue.h:527
const std::string & description() const
Returns the description.
Definition: tagvalue.h:598
const Locale & locale() const
Returns the locale.
Definition: tagvalue.h:653
TagValue()
Constructs an empty TagValue.
Definition: tagvalue.h:209
char * dataPointer()
Returns a pointer to the raw data assigned to the current instance.
Definition: tagvalue.h:570
The Tag class is used to store, read and write tag information.
Definition: tag.h:108
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
constexpr TAG_PARSER_EXPORT std::string_view description()
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10
constexpr int characterSize(TagTextEncoding encoding)
Returns the size of one character for the specified encoding in bytes.
Definition: tagvalue.h:57
TagTextEncoding
Specifies the text encoding.
Definition: tagvalue.h:28
constexpr bool operator!=(std::uint8_t lhs, FlacMetaDataBlockType type)
Definition: flacmetadata.h:23
constexpr bool operator==(std::uint8_t lhs, FlacMetaDataBlockType type)
Definition: flacmetadata.h:18
TagValueComparisionFlags
The TagValueComparisionOption enum specifies options for TagValue::compareTo().
Definition: tagvalue.h:89
TagValueFlags
Specifies additional flags about the tag value.
Definition: tagvalue.h:42
TagDataType
Specifies the data type.
Definition: tagvalue.h:74
CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(TagParser, TagParser::TagCreationFlags)
The Locale struct specifies a language and/or a country using one or more LocaleDetail objects.
Definition: localehelper.h:61