Mind encoding when converting TagValue to pos

This commit is contained in:
Martchus 2017-05-31 00:53:42 +02:00
parent b76d35acfd
commit 6b705d5652
3 changed files with 32 additions and 22 deletions

View File

@ -65,13 +65,10 @@ Id3v2Frame::Id3v2Frame(const identifierType &id, const TagValue &value, const by
* \returns Returns the genre index or -1 if the specified string does not denote a genre index.
*/
template<class stringtype>
int parseGenreIndex(const stringtype &denotation, bool isBigEndian = false)
int parseGenreIndex(const stringtype &denotation)
{
int index = -1;
for(auto c : denotation) {
if(sizeof(typename stringtype::value_type) == 2 && isBigEndian != CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN) {
c = swapOrder(static_cast<uint16>(c));
}
if(index == -1) {
switch(c) {
case ' ':
@ -272,7 +269,7 @@ void Id3v2Frame::parse(BinaryReader &reader, const uint32 version, const uint32
int genreIndex;
if(characterSize(dataEncoding) > 1) {
auto genreDenotation = parseWideString(buffer.get() + 1, m_dataSize - 1, dataEncoding);
genreIndex = parseGenreIndex(genreDenotation, dataEncoding == TagTextEncoding::Utf16BigEndian);
genreIndex = parseGenreIndex(genreDenotation);
} else {
auto genreDenotation = parseString(buffer.get() + 1, m_dataSize - 1, dataEncoding);
genreIndex = parseGenreIndex(genreDenotation);
@ -675,20 +672,7 @@ u16string Id3v2Frame::parseWideString(const char *buffer, size_t dataSize, TagTe
{
auto substr = parseSubstring(buffer, dataSize, encoding, addWarnings);
u16string res(reinterpret_cast<u16string::const_pointer>(get<0>(substr)), get<1>(substr) / 2);
if(encoding !=
#if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN)
TagTextEncoding::Utf16LittleEndian
#elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN)
TagTextEncoding::Utf16BigEndian
#else
# error "Host byte order not supported"
#endif
) {
// ensure byte order matches host byte order
for(auto &c : res) {
c = ((c >> 8) & 0x00FF) | ((c << 8) & 0xFF00);
}
}
TagValue::ensureHostByteOrder(res, encoding);
return res;
}

View File

@ -249,8 +249,9 @@ PositionInSet TagValue::toPositionInSet() const
return PositionInSet(string(m_ptr.get(), m_size));
case TagTextEncoding::Utf16LittleEndian:
case TagTextEncoding::Utf16BigEndian:
// FIXME: Ensure endianness is correctly
return PositionInSet(u16string(reinterpret_cast<char16_t *>(m_ptr.get()), m_size / 2));
u16string u16str(reinterpret_cast<char16_t *>(m_ptr.get()), m_size / 2);
ensureHostByteOrder(u16str, m_encoding);
return PositionInSet(u16str);
}
case TagDataType::Integer:
case TagDataType::PositionInSet:
@ -705,6 +706,27 @@ void TagValue::stripBom(const char *&text, size_t &length, TagTextEncoding encod
}
}
/*!
* \brief Ensures the byte-order of the specified UTF-16 string matches the byte-order of the machine.
* \remarks Does nothing if \a currentEncoding already matches the byte-order of the machine.
*/
void TagValue::ensureHostByteOrder(u16string &u16str, TagTextEncoding currentEncoding)
{
if(currentEncoding !=
#if defined(CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN)
TagTextEncoding::Utf16LittleEndian
#elif defined(CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN)
TagTextEncoding::Utf16BigEndian
#else
# error "Host byte order not supported"
#endif
) {
for(auto &c : u16str) {
c = swapOrder(static_cast<uint16>(c));
}
}
}
/*!
* \brief Returns an empty TagValue.
*/

View File

@ -14,6 +14,7 @@
namespace Media {
class Tag;
class Id3v2Frame;
/*!
* \brief Specifies the text encoding.
@ -62,6 +63,8 @@ enum class TagDataType : unsigned int
class TAG_PARSER_EXPORT TagValue
{
friend class Id3v2Frame; // FIXME: make ensureHostByteOrder() public in next minor release
public:
// constructor, destructor
TagValue();
@ -124,7 +127,8 @@ public:
private:
void stripBom(const char *&text, size_t &length, TagTextEncoding encoding);
static void stripBom(const char *&text, size_t &length, TagTextEncoding encoding);
static void ensureHostByteOrder(std::u16string &u16str, TagTextEncoding currentEncoding);
std::unique_ptr<char[]> m_ptr;
std::string::size_type m_size;