Tag Parser 11.4.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;
83
84 bool scaleTo(TagType targetScale);
85 Popularity scaled(TagType targetScale) const;
86 std::string toString() const;
87 static Popularity fromString(std::string_view str);
88 static Popularity fromString(std::string_view str, TagType scale);
89
91 bool isEmpty() const
92 {
93 return user.empty() && rating == 0.0 && !playCounter;
94 }
95
100 bool operator==(const Popularity &other) const
101 {
102 return playCounter == other.playCounter && rating == other.rating && user == other.user && scale == other.scale;
103 }
104};
105
109inline Popularity Popularity::scaled(TagType targetScale) const
110{
111 auto copy = *this;
112 copy.scaleTo(targetScale);
113 return copy;
114}
115
119enum class TagDataType : unsigned int {
120 Text,
121 Integer,
124 TimeSpan,
125 DateTime,
126 Picture,
127 Binary,
128 Undefined,
129 Popularity,
131};
132
136enum class TagValueComparisionFlags : unsigned int {
137 None,
138 CaseInsensitive = 0x1,
139 IgnoreMetaData = 0x2,
140};
141
143public:
144 // constructor, destructor
145 explicit TagValue();
146 explicit TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding = TagTextEncoding::Latin1,
148 explicit TagValue(
149 const char *text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
150 explicit TagValue(
151 const std::string &text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
152 explicit TagValue(
153 std::string_view text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
154 explicit TagValue(int value);
155 explicit TagValue(std::uint64_t value);
156 explicit TagValue(
157 const char *data, std::size_t length, TagDataType type = TagDataType::Undefined, TagTextEncoding encoding = TagTextEncoding::Latin1);
158 explicit TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type = TagDataType::Binary,
160 explicit TagValue(PositionInSet value);
161 explicit TagValue(CppUtilities::DateTime value);
162 explicit TagValue(CppUtilities::TimeSpan value);
163 explicit TagValue(const Popularity &value);
164 TagValue(const TagValue &other);
165 TagValue(TagValue &&other) = default;
166 ~TagValue();
167
168 // operators
169 TagValue &operator=(const TagValue &other);
170 TagValue &operator=(TagValue &&other) = default;
171 bool operator==(const TagValue &other) const;
172 bool operator!=(const TagValue &other) const;
173 operator bool() const;
174
175 // methods
176 bool isNull() const;
177 bool isEmpty() const;
178 void clearData();
179 void clearMetadata();
180 void clearDataAndMetadata();
181 TagDataType type() const;
182 std::string toString(TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
183 std::string toDisplayString() const;
184 void toString(std::string &result, TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
185 std::u16string toWString(TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
186 void toWString(std::u16string &result, TagTextEncoding encoding = TagTextEncoding::Unspecified) const;
187 std::int32_t toInteger() const;
188 std::uint64_t toUnsignedInteger() const;
189 int toStandardGenreIndex() const;
190 PositionInSet toPositionInSet() const;
191 CppUtilities::TimeSpan toTimeSpan() const;
192 CppUtilities::DateTime toDateTime() const;
193 Popularity toPopularity() const;
194 Popularity toScaledPopularity(TagType scale = TagType::Unspecified) const;
195 std::size_t dataSize() const;
196 char *dataPointer();
197 const char *dataPointer() const;
198 std::string_view data() const;
199 const std::string &description() const;
200 void setDescription(std::string_view value, TagTextEncoding encoding = TagTextEncoding::Latin1);
201 const std::string &mimeType() const;
202 void setMimeType(std::string_view mimeType);
203 const Locale &locale() const;
204 Locale &locale();
205 void setLocale(const Locale &locale);
206 TagValueFlags flags() const;
207 void setFlags(TagValueFlags flags);
208 bool isLabeledAsReadonly() const;
209 void setReadonly(bool readOnly);
210 const std::unordered_map<std::string, std::string> &nativeData() const;
211 std::unordered_map<std::string, std::string> &nativeData();
212 TagTextEncoding dataEncoding() const;
213 void convertDataEncoding(TagTextEncoding encoding);
214 void convertDataEncodingForTag(const Tag *tag);
215 TagTextEncoding descriptionEncoding() const;
216 void convertDescriptionEncoding(TagTextEncoding encoding);
217 static const TagValue &empty();
218
219 void assignText(const char *text, std::size_t textSize, TagTextEncoding textEncoding = TagTextEncoding::Latin1,
221 void assignText(
222 const std::string &text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
223 void assignText(
224 std::string_view text, TagTextEncoding textEncoding = TagTextEncoding::Latin1, TagTextEncoding convertTo = TagTextEncoding::Unspecified);
225 void assignInteger(int value);
226 void assignUnsignedInteger(std::uint64_t value);
227 void assignStandardGenreIndex(int index);
228 void assignData(const char *data, std::size_t length, TagDataType type = TagDataType::Binary, TagTextEncoding encoding = TagTextEncoding::Latin1);
229 void assignData(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type = TagDataType::Binary,
231 void assignPosition(PositionInSet value);
232 void assignTimeSpan(CppUtilities::TimeSpan value);
233 void assignDateTime(CppUtilities::DateTime value);
234 void assignPopularity(const Popularity &value);
235
236 static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding);
237 static void ensureHostByteOrder(std::u16string &u16str, TagTextEncoding currentEncoding);
238 template <typename ContainerType,
239 CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsIteratable<ContainerType>,
240 std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>>
241 * = nullptr>
242 static std::vector<std::string> toStrings(const ContainerType &values, TagTextEncoding encoding = TagTextEncoding::Utf8);
243 bool compareTo(const TagValue &other, TagValueComparisionFlags options = TagValueComparisionFlags::None) const;
244 bool compareData(const TagValue &other, bool ignoreCase = false) const;
245 static bool compareData(const std::string &data1, const std::string &data2, bool ignoreCase = false);
246 static bool compareData(const char *data1, std::size_t size1, const char *data2, std::size_t size2, bool ignoreCase = false);
247
248private:
249 std::unique_ptr<char[]> m_ptr;
250 std::size_t m_size;
251 std::string m_desc;
252 std::string m_mimeType;
253 Locale m_locale;
254 std::unordered_map<std::string, std::string> m_nativeData;
255 TagDataType m_type;
256 TagTextEncoding m_encoding;
257 TagTextEncoding m_descEncoding;
258 TagValueFlags m_flags;
259};
260
265 : m_size(0)
266 , m_type(TagDataType::Undefined)
267 , m_encoding(TagTextEncoding::Latin1)
268 , m_descEncoding(TagTextEncoding::Latin1)
269 , m_flags(TagValueFlags::None)
270{
271}
272
277{
278}
279
290inline TagValue::TagValue(const char *text, std::size_t textSize, TagTextEncoding textEncoding, TagTextEncoding convertTo)
291 : m_descEncoding(TagTextEncoding::Latin1)
292 , m_flags(TagValueFlags::None)
293{
294 assignText(text, textSize, textEncoding, convertTo);
295}
296
306inline TagValue::TagValue(const char *text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
307{
308 assignText(text, std::strlen(text), textEncoding, convertTo);
309}
310
320inline TagValue::TagValue(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
321 : m_descEncoding(TagTextEncoding::Latin1)
322 , m_flags(TagValueFlags::None)
323{
324 assignText(text, textEncoding, convertTo);
325}
326
336inline TagValue::TagValue(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
337 : m_descEncoding(TagTextEncoding::Latin1)
338 , m_flags(TagValueFlags::None)
339{
340 assignText(text, textEncoding, convertTo);
341}
342
346inline TagValue::TagValue(int value)
347 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::Integer)
348{
349}
350
354inline TagParser::TagValue::TagValue(std::uint64_t value)
355 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::UnsignedInteger)
356{
357}
358
369inline TagValue::TagValue(const char *data, std::size_t length, TagDataType type, TagTextEncoding encoding)
370 : m_size(length)
371 , m_type(type)
372 , m_encoding(encoding)
373 , m_descEncoding(TagTextEncoding::Latin1)
374 , m_flags(TagValueFlags::None)
375{
376 if (length) {
377 if (type == TagDataType::Text) {
378 stripBom(data, m_size, encoding);
379 }
380 m_ptr = std::make_unique<char[]>(m_size);
381 std::copy(data, data + m_size, m_ptr.get());
382 }
383}
384
397inline TagValue::TagValue(std::unique_ptr<char[]> &&data, std::size_t length, TagDataType type, TagTextEncoding encoding)
398 : m_size(length)
399 , m_type(type)
400 , m_encoding(encoding)
401 , m_descEncoding(TagTextEncoding::Latin1)
402 , m_flags(TagValueFlags::None)
403{
404 if (length) {
405 m_ptr = move(data);
406 }
407}
408
413 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::PositionInSet)
414{
415}
416
420inline TagValue::TagValue(CppUtilities::DateTime value)
421 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime)
422{
423}
424
428inline TagValue::TagValue(CppUtilities::TimeSpan value)
429 : TagValue(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan)
430{
431}
432
436inline TagValue::TagValue(const Popularity &value)
437 : TagValue()
438{
439 assignPopularity(value);
440}
441
446inline bool TagValue::operator==(const TagValue &other) const
447{
449}
450
455inline bool TagValue::operator!=(const TagValue &other) const
456{
458}
459
464inline TagParser::TagValue::operator bool() const
465{
466 return !isEmpty();
467}
468
478inline void TagValue::assignText(const std::string &text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
479{
480 assignText(text.data(), text.size(), textEncoding, convertTo);
481}
482
492inline void TagValue::assignText(std::string_view text, TagTextEncoding textEncoding, TagTextEncoding convertTo)
493{
494 assignText(text.data(), text.size(), textEncoding, convertTo);
495}
496
501{
502 if (value.isNull()) {
504 clearData();
505 } else {
506 assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::PositionInSet);
507 }
508}
509
513inline void TagValue::assignTimeSpan(CppUtilities::TimeSpan value)
514{
515 assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::TimeSpan);
516}
517
521inline void TagValue::assignDateTime(CppUtilities::DateTime value)
522{
523 assignData(reinterpret_cast<const char *>(&value), sizeof(value), TagDataType::DateTime);
524}
525
532{
533 assignInteger(index);
535}
536
541{
542 return m_type;
543}
544
557inline std::string TagValue::toString(TagTextEncoding encoding) const
558{
559 std::string res;
560 toString(res, encoding);
561 return res;
562}
563
570inline std::u16string TagValue::toWString(TagTextEncoding encoding) const
571{
572 std::u16string res;
573 toWString(res, encoding);
574 return res;
575}
576
584inline bool TagValue::isNull() const
585{
586 return m_ptr == nullptr;
587}
588
597inline bool TagValue::isEmpty() const
598{
599 return m_ptr == nullptr || m_size == 0;
600}
601
609{
610 m_size = 0;
611 m_ptr.reset();
612}
613
620{
621 clearData();
623}
624
629inline std::size_t TagValue::dataSize() const
630{
631 return m_size;
632}
633
641{
642 return m_ptr.get();
643}
644
645inline const char *TagValue::dataPointer() const
646{
647 return m_ptr.get();
648}
649
653inline std::string_view TagValue::data() const
654{
655 return std::string_view(m_ptr.get(), m_size);
656}
657
668inline const std::string &TagValue::description() const
669{
670 return m_desc;
671}
672
684inline void TagValue::setDescription(std::string_view value, TagTextEncoding encoding)
685{
686 m_desc = value;
687 m_descEncoding = encoding;
688}
689
697inline const std::string &TagValue::mimeType() const
698{
699 return m_mimeType;
700}
701
709inline void TagValue::setMimeType(std::string_view mimeType)
710{
711 m_mimeType = mimeType;
712}
713
723inline const Locale &TagValue::locale() const
724{
725 return m_locale;
726}
727
738{
739 return m_locale;
740}
741
751inline void TagValue::setLocale(const Locale &locale)
752{
753 m_locale = locale;
754}
755
761{
762 return m_flags;
763}
764
770{
771 m_flags = flags;
772}
773
784{
785 return m_flags & TagValueFlags::ReadOnly;
786}
787
797inline void TagValue::setReadonly(bool readOnly)
798{
799 CppUtilities::modFlagEnum(m_flags, TagValueFlags::ReadOnly, readOnly);
800}
801
806inline const std::unordered_map<std::string, std::string> &TagValue::nativeData() const
807{
808 return m_nativeData;
809}
810
815inline std::unordered_map<std::string, std::string> &TagValue::nativeData()
816{
817 return m_nativeData;
818}
819
826{
827 return m_encoding;
828}
829
836{
837 return m_descEncoding;
838}
839
845template <typename ContainerType,
846 CppUtilities::Traits::EnableIf<CppUtilities::Traits::IsIteratable<ContainerType>,
847 std::is_same<typename std::add_const<typename std::remove_pointer<typename ContainerType::value_type>::type>::type, const TagValue>> *>
848std::vector<std::string> TagValue::toStrings(const ContainerType &values, TagTextEncoding encoding)
849{
850 std::vector<std::string> res;
851 res.reserve(values.size());
852 for (const auto &value : values) {
853 res.emplace_back(CppUtilities::Traits::dereferenceMaybe(value).toString(encoding));
854 }
855 return res;
856}
857
861inline bool TagValue::compareData(const TagValue &other, bool ignoreCase) const
862{
863 return compareData(m_ptr.get(), m_size, other.m_ptr.get(), other.m_size, ignoreCase);
864}
865
869inline bool TagValue::compareData(const std::string &data1, const std::string &data2, bool ignoreCase)
870{
871 return compareData(data1.data(), data1.size(), data2.data(), data2.size(), ignoreCase);
872}
873
874} // namespace TagParser
875
877
878#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:142
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:861
void setMimeType(std::string_view mimeType)
Sets the MIME type.
Definition: tagvalue.h:709
void setFlags(TagValueFlags flags)
Sets the flags.
Definition: tagvalue.h:769
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:806
void clearMetadata()
Wipes assigned meta data.
Definition: tagvalue.cpp:351
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:1014
const std::string & mimeType() const
Returns the MIME type.
Definition: tagvalue.h:697
void assignInteger(int value)
Assigns the given integer value.
Definition: tagvalue.cpp:1065
bool compareTo(const TagValue &other, TagValueComparisionFlags options=TagValueComparisionFlags::None) const
Returns whether both instances are equal.
Definition: tagvalue.cpp:208
TagTextEncoding dataEncoding() const
Returns the data encoding.
Definition: tagvalue.h:825
void assignPosition(PositionInSet value)
Assigns the given PositionInSet value.
Definition: tagvalue.h:500
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:446
void setDescription(std::string_view value, TagTextEncoding encoding=TagTextEncoding::Latin1)
Sets the description.
Definition: tagvalue.h:684
TagDataType type() const
Returns the type of the assigned value.
Definition: tagvalue.h:540
void assignPopularity(const Popularity &value)
Assigns the specified popularity value.
Definition: tagvalue.cpp:1136
void assignTimeSpan(CppUtilities::TimeSpan value)
Assigns the given TimeSpan value.
Definition: tagvalue.h:513
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:848
void clearDataAndMetadata()
Wipes assigned data including meta data.
Definition: tagvalue.h:619
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:521
bool isLabeledAsReadonly() const
Returns an indication whether the value is labeled as read-only.
Definition: tagvalue.h:783
TagValueFlags flags() const
Returns the flags.
Definition: tagvalue.h:760
bool operator!=(const TagValue &other) const
Returns whether both instances are not equal.
Definition: tagvalue.h:455
~TagValue()
Destroys the TagValue.
Definition: tagvalue.h:276
std::string_view data() const
Returns the currently assigned raw data.
Definition: tagvalue.h:653
TagValue & operator=(TagValue &&other)=default
std::size_t dataSize() const
Returns the size of the assigned value in bytes.
Definition: tagvalue.h:629
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:570
TagTextEncoding descriptionEncoding() const
Returns the description encoding.
Definition: tagvalue.h:835
void assignStandardGenreIndex(int index)
Assigns the given standard genre index to be assigned.
Definition: tagvalue.h:531
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:557
bool isNull() const
Returns whether no value is assigned at all.
Definition: tagvalue.h:584
void setLocale(const Locale &locale)
Sets the setLocale.
Definition: tagvalue.h:751
void setReadonly(bool readOnly)
Sets whether the TagValue is labeled as read-only.
Definition: tagvalue.h:797
static void stripBom(const char *&text, std::size_t &length, TagTextEncoding encoding)
Strips the byte order mask from the specified text.
Definition: tagvalue.cpp:1158
void clearData()
Clears the assigned data.
Definition: tagvalue.h:608
bool isEmpty() const
Returns whether no or an empty value is assigned.
Definition: tagvalue.h:597
const std::string & description() const
Returns the description.
Definition: tagvalue.h:668
const Locale & locale() const
Returns the locale.
Definition: tagvalue.h:723
TagValue()
Constructs an empty TagValue.
Definition: tagvalue.h:264
char * dataPointer()
Returns a pointer to the raw data assigned to the current instance.
Definition: tagvalue.h:640
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:136
TagValueFlags
Specifies additional flags about the tag value.
Definition: tagvalue.h:43
TagDataType
Specifies the data type.
Definition: tagvalue.h:119
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:91
bool operator==(const Popularity &other) const
Returns whether two instances are equal.
Definition: tagvalue.h:100
std::uint64_t playCounter
Play counter specific to the user.
Definition: tagvalue.h:78
bool scaleTo(TagType targetScale)
Scales the rating from the current scale to targetScale.
Definition: tagvalue.cpp:1255
Popularity scaled(TagType targetScale) const
Same as Popularity::scaleTo() but returns a new object.
Definition: tagvalue.h:109
TagType scale
Specifies the scale used for rating by the tag defining that scale.
Definition: tagvalue.h:82
double rating
The rating on a tag type specific scale.
Definition: tagvalue.h:76