Tag Parser 11.3.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#include "./tagtype.h"
7
8#include <c++utilities/chrono/datetime.h>
9#include <c++utilities/chrono/timespan.h>
10#include <c++utilities/conversion/binaryconversion.h>
11#include <c++utilities/misc/flagenumclass.h>
12#include <c++utilities/misc/traits.h>
13
14#include <cstdint>
15#include <cstring>
16#include <iosfwd>
17#include <memory>
18#include <string>
19#include <unordered_map>
20
21namespace TagParser {
22
23class Tag;
24class Id3v2Frame;
25
29enum class TagTextEncoding : unsigned int {
30 Latin1,
31 Utf8,
35};
36
43enum class TagValueFlags : std::uint64_t {
44 None,
45 ReadOnly,
46};
47
48} // namespace TagParser
49
51
52namespace TagParser {
53
58constexpr int characterSize(TagTextEncoding encoding)
59{
60 switch (encoding) {
63 return 1;
66 return 2;
67 default:
68 return 0;
69 }
70}
71
74 std::string user;
76 double rating = 0.0;
78 std::uint64_t playCounter = 0;
84
85 std::string toString() const;
86 static Popularity fromString(std::string_view str);
87
89 bool isEmpty() const
90 {
91 return user.empty() && rating == 0.0 && !playCounter;
92 }
93
98 bool operator==(const Popularity &other) const
99 {
100 return playCounter == other.playCounter && rating == other.rating && user == other.user && scale == other.scale;
101 }
102};
103
107enum class TagDataType : unsigned int {
108 Text,
109 Integer,
112 TimeSpan,
113 DateTime,
114 Picture,
115 Binary,
116 Undefined,
117 Popularity,
119};
120
124enum class TagValueComparisionFlags : unsigned int {
125 None,
126 CaseInsensitive = 0x1,
127 IgnoreMetaData = 0x2,
128};
129
131public:
132 // constructor, destructor
133 explicit TagValue();
134 explicit TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding = TagTextEncoding::Latin1,
136 explicit TagValue(
137 const char *text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
138 explicit TagValue(
139 const std::string &text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
140 explicit TagValue(
141 std::string_view text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
142 explicit TagValue(int value);
143 explicit TagValue(std::uint64_t value);
144 explicit TagValue(
145 const char *data, std::size_t length, TagDataType type = TagDataType::Undefined, TagTextEncoding encoding = TagTextEncoding::Latin1);
146 explicit TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type = TagDataType::Binary,
148 explicit TagValue(PositionInSet value);
149 explicit TagValue(CppUtilities::DateTime value);
150 explicit TagValue(CppUtilities::TimeSpan value);
151 explicit TagValue(const Popularity &value);
152 TagValue(const TagValue &other);
153 TagValue(TagValue &&other) = default;
154 ~TagValue();
155
156 // operators
157 TagValue &operator=(const TagValue &other);
158 TagValue &operator=(TagValue &&other) = default;
159 bool operator==(const TagValue &other) const;
160 bool operator!=(const TagValue &other) const;
161 operator bool() const;
162
163 // methods
164 bool isNull() const;
165 bool isEmpty() const;
166 void clearData();
167 void clearMetadata();
168 void clearDataAndMetadata();
169 TagDataType type() const;
170 std::string toString(TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
171 std::string toDisplayString() const;
172 void toString(std::string &result, TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
173 std::u16string toWString(TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
174 void toWString(std::u16string &result, TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
175 std::int32_t toInteger() const;
176 std::uint64_t toUnsignedInteger() const;
177 int toStandardGenreIndex() const;
178 PositionInSet toPositionInSet() const;
179 CppUtilities::TimeSpan toTimeSpan() const;
180 CppUtilities::DateTime toDateTime() const;
181 Popularity toPopularity() const;
182 std::size_t dataSize() const;
183 char *dataPointer();
184 const char *dataPointer() const;
185 std::string_view data() const;
186 const std::string &description() const;
187 void setDescription(std::string_view value, TagTextEncoding encoding = TagTextEncoding::Latin1);
188 const std::string &mimeType() const;
189 void setMimeType(std::string_view mimeType);
190 const Locale &locale() const;
191 Locale &locale();
192 void setLocale(const Locale &locale);
193 TagValueFlags flags() const;
194 void setFlags(TagValueFlags flags);
195 bool isLabeledAsReadonly() const;
196 void setReadonly(bool readOnly);
197 const std::unordered_map<std::string, std::string> &nativeData() const;
198 std::unordered_map<std::string, std::string> &nativeData();
199 TagTextEncoding dataEncoding() const;
200 void convertDataEncoding(TagTextEncoding encoding);
201 void convertDataEncodingForTag(const Tag *tag);
202 TagTextEncoding descriptionEncoding() const;
203 void convertDescriptionEncoding(TagTextEncoding encoding);
204 static const TagValue &empty();
205
206 void assignText(const char *text, std::size_t textSize, TagTextEncoding textEncoding = TagTextEncoding::Latin1,
208 void assignText(
209 const std::string &text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
210 void assignText(
211 std::string_view text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
212 void assignInteger(int value);
213 void assignUnsignedInteger(std::uint64_t value);
214 void assignStandardGenreIndex(int index);
215 void assignData(const char *data, std::size_t length, TagDataType type = TagDataType::Binary, TagTextEncoding encoding = TagTextEncoding::Latin1);
216 void assignData(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type = TagDataType::Binary,
218 void assignPosition(PositionInSet value);
219 void assignTimeSpan(CppUtilities::TimeSpan value);
220 void assignDateTime(CppUtilities::DateTime value);
221 void assignPopularity(const Popularity &value);
222
223 static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding);
224 static void ensureHostByteOrder(std::u16string &u16str, TagTextEncoding currentEncoding);
225 template <typename ContainerType,
226 CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsIteratable<ContainerType>,
227 std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>>
228 * = nullptr>
229 static std::vector<std::string> toStrings(const ContainerType &values, TagTextEncoding encoding = TagTextEncoding::Utf8);
230 bool compareTo(const TagValue &other, TagValueComparisionFlags options = TagValueComparisionFlags::None) const;
231 bool compareData(const TagValue &other, bool ignoreCase = false) const;
232 static bool compareData(const std::string &data1, const std::string &data2, bool ignoreCase = false);
233 static bool compareData(const char *data1, std::size_t size1, const char *data2, std::size_t size2, bool ignoreCase = false);
234
235private:
236 std::unique_ptr<char[]> m_ptr;
237 std::size_t m_size;
238 std::string m_desc;
239 std::string m_mimeType;
240 Locale m_locale;
241 std::unordered_map<std::string, std::string> m_nativeData;
242 TagDataType m_type;
243 TagTextEncoding m_encoding;
244 TagTextEncoding m_descEncoding;
245 TagValueFlags m_flags;
246};
247
252 : m_size(0)
253 , m_type(TagDataType::Undefined)
254 , m_encoding(TagTextEncoding::Latin1)
255 , m_descEncoding(TagTextEncoding::Latin1)
256 , m_flags(TagValueFlags::None)
257{
258}
259
264{
265}
266
277inline TagValue::TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding, TagTextEncoding convertTo)
278 : m_descEncoding(TagTextEncoding::Latin1)
279 , m_flags(TagValueFlags::None)
280{
281 assignText(text, textSize, textEncoding, convertTo);
282}
283
293inline TagValue::TagValue(const char *text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
294{
295 assignText(text, std::strlen(text), textEncoding, convertTo);
296}
297
307inline TagValue::TagValue(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
308 : m_descEncoding(TagTextEncoding::Latin1)
309 , m_flags(TagValueFlags::None)
310{
311 assignText(text, textEncoding, convertTo);
312}
313
323inline TagValue::TagValue(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
324 : m_descEncoding(TagTextEncoding::Latin1)
325 , m_flags(TagValueFlags::None)
326{
327 assignText(text, textEncoding, convertTo);
328}
329
333inline TagValue::TagValue(int value)
334 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::Integer)
335{
336}
337
341inline TagParser::TagValue::TagValue(std::uint64_t value)
342 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::UnsignedInteger)
343{
344}
345
356inline TagValue::TagValue(const char *data, std::size_t length, TagDataType type, TagTextEncoding encoding)
357 : m_size(length)
358 , m_type(type)
359 , m_encoding(encoding)
360 , m_descEncoding(TagTextEncoding::Latin1)
361 , m_flags(TagValueFlags::None)
362{
363 if (length) {
364 if (type == TagDataType::Text) {
365 stripBom(data, m_size, encoding);
366 }
367 m_ptr = std::make_unique<char[]>(m_size);
368 std::copy(data, data + m_size, m_ptr.get());
369 }
370}
371
384inline TagValue::TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type, TagTextEncoding encoding)
385 : m_size(length)
386 , m_type(type)
387 , m_encoding(encoding)
388 , m_descEncoding(TagTextEncoding::Latin1)
389 , m_flags(TagValueFlags::None)
390{
391 if (length) {
392 m_ptr = move(data);
393 }
394}
395
400 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::PositionInSet)
401{
402}
403
407inline TagValue::TagValue(CppUtilities::DateTime value)
408 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime)
409{
410}
411
415inline TagValue::TagValue(CppUtilities::TimeSpan value)
416 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan)
417{
418}
419
423inline TagValue::TagValue(const Popularity &value)
424 : TagValue()
425{
426 assignPopularity(value);
427}
428
433inline bool TagValue::operator==(const TagValue &other) const
434{
436}
437
442inline bool TagValue::operator!=(const TagValue &other) const
443{
445}
446
451inline TagParser::TagValue::operator bool() const
452{
453 return !isEmpty();
454}
455
465inline void TagValue::assignText(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
466{
467 assignText(text.data(), text.size(), textEncoding, convertTo);
468}
469
479inline void TagValue::assignText(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
480{
481 assignText(text.data(), text.size(), textEncoding, convertTo);
482}
483
488{
489 if (value.isNull()) {
491 clearData();
492 } else {
493 assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::PositionInSet);
494 }
495}
496
500inline void TagValue::assignTimeSpan(CppUtilities::TimeSpan value)
501{
502 assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan);
503}
504
508inline void TagValue::assignDateTime(CppUtilities::DateTime value)
509{
510 assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime);
511}
512
519{
520 assignInteger(index);
522}
523
528{
529 return m_type;
530}
531
544inline std::string TagValue::toString(TagTextEncoding encoding) const
545{
546 std::string res;
547 toString(res, encoding);
548 return res;
549}
550
557inline std::u16string TagValue::toWString(TagTextEncoding encoding) const
558{
559 std::u16string res;
560 toWString(res, encoding);
561 return res;
562}
563
571inline bool TagValue::isNull() const
572{
573 return m_ptr == nullptr;
574}
575
584inline bool TagValue::isEmpty() const
585{
586 return m_ptr == nullptr || m_size == 0;
587}
588
596{
597 m_size = 0;
598 m_ptr.reset();
599}
600
607{
608 clearData();
610}
611
616inline std::size_t TagValue::dataSize() const
617{
618 return m_size;
619}
620
628{
629 return m_ptr.get();
630}
631
632inline const char *TagValue::dataPointer() const
633{
634 return m_ptr.get();
635}
636
640inline std::string_view TagValue::data() const
641{
642 return std::string_view(m_ptr.get(), m_size);
643}
644
655inline const std::string &TagValue::description() const
656{
657 return m_desc;
658}
659
671inline void TagValue::setDescription(std::string_view value, TagTextEncoding encoding)
672{
673 m_desc = value;
674 m_descEncoding = encoding;
675}
676
684inline const std::string &TagValue::mimeType() const
685{
686 return m_mimeType;
687}
688
696inline void TagValue::setMimeType(std::string_view mimeType)
697{
698 m_mimeType = mimeType;
699}
700
710inline const Locale &TagValue::locale() const
711{
712 return m_locale;
713}
714
725{
726 return m_locale;
727}
728
738inline void TagValue::setLocale(const Locale &locale)
739{
740 m_locale = locale;
741}
742
748{
749 return m_flags;
750}
751
757{
758 m_flags = flags;
759}
760
771{
772 return m_flags & TagValueFlags::ReadOnly;
773}
774
784inline void TagValue::setReadonly(bool readOnly)
785{
786 CppUtilities::modFlagEnum(m_flags, TagValueFlags::ReadOnly, readOnly);
787}
788
793inline const std::unordered_map<std::string, std::string> &TagValue::nativeData() const
794{
795 return m_nativeData;
796}
797
802inline std::unordered_map<std::string, std::string> &TagValue::nativeData()
803{
804 return m_nativeData;
805}
806
813{
814 return m_encoding;
815}
816
823{
824 return m_descEncoding;
825}
826
832template <typename ContainerType,
833 CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsIteratable<ContainerType>,
834 std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>> *>
835std::vector<std::string> TagValue::toStrings(const ContainerType &values, TagTextEncoding encoding)
836{
837 std::vector<std::string> res;
838 res.reserve(values.size());
839 for (const auto &value : values) {
840 res.emplace_back(CppUtilities::Traits::dereferenceMaybe(value).toString(encoding));
841 }
842 return res;
843}
844
848inline bool TagValue::compareData(const TagValue &other, bool ignoreCase) const
849{
850 return compareData(m_ptr.get(), m_size, other.m_ptr.get(), other.m_size, ignoreCase);
851}
852
856inline bool TagValue::compareData(const std::string &data1, const std::string &data2, bool ignoreCase)
857{
858 return compareData(data1.data(), data1.size(), data2.data(), data2.size(), ignoreCase);
859}
860
861} // namespace TagParser
862
864
865#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:130
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:848
void setMimeType(std::string_view mimeType)
Sets the MIME type.
Definition: tagvalue.h:696
void setFlags(TagValueFlags flags)
Sets the flags.
Definition: tagvalue.h:756
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:793
void clearMetadata()
Wipes assigned meta data.
Definition: tagvalue.cpp:331
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:955
const std::string & mimeType() const
Returns the MIME type.
Definition: tagvalue.h:684
void assignInteger(int value)
Assigns the given integer value.
Definition: tagvalue.cpp:1006
bool compareTo(const TagValue &other, TagValueComparisionFlags options=TagValueComparisionFlags::None) const
Returns whether both instances are equal.
Definition: tagvalue.cpp:188
TagTextEncoding dataEncoding() const
Returns the data encoding.
Definition: tagvalue.h:812
void assignPosition(PositionInSet value)
Assigns the given PositionInSet value.
Definition: tagvalue.h:487
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:433
void setDescription(std::string_view value, TagTextEncoding encoding=TagTextEncoding::Latin1)
Sets the description.
Definition: tagvalue.h:671
TagDataType type() const
Returns the type of the assigned value.
Definition: tagvalue.h:527
void assignPopularity(const Popularity &value)
Assigns the specified popularity value.
Definition: tagvalue.cpp:1077
void assignTimeSpan(CppUtilities::TimeSpan value)
Assigns the given TimeSpan value.
Definition: tagvalue.h:500
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:835
void clearDataAndMetadata()
Wipes assigned data including meta data.
Definition: tagvalue.h:606
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:508
bool isLabeledAsReadonly() const
Returns an indication whether the value is labeled as read-only.
Definition: tagvalue.h:770
TagValueFlags flags() const
Returns the flags.
Definition: tagvalue.h:747
bool operator!=(const TagValue &other) const
Returns whether both instances are not equal.
Definition: tagvalue.h:442
~TagValue()
Destroys the TagValue.
Definition: tagvalue.h:263
std::string_view data() const
Returns the currently assigned raw data.
Definition: tagvalue.h:640
TagValue & operator=(TagValue &&other)=default
std::size_t dataSize() const
Returns the size of the assigned value in bytes.
Definition: tagvalue.h:616
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:557
TagTextEncoding descriptionEncoding() const
Returns the description encoding.
Definition: tagvalue.h:822
void assignStandardGenreIndex(int index)
Assigns the given standard genre index to be assigned.
Definition: tagvalue.h:518
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:544
bool isNull() const
Returns whether no value is assigned at all.
Definition: tagvalue.h:571
void setLocale(const Locale &locale)
Sets the setLocale.
Definition: tagvalue.h:738
void setReadonly(bool readOnly)
Sets whether the TagValue is labeled as read-only.
Definition: tagvalue.h:784
static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding)
Strips the byte order mask from the specified text.
Definition: tagvalue.cpp:1099
void clearData()
Clears the assigned data.
Definition: tagvalue.h:595
bool isEmpty() const
Returns whether no or an empty value is assigned.
Definition: tagvalue.h:584
const std::string & description() const
Returns the description.
Definition: tagvalue.h:655
const Locale & locale() const
Returns the locale.
Definition: tagvalue.h:710
TagValue()
Constructs an empty TagValue.
Definition: tagvalue.h:251
char * dataPointer()
Returns a pointer to the raw data assigned to the current instance.
Definition: tagvalue.h:627
The Tag class is used to store, read and write tag information.
Definition: tag.h:163
#define TAG_PARSER_EXPORT
Marks the symbol to be exported by the tagparser library.
constexpr TAG_PARSER_EXPORT std::string_view rating()
constexpr TAG_PARSER_EXPORT std::string_view description()
constexpr TAG_PARSER_EXPORT std::string_view playCounter()
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:58
TagTextEncoding
Specifies the text encoding.
Definition: tagvalue.h:29
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
TagType
Specifies the tag type.
Definition: tagtype.h:11
TagValueComparisionFlags
The TagValueComparisionOption enum specifies options for TagValue::compareTo().
Definition: tagvalue.h:124
TagValueFlags
Specifies additional flags about the tag value.
Definition: tagvalue.h:43
TagDataType
Specifies the data type.
Definition: tagvalue.h:107
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
std::string user
The user who gave the rating / played the file, e.g. identified by e-mail address.
Definition: tagvalue.h:74
bool isEmpty() const
Returns whether the Popularity is empty. The scale and zero-values don't count.
Definition: tagvalue.h:89
bool operator==(const Popularity &other) const
Returns whether two instances are equal.
Definition: tagvalue.h:98
std::uint64_t playCounter
Play counter specific to the user.
Definition: tagvalue.h:78
TagType scale
Specifies the scale used for rating by the tag defining that scale.
Definition: tagvalue.h:83
double rating
The rating on a tag type specific scale.
Definition: tagvalue.h:76