Tag Parser 11.2.1
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
20namespace TagParser {
21
22class Tag;
23class Id3v2Frame;
24
28enum class TagTextEncoding : unsigned int {
29 Latin1,
30 Utf8,
34};
35
42enum class TagValueFlags : std::uint64_t {
43 None,
44 ReadOnly,
45};
46
47} // namespace TagParser
48
50
51namespace TagParser {
52
57constexpr int characterSize(TagTextEncoding encoding)
58{
59 switch (encoding) {
62 return 1;
65 return 2;
66 default:
67 return 0;
68 }
69}
70
74enum class TagDataType : unsigned int {
75 Text,
76 Integer,
79 TimeSpan,
80 DateTime,
81 Picture,
82 Binary,
83 Undefined
84};
85
89enum class TagValueComparisionFlags : unsigned int {
90 None,
91 CaseInsensitive = 0x1,
92 IgnoreMetaData = 0x2,
93};
94
96public:
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
193private:
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
235inline 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
251inline TagValue::TagValue(const char *text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
252{
253 assignText(text, std::strlen(text), textEncoding, convertTo);
254}
255
265inline 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
281inline 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
291inline TagValue::TagValue(int value)
292 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::Integer)
293{
294}
295
306inline 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
334inline 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
357inline TagValue::TagValue(CppUtilities::DateTime value)
358 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime)
359{
360}
361
365inline TagValue::TagValue(CppUtilities::TimeSpan value)
366 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan)
367{
368}
369
374inline bool TagValue::operator==(const TagValue &other) const
375{
377}
378
383inline bool TagValue::operator!=(const TagValue &other) const
384{
386}
387
392inline TagParser::TagValue::operator bool() const
393{
394 return !isEmpty();
395}
396
406inline void TagValue::assignText(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
407{
408 assignText(text.data(), text.size(), textEncoding, convertTo);
409}
410
420inline 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
441inline void TagValue::assignTimeSpan(CppUtilities::TimeSpan value)
442{
443 assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan);
444}
445
449inline 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
485inline std::string TagValue::toString(TagTextEncoding encoding) const
486{
487 std::string res;
488 toString(res, encoding);
489 return res;
490}
491
498inline std::u16string TagValue::toWString(TagTextEncoding encoding) const
499{
500 std::u16string res;
501 toWString(res, encoding);
502 return res;
503}
504
512inline bool TagValue::isNull() const
513{
514 return m_ptr == nullptr;
515}
516
525inline bool TagValue::isEmpty() const
526{
527 return m_ptr == nullptr || m_size == 0;
528}
529
537{
538 m_size = 0;
539 m_ptr.reset();
540}
541
548{
549 clearData();
551}
552
557inline std::size_t TagValue::dataSize() const
558{
559 return m_size;
560}
561
569{
570 return m_ptr.get();
571}
572
573inline const char *TagValue::dataPointer() const
574{
575 return m_ptr.get();
576}
577
581inline std::string_view TagValue::data() const
582{
583 return std::string_view(m_ptr.get(), m_size);
584}
585
596inline const std::string &TagValue::description() const
597{
598 return m_desc;
599}
600
612inline void TagValue::setDescription(std::string_view value, TagTextEncoding encoding)
613{
614 m_desc = value;
615 m_descEncoding = encoding;
616}
617
625inline const std::string &TagValue::mimeType() const
626{
627 return m_mimeType;
628}
629
637inline void TagValue::setMimeType(std::string_view mimeType)
638{
639 m_mimeType = mimeType;
640}
641
651inline const Locale &TagValue::locale() const
652{
653 return m_locale;
654}
655
666{
667 return m_locale;
668}
669
679inline void TagValue::setLocale(const Locale &locale)
680{
681 m_locale = locale;
682}
683
689{
690 return m_flags;
691}
692
698{
699 m_flags = flags;
700}
701
712{
713 return m_flags & TagValueFlags::ReadOnly;
714}
715
725inline void TagValue::setReadonly(bool readOnly)
726{
727 CppUtilities::modFlagEnum(m_flags, TagValueFlags::ReadOnly, readOnly);
728}
729
734inline const std::unordered_map<std::string, std::string> &TagValue::nativeData() const
735{
736 return m_nativeData;
737}
738
743inline std::unordered_map<std::string, std::string> &TagValue::nativeData()
744{
745 return m_nativeData;
746}
747
754{
755 return m_encoding;
756}
757
764{
765 return m_descEncoding;
766}
767
773template <typename ContainerType,
774 CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsIteratable<ContainerType>,
775 std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>> *>
776std::vector<std::string> TagValue::toStrings(const ContainerType &values, TagTextEncoding encoding)
777{
778 std::vector<std::string> res;
779 res.reserve(values.size());
780 for (const auto &value : values) {
781 res.emplace_back(CppUtilities::Traits::dereferenceMaybe(value).toString(encoding));
782 }
783 return res;
784}
785
789inline bool TagValue::compareData(const TagValue &other, bool ignoreCase) const
790{
791 return compareData(m_ptr.get(), m_size, other.m_ptr.get(), other.m_size, ignoreCase);
792}
793
797inline bool TagValue::compareData(const std::string &data1, const std::string &data2, bool ignoreCase)
798{
799 return compareData(data1.data(), data1.size(), data2.data(), data2.size(), ignoreCase);
800}
801
802} // namespace TagParser
803
805
806#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:789
void setMimeType(std::string_view mimeType)
Sets the MIME type.
Definition: tagvalue.h:637
void setFlags(TagValueFlags flags)
Sets the flags.
Definition: tagvalue.h:697
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:734
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:625
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:753
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:612
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:776
void clearDataAndMetadata()
Wipes assigned data including meta data.
Definition: tagvalue.h:547
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:711
TagValueFlags flags() const
Returns the flags.
Definition: tagvalue.h:688
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:581
TagValue & operator=(TagValue &&other)=default
std::size_t dataSize() const
Returns the size of the assigned value in bytes.
Definition: tagvalue.h:557
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:763
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:512
void setLocale(const Locale &locale)
Sets the setLocale.
Definition: tagvalue.h:679
void setReadonly(bool readOnly)
Sets whether the TagValue is labeled as read-only.
Definition: tagvalue.h:725
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:536
bool isEmpty() const
Returns whether no or an empty value is assigned.
Definition: tagvalue.h:525
const std::string & description() const
Returns the description.
Definition: tagvalue.h:596
const Locale & locale() const
Returns the locale.
Definition: tagvalue.h:651
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:568
The Tag class is used to store, read and write tag information.
Definition: tag.h:177
#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