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."));
480 if (m_size ==
sizeof(std::int32_t)) {
481 return DateTime(*(reinterpret_cast<std::uint32_t *>(m_ptr.get())));
482 }
else if (m_size ==
sizeof(std::int64_t)) {
483 return DateTime(*(reinterpret_cast<std::uint64_t *>(m_ptr.get())));
485 throw ConversionException(
"The size of the assigned integer is not appropriate for conversion to date time.");
488 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to date time."));
503 if (m_encoding == encoding) {
507 StringData encodedData;
513 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
516 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
519 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
529 = convertString(inputParameter.first, outputParameter.first, m_ptr.get(), m_size, outputParameter.second / inputParameter.second);
533 m_ptr = make_unique<char[]>(m_size = encodedData.second);
534 copy(encodedData.first.get(), encodedData.first.get() + encodedData.second, m_ptr.get());
536 m_encoding = encoding;
555 if (encoding == m_descEncoding) {
558 if (m_desc.empty()) {
559 m_descEncoding = encoding;
562 StringData encodedData;
568 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
571 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
574 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
583 encodedData = convertString(
584 inputParameter.first, outputParameter.first, m_desc.data(), m_desc.size(), outputParameter.second / inputParameter.second);
587 m_desc.assign(encodedData.first.get(), encodedData.second);
588 m_descEncoding = encoding;
613 result.assign(m_ptr.get(), m_size);
615 StringData encodedData;
621 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
624 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
627 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
637 = convertString(inputParameter.first, outputParameter.first, m_ptr.get(), m_size, outputParameter.second / inputParameter.second);
640 result.assign(encodedData.first.get(), encodedData.second);
654 result.assign(genreName);
656 throw ConversionException(
"No string representation for the assigned standard genre index available.");
667 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to string."));
671 : convertUtf8ToUtf16BE(result.data(), result.size());
672 result.assign(encodedData.first.get(), encodedData.second);
693 string regularStrRes;
697 result.assign(reinterpret_cast<const char16_t *>(m_ptr.get()), m_size /
sizeof(char16_t));
699 StringData encodedData;
705 encodedData = convertLatin1ToUtf8(m_ptr.get(), m_size);
708 encodedData = convertUtf16LEToUtf8(m_ptr.get(), m_size);
711 encodedData = convertUtf16BEToUtf8(m_ptr.get(), m_size);
721 = convertString(inputParameter.first, outputParameter.first, m_ptr.get(), m_size, outputParameter.second / inputParameter.second);
724 result.assign(reinterpret_cast<const char16_t *>(encodedData.first.get()), encodedData.second /
sizeof(char16_t));
728 regularStrRes = numberToString(
toInteger());
736 regularStrRes.clear();
738 regularStrRes.assign(genreName);
740 throw ConversionException(
"No string representation for the assigned standard genre index available.");
748 throw ConversionException(argsToString(
"Can not convert ",
tagDataTypeString(m_type),
" to string."));
752 : convertUtf8ToUtf16BE(regularStrRes.data(), result.size());
753 result.assign(reinterpret_cast<const char16_t *>(encodedData.first.get()), encodedData.second /
sizeof(
const char16_t));
772 stripBom(text, textSize, textEncoding);
780 m_ptr = make_unique<char[]>(m_size = textSize);
781 copy(text, text + textSize, m_ptr.get());
785 StringData encodedData;
786 switch (textEncoding) {
791 encodedData = convertUtf8ToLatin1(text, textSize);
794 encodedData = convertUtf8ToUtf16LE(text, textSize);
797 encodedData = convertUtf8ToUtf16BE(text, textSize);
806 encodedData = convertString(inputParameter.first, outputParameter.first, text, textSize, outputParameter.second / inputParameter.second);
810 m_ptr = make_unique<char[]>(m_size = encodedData.second);
811 copy(encodedData.first.get(), encodedData.first.get() + encodedData.second, m_ptr.get());
820 m_size =
sizeof(value);
821 m_ptr = make_unique<char[]>(m_size);
822 std::copy(reinterpret_cast<const char *>(&value), reinterpret_cast<const char *>(&value) + m_size, m_ptr.get());
840 if (length > m_size) {
841 m_ptr = make_unique<char[]>(length);
844 std::copy(data, data + length, m_ptr.get());
850 m_encoding = encoding;
869 m_encoding = encoding;
880 if ((length >= 3) && (BE::toUInt24(text) == 0x00EFBBBF)) {
886 if ((length >= 2) && (LE::toUInt16(text) == 0xFEFF)) {
892 if ((length >= 2) && (BE::toUInt16(text) == 0xFEFF)) {
907 if (currentEncoding !=
908 #
if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN)
910 #elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN)
913 #error
"Host byte order not supported"
916 for (
auto &c : u16str) {
917 c = swapOrder(static_cast<std::uint16_t>(c));
925 bool TagValue::compareData(
const char *data1, std::size_t size1,
const char *data2, std::size_t size2,
bool ignoreCase)
927 if (size1 != size2) {
934 for (
auto i1 = data1, i2 = data2, end = data1 + size1; i1 != end; ++i1, ++i2) {
941 for (
auto i1 = data1, i2 = data2, end = data1 + size1; i1 != end; ++i1, ++i2) {
958 return emptyTagValue;