From 9dc458f5725536ca11da1e60d5580635509d59b7 Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 26 Jun 2017 23:44:14 +0200 Subject: [PATCH] WIP: Allow conversion of TagValue to any number --- tagvalue.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++-- tagvalue.h | 7 +++-- 2 files changed, 81 insertions(+), 4 deletions(-) diff --git a/tagvalue.cpp b/tagvalue.cpp index 9dc6eb6..33a7467 100644 --- a/tagvalue.cpp +++ b/tagvalue.cpp @@ -177,6 +177,7 @@ int32 TagValue::toInteger() const ensureHostByteOrder(u16str, m_encoding); return ConversionUtilities::stringToNumber(u16str); } + break; case TagDataType::Integer: case TagDataType::PositionInSet: case TagDataType::StandardGenreIndex: @@ -192,6 +193,59 @@ int32 TagValue::toInteger() const return 0; } +/*! + * \brief Converts the value of the current TagValue object to its equivalent integer representation. + * \tparam Specifies the integer type to convert to. + * \remarks Precision loss or overflow might occur if \a NumberType isn't suitable to hold the assigned + * number. + * \throws Throws ConversionException on failure. + */ +template +NumberType TagValue::toNumber() const +{ + if(!isEmpty()) { + switch(m_type) { + case TagDataType::Text: + switch(m_encoding) { + case TagTextEncoding::Unspecified: + case TagTextEncoding::Latin1: + case TagTextEncoding::Utf8: + return ConversionUtilities::bufferToNumber(m_ptr.get(), m_size); + case TagTextEncoding::Utf16LittleEndian: + case TagTextEncoding::Utf16BigEndian: + u16string u16str(reinterpret_cast(m_ptr.get()), m_size / 2); + ensureHostByteOrder(u16str, m_encoding); + return ConversionUtilities::stringToNumber(u16str); + } + break; + case TagDataType::Integer: + case TagDataType::PositionInSet: + case TagDataType::StandardGenreIndex: + if(m_size == sizeof(int32)) { + return static_cast(*reinterpret_cast(m_ptr.get())); + } else(m_size == sizeof(int64)) { + // maybe support assignment of 64-bit int in the future + return static_cast(*reinterpret_cast(m_ptr.get())); + } else { + throw ConversionException("Can not convert assigned data to integer because the data size is not appropriate."); + } + break; + case TagDataType::Float: + if(m_size == sizeof(float)) { + return static_cast(*reinterpret_cast(m_ptr.get())); + } else if(m_size == sizeof(double)) { + return static_cast(*reinterpret_cast(m_ptr.get())); + } else { + throw ConversionException("Can not convert assigned float to integer because the data size is not appropriate."); + } + break; + default: + throw ConversionException("Can not convert binary data/picture/time span/date time to integer."); + } + } + return 0; +} + /*! * \brief Converts the value of the current TagValue object to its equivalent * standard genre index. @@ -283,7 +337,17 @@ TimeSpan TagValue::toTimeSpan() const if(!isEmpty()) { switch(m_type) { case TagDataType::Text: - return TimeSpan::fromString(string(m_ptr.get(), m_size)); + switch(m_encoding) { + case TagTextEncoding::Unspecified: + case TagTextEncoding::Latin1: + case TagTextEncoding::Utf8: + return TimeSpan::fromString(string(m_ptr.get(), m_size)); + case TagTextEncoding::Utf16LittleEndian: + return TimeSpan::fromString(convertUtf16LEToUtf8(m_ptr.get(), m_size)); + case TagTextEncoding::Utf16BigEndian: + return TimeSpan::fromString(convertUtf16BEToUtf8(m_ptr.get(), m_size)); + } + break; case TagDataType::Integer: case TagDataType::TimeSpan: switch(m_size) { @@ -311,7 +375,17 @@ DateTime TagValue::toDateTime() const if(!isEmpty()) { switch(m_type) { case TagDataType::Text: - return DateTime::fromString(string(m_ptr.get(), m_size)); + switch(m_encoding) { + case TagTextEncoding::Unspecified: + case TagTextEncoding::Latin1: + case TagTextEncoding::Utf8: + return DateTime::fromString(string(m_ptr.get(), m_size)); + case TagTextEncoding::Utf16LittleEndian: + return DateTime::fromString(convertUtf16LEToUtf8(m_ptr.get(), m_size)); + case TagTextEncoding::Utf16BigEndian: + return DateTime::fromString(convertUtf16BEToUtf8(m_ptr.get(), m_size)); + } + break; case TagDataType::Integer: case TagDataType::DateTime: if(m_size == sizeof(int32)) { diff --git a/tagvalue.h b/tagvalue.h index 7e2c539..4f1d6f5 100644 --- a/tagvalue.h +++ b/tagvalue.h @@ -51,14 +51,15 @@ inline int characterSize(TagTextEncoding encoding) { enum class TagDataType : unsigned int { Text, /**< text/string */ - Integer, /**< integer */ + Integer, /**< integer, up to 64-bit */ PositionInSet, /**< position in set, see Media::PositionInSet */ StandardGenreIndex, /**< pre-defined genre name denoted by numerical code */ TimeSpan, /**< time span, see ChronoUtils::TimeSpan */ DateTime, /**< date time, see ChronoUtils::DateTime */ Picture, /**< picture file */ Binary, /**< unspecified binary data */ - Undefined /**< undefined/invalid data type */ + Undefined, /**< undefined/invalid data type */ + Float, /**< IEEE float, 32- or 64-bit */ }; class TAG_PARSER_EXPORT TagValue @@ -95,6 +96,8 @@ public: std::u16string toWString(TagTextEncoding encoding = TagTextEncoding::Unspecified) const; void toWString(std::u16string &result, TagTextEncoding encoding = TagTextEncoding::Unspecified) const; int32 toInteger() const; + template + NumberType toNumber() const; int toStandardGenreIndex() const; PositionInSet toPositionInSet() const; ChronoUtilities::TimeSpan toTimeSpan() const;