Tag Parser 10.3.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,
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
513inline bool TagValue::isNull() const
514{
515 return m_ptr == nullptr;
516}
517
527inline bool TagValue::isEmpty() const
528{
529 return m_ptr == nullptr || m_size == 0;
530}
531
539{
540 m_size = 0;
541 m_ptr.reset();
542}
543
550{
551 clearData();
553}
554
559inline std::size_t TagValue::dataSize() const
560{
561 return m_size;
562}
563
571{
572 return m_ptr.get();
573}
574
575inline const char *TagValue::dataPointer() const
576{
577 return m_ptr.get();
578}
579
583inline std::string_view TagValue::data() const
584{
585 return std::string_view(m_ptr.get(), m_size);
586}
587
598inline const std::string &TagValue::description() const
599{
600 return m_desc;
601}
602
614inline void TagValue::setDescription(std::string_view value, TagTextEncoding encoding)
615{
616 m_desc = value;
617 m_descEncoding = encoding;
618}
619
627inline const std::string &TagValue::mimeType() const
628{
629 return m_mimeType;
630}
631
639inline void TagValue::setMimeType(std::string_view mimeType)
640{
641 m_mimeType = mimeType;
642}
643
653inline const Locale &TagValue::locale() const
654{
655 return m_locale;
656}
657
668{
669 return m_locale;
670}
671
681inline 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
714{
715 return m_flags & TagValueFlags::ReadOnly;
716}
717
727inline void TagValue::setReadonly(bool readOnly)
728{
729 CppUtilities::modFlagEnum(m_flags, TagValueFlags::ReadOnly, readOnly);
730}
731
736inline const std::unordered_map<std::string, std::string> &TagValue::nativeData() const
737{
738 return m_nativeData;
739}
740
745inline 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
775template <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>> *>
778std::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
791inline 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
799inline 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
TagValue & operator=(TagValue &&other)=default
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
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