8 #include <c++utilities/conversion/binaryconversion.h>
9 #include <c++utilities/conversion/conversionexception.h>
10 #include <c++utilities/conversion/stringbuilder.h>
11 #include <c++utilities/conversion/stringconversion.h>
28 case TagDataType::Text:
30 case TagDataType::Integer:
32 case TagDataType::PositionInSet:
33 return "position in set";
34 case TagDataType::StandardGenreIndex:
36 case TagDataType::TimeSpan:
40 case TagDataType::Picture:
42 case TagDataType::Binary:
54 switch (tagTextEncoding) {
55 case TagTextEncoding::Latin1:
56 return make_pair(
"ISO-8859-1", 1.0f);
58 return make_pair(
"UTF-8", 1.0f);
59 case TagTextEncoding::Utf16LittleEndian:
60 return make_pair(
"UTF-16LE", 2.0f);
61 case TagTextEncoding::Utf16BigEndian:
62 return make_pair(
"UTF-16BE", 2.0f);
64 return make_pair(
nullptr, 0.0f);
97 : m_size(other.m_size)
98 , m_desc(other.m_desc)
99 , m_mimeType(other.m_mimeType)
100 , m_language(other.m_language)
101 , m_type(other.m_type)
102 , m_encoding(other.m_encoding)
103 , m_descEncoding(other.m_descEncoding)
104 , m_labeledAsReadonly(other.m_labeledAsReadonly)
107 m_ptr = make_unique<char[]>(m_size);
108 std::copy(other.m_ptr.get(), other.m_ptr.get() + other.m_size, m_ptr.get());
117 if (
this == &other) {
120 m_size = other.m_size;
121 m_type = other.m_type;
122 m_desc = other.m_desc;
123 m_mimeType = other.m_mimeType;
124 m_language = other.m_language;
125 m_labeledAsReadonly = other.m_labeledAsReadonly;
126 m_encoding = other.m_encoding;
127 m_descEncoding = other.m_descEncoding;
131 m_ptr = make_unique<char[]>(m_size);
132 std::copy(other.m_ptr.get(), other.m_ptr.get() + other.m_size, m_ptr.get());
186 if (m_mimeType != other.m_mimeType || m_language != other.m_language || m_labeledAsReadonly != other.m_labeledAsReadonly) {
197 const auto utfEncodingToUse = pickUtfEncoding(m_descEncoding, other.m_descEncoding);
198 StringData str1, str2;
199 const char *data1, *data2;
201 if (m_descEncoding != utfEncodingToUse) {
203 str1 = convertString(
204 inputParameter.first, outputParameter.first, m_desc.data(), m_desc.size(), outputParameter.second / inputParameter.second);
205 data1 = str1.first.get();
208 data1 = m_desc.data();
209 size1 = m_desc.size();
211 if (other.m_descEncoding != utfEncodingToUse) {
213 str2 = convertString(inputParameter.first, outputParameter.first, other.m_desc.data(), other.m_desc.size(),
214 outputParameter.second / inputParameter.second);
215 data2 = str2.first.get();
218 data2 = other.m_desc.data();
219 size2 = other.m_desc.size();
228 if (m_type == other.m_type) {
232 if (m_size != other.m_size && m_encoding == other.m_encoding) {
240 const auto utfEncodingToUse = pickUtfEncoding(m_encoding, other.m_encoding);
242 const char *data1, *data2;
244 if (m_encoding != utfEncodingToUse) {
252 if (other.m_encoding != utfEncodingToUse) {
253 str2 = other.
toString(utfEncodingToUse);
257 data2 = other.m_ptr.get();
258 size2 = other.m_size;
281 for (
const auto dataType : { m_type, other.m_type }) {
295 }
catch (
const ConversionException &) {
312 m_labeledAsReadonly =
false;
330 switch (m_encoding) {
334 return bufferToNumber<std::int32_t>(m_ptr.get(), m_size);
337 u16string u16str(
reinterpret_cast<char16_t *
>(m_ptr.get()), m_size / 2);
339 return stringToNumber<std::int32_t>(u16str);
343 return *
reinterpret_cast<std::int32_t *
>(m_ptr.get());
345 throw ConversionException(
"Can not convert assigned data to integer because the data size is not appropriate.");
348 if (m_size ==
sizeof(std::int32_t)) {
349 return *
reinterpret_cast<std::int32_t *
>(m_ptr.get());
351 throw ConversionException(
"Can not convert assigned data to integer because the data size is not appropriate.");
353 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to integer."));
372 }
catch (
const ConversionException &) {
384 if (m_size !=
sizeof(std::int32_t)) {
385 throw ConversionException(
"The assigned index/integer is of unappropriate size.");
387 index =
static_cast<int>(*
reinterpret_cast<std::int32_t *
>(m_ptr.get()));
390 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to genre index."));
393 throw ConversionException(
"The assigned number is not a valid standard genre index.");
410 switch (m_encoding) {
417 u16string u16str(
reinterpret_cast<char16_t *
>(m_ptr.get()), m_size / 2);
424 case sizeof(std::int32_t):
425 return PositionInSet(*(
reinterpret_cast<std::int32_t *
>(m_ptr.get())));
426 case 2 *
sizeof(std::int32_t):
428 *(
reinterpret_cast<std::int32_t *
>(m_ptr.get())), *(
reinterpret_cast<std::int32_t *
>(m_ptr.get() +
sizeof(std::int32_t))));
430 throw ConversionException(
"The size of the assigned data is not appropriate.");
433 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to position in set."));
453 case sizeof(std::int32_t):
454 return TimeSpan(*(
reinterpret_cast<std::int32_t *
>(m_ptr.get())));
455 case sizeof(std::int64_t):
456 return TimeSpan(*(
reinterpret_cast<std::int64_t *
>(m_ptr.get())));
458 throw ConversionException(
"The size of the assigned integer is not appropriate for conversion to time span.");
461 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to time span."));
479 return DateTime::fromIsoStringGmt(str.data());
480 }
catch (
const ConversionException &) {
481 return DateTime::fromString(str);
486 if (m_size ==
sizeof(std::int32_t)) {
487 return DateTime(*(
reinterpret_cast<std::uint32_t *
>(m_ptr.get())));
488 }
else if (m_size ==
sizeof(std::int64_t)) {
489 return DateTime(*(
reinterpret_cast<std::uint64_t *
>(m_ptr.get())));
491 throw ConversionException(
"The size of the assigned integer is not appropriate for conversion to date time.");
494 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to date time."));
509 if (m_encoding == encoding) {
513 StringData encodedData;
519 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
522 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
525 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
535 = convertString(inputParameter.first, outputParameter.first, m_ptr.get(), m_size, outputParameter.second / inputParameter.second);
539 m_ptr = make_unique<char[]>(m_size = encodedData.second);
540 copy(encodedData.first.get(), encodedData.first.get() + encodedData.second, m_ptr.get());
542 m_encoding = encoding;
561 if (encoding == m_descEncoding) {
564 if (m_desc.empty()) {
565 m_descEncoding = encoding;
568 StringData encodedData;
574 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
577 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
580 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
589 encodedData = convertString(
590 inputParameter.first, outputParameter.first, m_desc.data(), m_desc.size(), outputParameter.second / inputParameter.second);
593 m_desc.assign(encodedData.first.get(), encodedData.second);
594 m_descEncoding = encoding;
619 result.assign(m_ptr.get(), m_size);
621 StringData encodedData;
627 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
630 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
633 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
643 = convertString(inputParameter.first, outputParameter.first, m_ptr.get(), m_size, outputParameter.second / inputParameter.second);
646 result.assign(encodedData.first.get(), encodedData.second);
660 result.assign(genreName);
662 throw ConversionException(
"No string representation for the assigned standard genre index available.");
670 result =
toDateTime().toString(DateTimeOutputFormat::IsoOmittingDefaultComponents);
673 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to string."));
677 : convertUtf8ToUtf16BE(result.data(), result.size());
678 result.assign(encodedData.first.get(), encodedData.second);
699 string regularStrRes;
703 result.assign(
reinterpret_cast<const char16_t *
>(m_ptr.get()), m_size /
sizeof(char16_t));
705 StringData encodedData;
711 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
714 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
717 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
727 = convertString(inputParameter.first, outputParameter.first, m_ptr.get(), m_size, outputParameter.second / inputParameter.second);
730 result.assign(
reinterpret_cast<const char16_t *
>(encodedData.first.get()), encodedData.second /
sizeof(char16_t));
734 regularStrRes = numberToString(
toInteger());
742 regularStrRes.clear();
744 regularStrRes.assign(genreName);
746 throw ConversionException(
"No string representation for the assigned standard genre index available.");
754 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to string."));
758 : convertUtf8ToUtf16BE(regularStrRes.data(), result.size());
759 result.assign(
reinterpret_cast<const char16_t *
>(encodedData.first.get()), encodedData.second /
sizeof(
const char16_t));
778 stripBom(text, textSize, textEncoding);
786 m_ptr = make_unique<char[]>(m_size = textSize);
787 copy(text, text + textSize, m_ptr.get());
791 StringData encodedData;
792 switch (textEncoding) {
797 encodedData = convertUtf8ToLatin1(text, textSize);
800 encodedData = convertUtf8ToUtf16LE(text, textSize);
803 encodedData = convertUtf8ToUtf16BE(text, textSize);
812 encodedData = convertString(inputParameter.first, outputParameter.first, text, textSize, outputParameter.second / inputParameter.second);
816 m_ptr = make_unique<char[]>(m_size = encodedData.second);
817 copy(encodedData.first.get(), encodedData.first.get() + encodedData.second, m_ptr.get());
826 m_size =
sizeof(value);
827 m_ptr = make_unique<char[]>(m_size);
828 std::copy(
reinterpret_cast<const char *
>(&value),
reinterpret_cast<const char *
>(&value) + m_size, m_ptr.get());
846 if (length > m_size) {
847 m_ptr = make_unique<char[]>(length);
850 std::copy(data, data + length, m_ptr.get());
856 m_encoding = encoding;
875 m_encoding = encoding;
886 if ((length >= 3) && (BE::toUInt24(text) == 0x00EFBBBF)) {
892 if ((length >= 2) && (LE::toUInt16(text) == 0xFEFF)) {
898 if ((length >= 2) && (BE::toUInt16(text) == 0xFEFF)) {
913 if (currentEncoding !=
914 #
if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN)
916 #elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN)
919 #error
"Host byte order not supported"
922 for (
auto &c : u16str) {
923 c = swapOrder(
static_cast<std::uint16_t
>(c));
931 bool TagValue::compareData(
const char *data1, std::size_t size1,
const char *data2, std::size_t size2,
bool ignoreCase)
933 if (size1 != size2) {
940 for (
auto i1 = data1, i2 = data2, end = data1 + size1; i1 != end; ++i1, ++i2) {
947 for (
auto i1 = data1, i2 = data2, end = data1 + size1; i1 != end; ++i1, ++i2) {
964 return emptyTagValue;