From fb3cca2c44af4974a2e7ac06a6632bbf7635d161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sun, 16 Jan 2011 11:57:12 +0000 Subject: [PATCH] Support for ASF embedded pictures Patch by Anton Sergunov CCMAIL: setosha@gmail.com git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1214788 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- taglib/CMakeLists.txt | 1 + taglib/asf/CMakeLists.txt | 2 +- taglib/asf/Makefile.am | 4 +- taglib/asf/asfattribute.cpp | 36 ++++++- taglib/asf/asfattribute.h | 23 +++- taglib/asf/asffile.cpp | 2 +- taglib/asf/asffile.h | 1 + taglib/asf/asfpicture.cpp | 185 +++++++++++++++++++++++++++++++ taglib/asf/asfpicture.h | 192 +++++++++++++++++++++++++++++++++ taglib/taglib.pro | 4 + taglib/toolkit/tbytevector.cpp | 5 + taglib/toolkit/tbytevector.h | 11 ++ tests/test_asf.cpp | 74 +++++++++++++ tests/test_bytevector.cpp | 10 ++ 14 files changed, 541 insertions(+), 9 deletions(-) create mode 100644 taglib/asf/asfpicture.cpp create mode 100644 taglib/asf/asfpicture.h diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 70da391d..f050a5c4 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -150,6 +150,7 @@ asf/asftag.cpp asf/asffile.cpp asf/asfproperties.cpp asf/asfattribute.cpp +asf/asfpicture.cpp ) ELSE(WITH_ASF) SET(asf_SRCS) diff --git a/taglib/asf/CMakeLists.txt b/taglib/asf/CMakeLists.txt index 1cf3569a..2855beca 100644 --- a/taglib/asf/CMakeLists.txt +++ b/taglib/asf/CMakeLists.txt @@ -1 +1 @@ -INSTALL( FILES asffile.h asfproperties.h asftag.h asfattribute.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) +INSTALL( FILES asffile.h asfproperties.h asftag.h asfattribute.h asfpicture.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) diff --git a/taglib/asf/Makefile.am b/taglib/asf/Makefile.am index b5f79959..1ac457f5 100644 --- a/taglib/asf/Makefile.am +++ b/taglib/asf/Makefile.am @@ -6,7 +6,7 @@ INCLUDES = \ noinst_LTLIBRARIES = libasf.la -libasf_la_SOURCES = asfattribute.cpp asffile.cpp asfproperties.cpp asftag.cpp +libasf_la_SOURCES = asfattribute.cpp asffile.cpp asfproperties.cpp asftag.cpp asfpicture.cpp -taglib_include_HEADERS = asfattribute.h asffile.h asfproperties.h asftag.h +taglib_include_HEADERS = asfattribute.h asffile.h asfproperties.h asftag.h asfpicture.h taglib_includedir = $(includedir)/taglib diff --git a/taglib/asf/asfattribute.cpp b/taglib/asf/asfattribute.cpp index 3405f980..fd30456e 100644 --- a/taglib/asf/asfattribute.cpp +++ b/taglib/asf/asfattribute.cpp @@ -40,11 +40,13 @@ class ASF::Attribute::AttributePrivate : public RefCounter { public: AttributePrivate() - : stream(0), + : pictureValue(ASF::Picture::fromInvalid()), + stream(0), language(0) {} AttributeTypes type; String stringValue; ByteVector byteVectorValue; + ASF::Picture pictureValue; union { unsigned int intValue; unsigned short shortValue; @@ -101,6 +103,13 @@ ASF::Attribute::Attribute(const ByteVector &value) d->byteVectorValue = value; } +ASF::Attribute::Attribute(const ASF::Picture &value) +{ + d = new AttributePrivate; + d->type = BytesType; + d->pictureValue = value; +} + ASF::Attribute::Attribute(unsigned int value) { d = new AttributePrivate; @@ -144,6 +153,8 @@ ASF::Attribute::toString() const ByteVector ASF::Attribute::toByteVector() const { + if(d->pictureValue.isValid()) + return d->pictureValue.render(); return d->byteVectorValue; } @@ -171,12 +182,18 @@ ASF::Attribute::toULongLong() const return d->longLongValue; } +ASF::Picture +ASF::Attribute::toPicture() const +{ + return d->pictureValue; +} + String ASF::Attribute::parse(ASF::File &f, int kind) { - int size, nameLength; + uint size, nameLength; String name; - + d->pictureValue = Picture::fromInvalid(); // extended content descriptor if(kind == 0) { nameLength = f.readWORD(); @@ -234,6 +251,13 @@ ASF::Attribute::parse(ASF::File &f, int kind) break; } + if(d->type == BytesType && name == "WM/Picture") { + d->pictureValue.parse(d->byteVectorValue); + if(d->pictureValue.isValid()) { + d->byteVectorValue.clear(); + } + } + return name; } @@ -252,6 +276,8 @@ ASF::Attribute::dataSize() const case UnicodeType: return d->stringValue.size() * 2 + 2; case BytesType: + if(d->pictureValue.isValid()) + return d->pictureValue.dataSize(); case GuidType: return d->byteVectorValue.size(); } @@ -290,6 +316,10 @@ ASF::Attribute::render(const String &name, int kind) const break; case BytesType: + if(d->pictureValue.isValid()) { + data.append(d->pictureValue.render()); + break; + } case GuidType: data.append(d->byteVectorValue); break; diff --git a/taglib/asf/asfattribute.h b/taglib/asf/asfattribute.h index c30e4e4c..56186999 100644 --- a/taglib/asf/asfattribute.h +++ b/taglib/asf/asfattribute.h @@ -29,6 +29,7 @@ #include "tstring.h" #include "tbytevector.h" #include "taglib_export.h" +#include "asfpicture.h" namespace TagLib { @@ -37,6 +38,7 @@ namespace TagLib { class File; + class Picture; class TAGLIB_EXPORT Attribute { @@ -68,7 +70,20 @@ namespace TagLib /*! * Constructs an attribute with \a key and a BytesType \a value. */ - Attribute(const ByteVector &value); + Attribute(const ByteVector &value); + + /*! + * Constructs an attribute with \a key and a Picture \a value. + * + * This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that, + * while there may be any number of APIC frames associated with a file, + * only one may be of type 1 and only one may be of type 2. + * + * The specification also states that the description of the picture can be no longer than 64 characters, but can be empty. + * WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications. + * You must add code in your application to perform validations if you want to maintain complete compatibility with ID3. + */ + Attribute(const Picture &value); /*! * Constructs an attribute with \a key and a DWordType \a value. @@ -140,6 +155,11 @@ namespace TagLib */ ByteVector toByteVector() const; + /*! + * Returns the Picture \a value. + */ + Picture toPicture() const; + /*! * Returns the language number, or 0 is no stream number was set. */ @@ -176,7 +196,6 @@ namespace TagLib class AttributePrivate; AttributePrivate *d; }; - } } diff --git a/taglib/asf/asffile.cpp b/taglib/asf/asffile.cpp index 30433cd9..c0cab950 100644 --- a/taglib/asf/asffile.cpp +++ b/taglib/asf/asffile.cpp @@ -518,7 +518,7 @@ int ASF::File::readBYTE() int ASF::File::readWORD() { ByteVector v = readBlock(2); - return v.toShort(false); + return v.toUShort(false); } unsigned int ASF::File::readDWORD() diff --git a/taglib/asf/asffile.h b/taglib/asf/asffile.h index ea148323..9242aa68 100644 --- a/taglib/asf/asffile.h +++ b/taglib/asf/asffile.h @@ -97,6 +97,7 @@ namespace TagLib { void read(bool readProperties, Properties::ReadStyle propertiesStyle); friend class Attribute; + friend class Picture; class BaseObject; class UnknownObject; diff --git a/taglib/asf/asfpicture.cpp b/taglib/asf/asfpicture.cpp new file mode 100644 index 00000000..ecf658c0 --- /dev/null +++ b/taglib/asf/asfpicture.cpp @@ -0,0 +1,185 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WITH_ASF + +#include +#include +#include "asfattribute.h" +#include "asffile.h" +#include "asfpicture.h" + +using namespace TagLib; + +class ASF::Picture::PicturePriavte : public RefCounter +{ +public: + bool valid; + Type type; + String mimeType; + String description; + ByteVector picture; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Picture class members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Picture::Picture() +{ + d = new PicturePriavte(); + d->valid = true; +} + +ASF::Picture::Picture(const Picture& other) + : d(other.d) +{ + d->ref(); +} + +ASF::Picture::~Picture() +{ + if(d->deref()) + delete d; +} + +bool ASF::Picture::isValid() const +{ + return d->valid; +} + +String ASF::Picture::mimeType() const +{ + return d->mimeType; +} + +void ASF::Picture::setMimeType(const String &value) +{ + d->mimeType = value; +} + +ASF::Picture::Type ASF::Picture::type() const +{ + return d->type; +} + +void ASF::Picture::setType(const ASF::Picture::Type& t) +{ + d->type = t; +} + +String ASF::Picture::description() const +{ + return d->description; +} + +void ASF::Picture::setDescription(const String &desc) +{ + d->description = desc; +} + +ByteVector ASF::Picture::picture() const +{ + return d->picture; +} + +void ASF::Picture::setPicture(const ByteVector &p) +{ + d->picture = p; +} + +int ASF::Picture::dataSize() const +{ + return + 9 + (d->mimeType.length() + d->description.length()) * 2 + + d->picture.size(); +} + +ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other) +{ + if(other.d != d) { + if(d->deref()) + delete d; + d = other.d; + d->ref(); + } + return *this; +} + +ByteVector ASF::Picture::render() const +{ + if(!isValid()) + return ByteVector::null; + return + ByteVector((char)d->type) + + ByteVector::fromUInt(d->picture.size(), false) + + ASF::File::renderString(d->mimeType) + + ASF::File::renderString(d->description) + + d->picture; +} + +void ASF::Picture::parse(const ByteVector& bytes) +{ + d->valid = false; + if(bytes.size() < 9) + return; + int pos = 0; + d->type = (Type)bytes[0]; ++pos; + uint dataLen = bytes.mid(pos, 4).toUInt(false); pos+=4; + + const ByteVector nullStringTerminator(2, 0); + + int endPos = bytes.find(nullStringTerminator, pos, 2); + if(endPos < 0) + return; + d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE); + pos = endPos+2; + + endPos = bytes.find(nullStringTerminator, pos, 2); + if(endPos < 0) + return; + d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE); + pos = endPos+2; + + if(dataLen + pos != bytes.size()) + return; + + d->picture = bytes.mid(pos, dataLen); + d->valid = true; + return; +} + +ASF::Picture ASF::Picture::fromInvalid() +{ + Picture ret; + ret.d->valid = false; + return ret; +} + +#endif diff --git a/taglib/asf/asfpicture.h b/taglib/asf/asfpicture.h new file mode 100644 index 00000000..d042ac3a --- /dev/null +++ b/taglib/asf/asfpicture.h @@ -0,0 +1,192 @@ +#ifndef ASFPICTURE_H +#define ASFPICTURE_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "attachedpictureframe.h" + +namespace TagLib +{ + namespace ASF + { + + //! An ASF attached picture interface implementation + + /*! + * This is an implementation of ASF attached pictures interface. Pictures may be + * included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture + * attribute in a single tag). These pictures are usually in either JPEG or + * PNG format. + * \see Attribute::toPicture() + * \see Attribute::Attribute(const Picture& picture) + */ + class TAGLIB_EXPORT Picture { + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + /*! + * Constructs an empty picture. + */ + Picture(); + + /*! + * Construct an picture as a copy of \a other. + */ + Picture(const Picture& other); + + /*! + * Destroys the picture. + */ + virtual ~Picture(); + + /*! + * Copies the contents of \a other into this picture. + */ + Picture& operator=(const Picture& other); + + /*! + * Returns true if Picture stores valid picture + */ + bool isValid() const; + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + void setMimeType(const String &value); + + /*! + * Returns the type of the image. + * + * \see Type + * \see setType() + */ + Type type() const; + + /*! + * Sets the type for the image. + * + * \see Type + * \see type() + */ + void setType(const ASF::Picture::Type& t); + + /*! + * Returns a text description of the image. + * + * \see setDescription() + */ + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + * + * \see description() + */ + void setDescription(const String &desc); + + /*! + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ + ByteVector picture() const; + + /*! + * Sets the image data to \a p. \a p should be of the type specified in + * this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ + void setPicture(const ByteVector &p); + + /*! + * Returns picture as binary raw data \a value + */ + ByteVector render() const; + + /*! + * Returns picture as binary raw data \a value + */ + int dataSize() const; + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + void parse(const ByteVector& ); + static Picture fromInvalid(); + friend class Attribute; +#endif + private: + struct PicturePriavte; + PicturePriavte *d; + }; + } +} + +#endif // ASFPICTURE_H diff --git a/taglib/taglib.pro b/taglib/taglib.pro index 0c462954..0124143f 100644 --- a/taglib/taglib.pro +++ b/taglib/taglib.pro @@ -63,6 +63,7 @@ HEADERS += audioproperties.h \ ape/apetag.h \ flac/flacfile.h \ flac/flacproperties.h \ + flac/flacpicture.h \ mpc/mpcfile.h \ mpc/mpcproperties.h \ mp4/mp4atom.h \ @@ -124,10 +125,12 @@ SOURCES += ape/apefooter.cpp \ asf/asffile.cpp \ asf/asfproperties.cpp \ asf/asftag.cpp \ + asf/asfpicture.cpp \ audioproperties.cpp \ fileref.cpp \ flac/flacfile.cpp \ flac/flacproperties.cpp \ + flac/flacpicture.cpp \ mp4/mp4atom.cpp \ mp4/mp4coverart.cpp \ mp4/mp4file.cpp \ @@ -197,6 +200,7 @@ FRAMEWORK_HEADERS.files = \ asf/asffile.h \ asf/asfproperties.h \ asf/asftag.h \ + asf/asfpicture.h \ audioproperties.h \ fileref.h \ flac/flacfile.h \ diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index 7495b9f0..9fb77b12 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -565,6 +565,11 @@ short ByteVector::toShort(bool mostSignificantByteFirst) const return toNumber(d->data, mostSignificantByteFirst); } +unsigned short ByteVector::toUShort(bool mostSignificantByteFirst) const +{ + return toNumber(d->data, mostSignificantByteFirst); +} + long long ByteVector::toLongLong(bool mostSignificantByteFirst) const { return toNumber(d->data, mostSignificantByteFirst); diff --git a/taglib/toolkit/tbytevector.h b/taglib/toolkit/tbytevector.h index 0fdb878e..b7fffdde 100644 --- a/taglib/toolkit/tbytevector.h +++ b/taglib/toolkit/tbytevector.h @@ -266,6 +266,17 @@ namespace TagLib { */ short toShort(bool mostSignificantByteFirst = true) const; + /*! + * Converts the first 2 bytes of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + unsigned short toUShort(bool mostSignificantByteFirst = true) const; + /*! * Converts the first 8 bytes of the vector to a (signed) long long. * diff --git a/tests/test_asf.cpp b/tests/test_asf.cpp index 5094f0f0..d93dcb47 100644 --- a/tests/test_asf.cpp +++ b/tests/test_asf.cpp @@ -20,6 +20,8 @@ class TestASF : public CppUnit::TestFixture CPPUNIT_TEST(testSaveLanguage); CPPUNIT_TEST(testDWordTrackNumber); CPPUNIT_TEST(testSaveLargeValue); + CPPUNIT_TEST(testSavePicture); + CPPUNIT_TEST(testSaveMultiplePictures); CPPUNIT_TEST_SUITE_END(); public: @@ -141,6 +143,78 @@ public: delete f; } + void testSavePicture() + { + ScopedFileCopy copy("silence-1", ".wma"); + string newname = copy.fileName(); + + ASF::File *f = new ASF::File(newname.c_str()); + ASF::AttributeList values; + ASF::Picture picture; + picture.setMimeType("image/jpeg"); + picture.setType(ASF::Picture::FrontCover); + picture.setDescription("description"); + picture.setPicture("data"); + ASF::Attribute attr(picture); + values.append(attr); + f->tag()->attributeListMap()["WM/Picture"] = values; + f->save(); + delete f; + + f = new ASF::File(newname.c_str()); + ASF::AttributeList values2 = f->tag()->attributeListMap()["WM/Picture"]; + CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), values2.size()); + ASF::Attribute attr2 = values2.front(); + ASF::Picture picture2 = attr2.toPicture(); + CPPUNIT_ASSERT(picture2.isValid()); + CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), picture2.mimeType()); + CPPUNIT_ASSERT_EQUAL(ASF::Picture::FrontCover, picture2.type()); + CPPUNIT_ASSERT_EQUAL(String("description"), picture2.description()); + CPPUNIT_ASSERT_EQUAL(ByteVector("data"), picture2.picture()); + delete f; + } + + void testSaveMultiplePictures() + { + ScopedFileCopy copy("silence-1", ".wma"); + string newname = copy.fileName(); + + ASF::File *f = new ASF::File(newname.c_str()); + ASF::AttributeList values; + ASF::Picture picture; + picture.setMimeType("image/jpeg"); + picture.setType(ASF::Picture::FrontCover); + picture.setDescription("description"); + picture.setPicture("data"); + values.append(ASF::Attribute(picture)); + ASF::Picture picture2; + picture2.setMimeType("image/png"); + picture2.setType(ASF::Picture::BackCover); + picture2.setDescription("back cover"); + picture2.setPicture("PNG data"); + values.append(ASF::Attribute(picture2)); + f->tag()->attributeListMap()["WM/Picture"] = values; + f->save(); + delete f; + + f = new ASF::File(newname.c_str()); + ASF::AttributeList values2 = f->tag()->attributeListMap()["WM/Picture"]; + CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), values2.size()); + ASF::Picture picture3 = values2[1].toPicture(); + CPPUNIT_ASSERT(picture3.isValid()); + CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), picture3.mimeType()); + CPPUNIT_ASSERT_EQUAL(ASF::Picture::FrontCover, picture3.type()); + CPPUNIT_ASSERT_EQUAL(String("description"), picture3.description()); + CPPUNIT_ASSERT_EQUAL(ByteVector("data"), picture3.picture()); + ASF::Picture picture4 = values2[0].toPicture(); + CPPUNIT_ASSERT(picture4.isValid()); + CPPUNIT_ASSERT_EQUAL(String("image/png"), picture4.mimeType()); + CPPUNIT_ASSERT_EQUAL(ASF::Picture::BackCover, picture4.type()); + CPPUNIT_ASSERT_EQUAL(String("back cover"), picture4.description()); + CPPUNIT_ASSERT_EQUAL(ByteVector("PNG data"), picture4.picture()); + delete f; + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestASF); diff --git a/tests/test_bytevector.cpp b/tests/test_bytevector.cpp index 6b4dae3c..2b1f981f 100644 --- a/tests/test_bytevector.cpp +++ b/tests/test_bytevector.cpp @@ -38,6 +38,7 @@ class TestByteVector : public CppUnit::TestFixture CPPUNIT_TEST(testRfind1); CPPUNIT_TEST(testRfind2); CPPUNIT_TEST(testToHex); + CPPUNIT_TEST(testToUShort); CPPUNIT_TEST_SUITE_END(); public: @@ -181,6 +182,15 @@ public: CPPUNIT_ASSERT_EQUAL(ByteVector("f0e1d2c3b4a5968778695a4b3c2d1e0f"), v.toHex()); } + void testToUShort() + { + CPPUNIT_ASSERT_EQUAL((unsigned short)0xFFFF, ByteVector("\xff\xff", 2).toUShort()); + CPPUNIT_ASSERT_EQUAL((unsigned short)0x0001, ByteVector("\x00\x01", 2).toUShort()); + CPPUNIT_ASSERT_EQUAL((unsigned short)0x0100, ByteVector("\x00\x01", 2).toUShort(false)); + CPPUNIT_ASSERT_EQUAL((unsigned short)0xFF01, ByteVector("\xFF\x01", 2).toUShort()); + CPPUNIT_ASSERT_EQUAL((unsigned short)0x01FF, ByteVector("\xFF\x01", 2).toUShort(false)); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVector);