Merge branch 'master' into merge-master-to-taglib2

Conflicts:
	taglib/riff/wav/infotag.cpp
	taglib/toolkit/trefcounter.h
	taglib/toolkit/tstring.cpp
	taglib/toolkit/tstring.h
	taglib/xm/xmfile.cpp
	tests/test_string.cpp
This commit is contained in:
Tsuda Kageyu 2014-02-18 17:32:05 +09:00
commit bd84c8928a
9 changed files with 247 additions and 222 deletions

View File

@ -5,7 +5,7 @@ TagLib uses the CMake build system. As a user, you will most likely want to
build TagLib in release mode and install it into a system-wide location.
This can be done using the following commands:
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_RELEASE_TYPE=Release .
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release .
make
sudo make install

View File

@ -61,7 +61,7 @@ install(TARGETS tag_c
PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/taglib
)
if(NOT WIN32 AND NOT BUILD_FRAMEWORK)
if(NOT BUILD_FRAMEWORK)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/taglib_c.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif()

View File

@ -1,36 +1,36 @@
@echo off
goto beginning
*
* It is what it is, you can do with it as you please.
*
* Just don't blame me if it teaches your computer to smoke!
*
* -Enjoy
* fh :)_~
*
:beginning
if /i "%1#" == "--libs#" goto doit
if /i "%1#" == "--cflags#" goto doit
if /i "%1#" == "--version#" goto doit
if /i "%1#" == "--prefix#" goto doit
echo "usage: %0 [OPTIONS]"
echo [--libs]
echo [--cflags]
echo [--version]
echo [--prefix]
goto theend
*
* NOTE: Windows does not assume libraries are prefixed with 'lib'.
* NOTE: If '-llibtag' is the last element, it is easily appended in the users installation/makefile process
* to allow for static, shared or debug builds.
* It would be preferable if the top level CMakeLists.txt provided the library name during config. ??
:doit
if /i "%1#" == "--libs#" echo -L${LIB_INSTALL_DIR} -llibtag
if /i "%1#" == "--cflags#" echo -I${INCLUDE_INSTALL_DIR}/taglib
if /i "%1#" == "--version#" echo ${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}
if /i "%1#" == "--prefix#" echo ${CMAKE_INSTALL_PREFIX}
:theend
@echo off
goto beginning
*
* It is what it is, you can do with it as you please.
*
* Just don't blame me if it teaches your computer to smoke!
*
* -Enjoy
* fh :)_~
*
:beginning
if /i "%1#" == "--libs#" goto doit
if /i "%1#" == "--cflags#" goto doit
if /i "%1#" == "--version#" goto doit
if /i "%1#" == "--prefix#" goto doit
echo "usage: %0 [OPTIONS]"
echo [--libs]
echo [--cflags]
echo [--version]
echo [--prefix]
goto theend
*
* NOTE: Windows does not assume libraries are prefixed with 'lib'.
* NOTE: If '-llibtag' is the last element, it is easily appended in the users installation/makefile process
* to allow for static, shared or debug builds.
* It would be preferable if the top level CMakeLists.txt provided the library name during config. ??
:doit
if /i "%1#" == "--libs#" echo -L${LIB_INSTALL_DIR} -llibtag
if /i "%1#" == "--cflags#" echo -I${INCLUDE_INSTALL_DIR}/taglib
if /i "%1#" == "--version#" echo ${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}
if /i "%1#" == "--prefix#" echo ${CMAKE_INSTALL_PREFIX}
:theend

View File

@ -234,7 +234,7 @@ namespace TagLib {
* This description identifies the frame and must be unique.
*/
//! An ID3v2 custom text identification frame implementationx
//! An ID3v2 custom text identification frame implementation
class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame
{

View File

@ -35,7 +35,7 @@ using namespace RIFF::Info;
class RIFF::Info::Tag::TagPrivate
{
public:
TagPrivate()
TagPrivate()
{}
FieldListMap fieldListMap;
@ -72,14 +72,14 @@ ByteVector RIFF::Info::StringHandler::render(const String &s) const
// public members
////////////////////////////////////////////////////////////////////////////////
RIFF::Info::Tag::Tag(const ByteVector &data)
RIFF::Info::Tag::Tag(const ByteVector &data)
: TagLib::Tag()
, d(new TagPrivate())
{
parse(data);
}
RIFF::Info::Tag::Tag()
RIFF::Info::Tag::Tag()
: TagLib::Tag()
, d(new TagPrivate())
{
@ -215,7 +215,7 @@ ByteVector RIFF::Info::Tag::render() const
data.append(it->first);
data.append(ByteVector::fromUInt32LE(text.size() + 1));
data.append(text);
do {
data.append('\0');
} while(data.size() & 1);

View File

@ -141,13 +141,13 @@ namespace
debug("String::copyFromUTF8() - Unicode conversion error.");
}
#endif
#endif
}
}
namespace TagLib {
class String::StringPrivate
class String::StringPrivate
{
public:
StringPrivate()
@ -155,13 +155,13 @@ public:
{
}
StringPrivate(size_t n, wchar_t c)
: data(new std::wstring(n, c))
StringPrivate(size_t n, wchar_t c)
: data(new std::wstring(n, c))
{
}
/*!
* Stores string in UTF-16. The byte order depends on the CPU endian.
* Stores string in UTF-16. The byte order depends on the CPU endian.
*/
SHARED_PTR<std::wstring> data;
@ -178,12 +178,12 @@ const size_t String::npos = std::wstring::npos;
////////////////////////////////////////////////////////////////////////////////
String::String()
String::String()
: d(new StringPrivate())
{
}
String::String(const String &s)
String::String(const String &s)
: d(new StringPrivate(*s.d))
{
}
@ -192,9 +192,9 @@ String::String(const std::string &s, Type t)
: d(new StringPrivate())
{
if(t == Latin1)
copyFromLatin1(&s[0], s.length());
copyFromLatin1(s.c_str(), s.length());
else if(t == String::UTF8)
copyFromUTF8(&s[0], s.length());
copyFromUTF8(s.c_str(), s.length());
else {
debug("String::String() -- A std::string should not contain UTF16.");
}
@ -256,11 +256,11 @@ String::String(const ByteVector &v, Type t)
if(v.isEmpty())
return;
if(t == Latin1)
if(t == Latin1)
copyFromLatin1(v.data(), v.size());
else if(t == UTF8)
else if(t == UTF8)
copyFromUTF8(v.data(), v.size());
else
else
copyFromUTF16(v.data(), v.size(), t);
// If we hit a null in the ByteVector, shrink the string again.
@ -276,25 +276,8 @@ String::~String()
std::string String::to8Bit(bool unicode) const
{
std::string s;
if(!unicode) {
s.resize(d->data->size());
std::string::iterator targetIt = s.begin();
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*targetIt = static_cast<char>(*it);
++targetIt;
}
}
else {
s.resize(d->data->size() * 4 + 1);
UTF16toUTF8(&(*d->data)[0], d->data->size(), &s[0], s.size());
s.resize(::strlen(s.c_str()));
}
return s;
const ByteVector v = data(unicode ? UTF8 : Latin1);
return std::string(v.data(), v.size());
}
const std::wstring &String::toWString() const
@ -418,74 +401,78 @@ bool String::isNull() const
ByteVector String::data(Type t) const
{
switch(t)
switch(t)
{
case Latin1:
{
ByteVector v(size(), 0);
char *p = v.data();
{
ByteVector v(size(), 0);
char *p = v.data();
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++)
*p++ = static_cast<char>(*it);
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++)
*p++ = static_cast<char>(*it);
return v;
}
return v;
}
case UTF8:
{
ByteVector v(size() * 4 + 1, 0);
if(!d->data->empty())
{
ByteVector v(size() * 4 + 1, 0);
UTF16toUTF8(&(*d->data)[0], d->data->size(), v.data(), v.size());
v.resize(::strlen(v.data()));
UTF16toUTF8(d->data->c_str(), d->data->size(), v.data(), v.size());
v.resize(::strlen(v.data()));
return v;
}
return v;
}
else {
return ByteVector::null;
}
case UTF16:
{
ByteVector v(2 + size() * 2, 0);
char *p = v.data();
{
ByteVector v(2 + size() * 2, 0);
char *p = v.data();
// Assume that if we're doing UTF16 and not UTF16BE that we want little
// endian encoding. (Byte Order Mark)
// Assume that if we're doing UTF16 and not UTF16BE that we want little
// endian encoding. (Byte Order Mark)
*p++ = '\xff';
*p++ = '\xfe';
*p++ = '\xff';
*p++ = '\xfe';
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
}
return v;
}
return v;
}
case UTF16BE:
{
ByteVector v(size() * 2, 0);
char *p = v.data();
{
ByteVector v(size() * 2, 0);
char *p = v.data();
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it >> 8);
*p++ = static_cast<char>(*it & 0xff);
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it >> 8);
*p++ = static_cast<char>(*it & 0xff);
}
return v;
}
return v;
}
case UTF16LE:
{
ByteVector v(size() * 2, 0);
char *p = v.data();
{
ByteVector v(size() * 2, 0);
char *p = v.data();
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
for(std::wstring::const_iterator it = d->data->begin(); it != d->data->end(); it++) {
*p++ = static_cast<char>(*it & 0xff);
*p++ = static_cast<char>(*it >> 8);
}
return v;
}
return v;
}
default:
{
debug("String::data() - Invalid Type value.");
return ByteVector();
}
{
debug("String::data() - Invalid Type value.");
return ByteVector::null;
}
}
}
@ -717,17 +704,19 @@ void String::copyFromUTF8(const char *s, size_t length)
{
d->data->resize(length);
UTF8toUTF16(s, length, &(*d->data)[0], d->data->size());
d->data->resize(::wcslen(d->data->c_str()));
if(length > 0) {
UTF8toUTF16(s, length, &(*d->data)[0], d->data->size());
d->data->resize(::wcslen(d->data->c_str()));
}
}
void String::copyFromUTF16(const wchar_t *s, size_t length, Type t)
{
bool swap;
if(t == UTF16) {
if(length >= 1 && s[0] == 0xfeff)
if(length >= 1 && s[0] == 0xfeff)
swap = false; // Same as CPU endian. No need to swap bytes.
else if(length >= 1 && s[0] == 0xfffe)
else if(length >= 1 && s[0] == 0xfffe)
swap = true; // Not same as CPU endian. Need to swap bytes.
else {
debug("String::copyFromUTF16() - Invalid UTF16 string.");
@ -737,15 +726,18 @@ void String::copyFromUTF16(const wchar_t *s, size_t length, Type t)
s++;
length--;
}
else
else
swap = (t != WCharByteOrder);
d->data->resize(length);
memcpy(&(*d->data)[0], s, length * sizeof(wchar_t));
if(swap) {
for(size_t i = 0; i < length; ++i)
(*d->data)[i] = Utils::byteSwap(static_cast<ushort>(s[i]));
if(length > 0) {
if(swap) {
for(size_t i = 0; i < length; ++i)
(*d->data)[i] = Utils::byteSwap(static_cast<ushort>(s[i]));
}
else {
::memcpy(&(*d->data)[0], s, length * sizeof(wchar_t));
}
}
}
@ -762,9 +754,9 @@ void String::copyFromUTF16(const char *s, size_t length, Type t)
ushort bom;
::memcpy(&bom, s, 2);
if(bom == 0xfeff)
if(bom == 0xfeff)
swap = false; // Same as CPU endian. No need to swap bytes.
else if(bom == 0xfffe)
else if(bom == 0xfffe)
swap = true; // Not same as CPU endian. Need to swap bytes.
else {
debug("String::copyFromUTF16() - Invalid UTF16 string.");
@ -774,7 +766,7 @@ void String::copyFromUTF16(const char *s, size_t length, Type t)
s += 2;
length -= 2;
}
else
else
swap = (t != WCharByteOrder);
d->data->resize(length / 2);
@ -784,7 +776,7 @@ void String::copyFromUTF16(const char *s, size_t length, Type t)
}
}
const String::Type String::WCharByteOrder
const String::Type String::WCharByteOrder
= (Utils::SystemByteOrder == BigEndian) ? String::UTF16BE : String::UTF16LE;
////////////////////////////////////////////////////////////////////////////////

View File

@ -94,7 +94,7 @@ namespace TagLib {
*/
UTF16 = 1,
/*!
* UTF16 <i>big endian</i>. 16 bit characters.
* UTF16 <i>big endian</i>. 16 bit characters.
*/
UTF16BE = 2,
/*!
@ -130,20 +130,20 @@ namespace TagLib {
/*!
* Makes a deep copy of the data in \a s.
*
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or
* UTF16LE, when used with other codecs it will simply print a warning and
* exit. UTF16BE or UTF16LE is automatically chosen as default according
* to the CPU byte order
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or
* UTF16LE, when used with other codecs it will simply print a warning and
* exit. UTF16BE or UTF16LE is automatically chosen as default according
* to the CPU byte order
*/
String(const std::wstring &s, Type t = WCharByteOrder);
/*!
* Makes a deep copy of the data in \a s.
*
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or
* UTF16LE, when used with other codecs it will simply print a warning and
* exit. UTF16BE or UTF16LE is automatically chosen as default according
* to the CPU byte order
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or
* UTF16LE, when used with other codecs it will simply print a warning and
* exit. UTF16BE or UTF16LE is automatically chosen as default according
* to the CPU byte order
*/
String(const wchar_t *s, Type t = WCharByteOrder);
@ -158,10 +158,10 @@ namespace TagLib {
/*!
* Makes a deep copy of the data in \a c.
*
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or
* UTF16LE, when used with other codecs it will simply print a warning and
* exit. UTF16BE or UTF16LE is automatically chosen as default according
* to the CPU byte order
* \note This should only be used with the 16-bit codecs UTF16, UTF16BE or
* UTF16LE, when used with other codecs it will simply print a warning and
* exit. UTF16BE or UTF16LE is automatically chosen as default according
* to the CPU byte order
*/
String(wchar_t c, Type t = WCharByteOrder);
@ -185,7 +185,7 @@ namespace TagLib {
virtual ~String();
/*!
* Returns a deep copy of this String as an std::string. The returned string
* Returns a deep copy of this String as an std::string. The returned string
* is encoded in UTF8 if \a unicode is true, otherwise Latin1.
*
* \see toCString()
@ -193,7 +193,7 @@ namespace TagLib {
std::string to8Bit(bool unicode = false) const;
/*!
* Returns a deep copy of this String as a wstring. The returned string is
* Returns a deep copy of this String as a wstring. The returned string is
* encoded in UTF-16 (without BOM/CPU byte order).
*
* \see toCWString()
@ -201,43 +201,43 @@ namespace TagLib {
const std::wstring &toWString() const;
/*!
* Creates and returns a standard C-style (null-terminated) version of this
* String. The returned string is encoded in UTF8 if \a unicode is true,
* Creates and returns a standard C-style (null-terminated) version of this
* String. The returned string is encoded in UTF8 if \a unicode is true,
* otherwise Latin1.
*
* The returned string is still owned by this String and should not be deleted
*
* The returned string is still owned by this String and should not be deleted
* by the user.
*
* The returned pointer remains valid until this String instance is destroyed
* The returned pointer remains valid until this String instance is destroyed
* or toCString() is called again.
*
* \warning This however has the side effect that the returned string will remain
* in memory <b>in addition to</b> other memory that is consumed by this
* in memory <b>in addition to</b> other memory that is consumed by this
* String instance. So, this method should not be used on large strings or
* where memory is critical. Consider using to8Bit() instead to avoid it.
*
* \see to8Bit()
*/
const char *toCString(bool unicode = false) const;
/*!
* Returns a standard C-style (null-terminated) wide character version of
* this String. The returned string is encoded in UTF-16 (without BOM/CPU byte
* Returns a standard C-style (null-terminated) wide character version of
* this String. The returned string is encoded in UTF-16 (without BOM/CPU byte
* order).
*
* The returned string is still owned by this String and should not be deleted
*
* The returned string is still owned by this String and should not be deleted
* by the user.
*
* The returned pointer remains valid until this String instance is destroyed
* The returned pointer remains valid until this String instance is destroyed
* or any other method of this String is called.
*
* \note This returns a pointer to the String's internal data without any
* \note This returns a pointer to the String's internal data without any
* conversions.
*
* \see toWString()
*/
const wchar_t *toCWString() const;
/*!
* Returns an iterator pointing to the beginning of the string.
*/
@ -332,6 +332,8 @@ namespace TagLib {
* Returns a ByteVector containing the string's data. If \a t is Latin1 or
* UTF8, this will return a vector of 8 bit characters, otherwise it will use
* 16 bit characters.
*
* \note The returned data is not null terminated.
*/
ByteVector data(Type t) const;
@ -477,7 +479,7 @@ namespace TagLib {
static const String null;
/*!
* When used as the value for a \a length parameter in String's member
* When used as the value for a \a length parameter in String's member
* functions, means "until the end of the string".
* As a return value, it is usually used to indicate no matches.
*/
@ -493,31 +495,31 @@ namespace TagLib {
private:
/*!
* Converts a \e Latin-1 string into \e UTF-16(without BOM/CPU byte order)
* Converts a \e Latin-1 string into \e UTF-16(without BOM/CPU byte order)
* and copies it to the internal buffer.
*/
void copyFromLatin1(const char *s, size_t length);
/*!
* Converts a \e UTF-8 string into \e UTF-16(without BOM/CPU byte order)
* Converts a \e UTF-8 string into \e UTF-16(without BOM/CPU byte order)
* and copies it to the internal buffer.
*/
void copyFromUTF8(const char *s, size_t length);
/*!
* Converts a \e UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
* Converts a \e UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
* \e UTF-16(without BOM/CPU byte order) and copies it to the internal buffer.
*/
void copyFromUTF16(const wchar_t *s, size_t length, Type t);
/*!
* Converts a \e UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
* Converts a \e UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
* \e UTF-16(without BOM/CPU byte order) and copies it to the internal buffer.
*/
void copyFromUTF16(const char *s, size_t length, Type t);
/*!
* Indicates which byte order of UTF-16 is used to store strings internally.
* Indicates which byte order of UTF-16 is used to store strings internally.
*
* \note \e String::UTF16BE or \e String::UTF16LE
*/

View File

@ -406,97 +406,90 @@ bool XM::File::save()
debug("XM::File::save() - Cannot save to a read only file.");
return false;
}
seek(17);
writeString(d->tag.title(), 20);
seek(1, Current);
seek(38);
writeString(d->tag.trackerName(), 20);
seek(2, Current);
seek(60);
uint headerSize = 0;
if(!readU32L(headerSize))
return false;
seek(2+2+2, Current);
seek(70);
ushort patternCount = 0;
ushort instrumentCount = 0;
if(!readU16L(patternCount) || !readU16L(instrumentCount))
return false;
seek(60 + headerSize);
long pos = 60 + headerSize; // should be offset_t in taglib2.
// need to read patterns again in order to seek to the instruments:
for(ushort i = 0; i < patternCount; ++ i) {
seek(pos);
uint patternHeaderLength = 0;
if(!readU32L(patternHeaderLength) || patternHeaderLength < 4)
return false;
seek(pos + 7);
ushort dataSize = 0;
StructReader pattern;
pattern.skip(3).u16L(dataSize);
uint count = pattern.read(*this, patternHeaderLength - 4U);
if(count != std::min(patternHeaderLength - 4U, pattern.size()))
if (!readU16L(dataSize))
return false;
seek(patternHeaderLength - (4 + count) + dataSize, Current);
pos += patternHeaderLength + dataSize;
}
StringList lines = d->tag.comment().split("\n");
const StringList lines = d->tag.comment().split("\n");
uint sampleNameIndex = instrumentCount;
for(ushort i = 0; i < instrumentCount; ++ i) {
seek(pos);
uint instrumentHeaderSize = 0;
if(!readU32L(instrumentHeaderSize) || instrumentHeaderSize < 4)
return false;
uint len = std::min(22U, instrumentHeaderSize - 4U);
seek(pos + 4);
const uint len = std::min(22U, instrumentHeaderSize - 4U);
if(i >= lines.size())
writeString(String::null, len);
else
writeString(lines[i], len);
long offset = 0;
ushort sampleCount = 0;
if(instrumentHeaderSize >= 29U) {
ushort sampleCount = 0;
seek(1, Current);
seek(pos + 27);
if(!readU16L(sampleCount))
return false;
}
if(sampleCount > 0) {
uint sampleHeaderSize = 0;
if(instrumentHeaderSize < 33U || !readU32L(sampleHeaderSize))
uint sampleHeaderSize = 0;
if(sampleCount > 0) {
seek(pos + 29);
if(instrumentHeaderSize < 33U || !readU32L(sampleHeaderSize))
return false;
}
pos += instrumentHeaderSize;
for(ushort j = 0; j < sampleCount; ++ j) {
if(sampleHeaderSize > 4U) {
seek(pos);
uint sampleLength = 0;
if(!readU32L(sampleLength))
return false;
// skip unhandeled header proportion:
seek(instrumentHeaderSize - 33, Current);
for(ushort j = 0; j < sampleCount; ++ j) {
if(sampleHeaderSize > 4U) {
uint sampleLength = 0;
if(!readU32L(sampleLength))
return false;
offset += sampleLength;
seek(std::min(sampleHeaderSize, 14U), Current);
if(sampleHeaderSize > 18U) {
uint len = std::min(sampleHeaderSize - 18U, 22U);
if(sampleNameIndex >= lines.size())
writeString(String::null, len);
else
writeString(lines[sampleNameIndex ++], len);
seek(sampleHeaderSize - (18U + len), Current);
}
}
else {
seek(sampleHeaderSize, Current);
}
if(sampleHeaderSize > 18U) {
seek(pos + 18);
const uint len = std::min(sampleHeaderSize - 18U, 22U);
if(sampleNameIndex >= lines.size())
writeString(String::null, len);
else
writeString(lines[sampleNameIndex ++], len);
}
}
else {
offset = instrumentHeaderSize - 29;
}
pos += sampleHeaderSize;
}
else {
offset = instrumentHeaderSize - (4 + len);
}
seek(offset, Current);
}
return true;

View File

@ -45,6 +45,7 @@ class TestString : public CppUnit::TestFixture
CPPUNIT_TEST(testSubstr);
CPPUNIT_TEST(testNewline);
CPPUNIT_TEST(testUpper);
CPPUNIT_TEST(testEncode);
CPPUNIT_TEST_SUITE_END();
public:
@ -200,10 +201,10 @@ public:
String a("abc");
String b = a;
String c = a;
b += 'd';
c += L'd';
CPPUNIT_ASSERT_EQUAL(String("abc"), a);
CPPUNIT_ASSERT_EQUAL(String("abcd"), b);
CPPUNIT_ASSERT_EQUAL(String("abcd"), c);
@ -277,7 +278,7 @@ public:
CPPUNIT_ASSERT_EQUAL(L'\x0d', String(crlf)[3]);
CPPUNIT_ASSERT_EQUAL(L'\x0a', String(crlf)[4]);
}
void testUpper()
{
String s1 = "tagLIB 012 strING";
@ -286,6 +287,43 @@ public:
CPPUNIT_ASSERT_EQUAL(String("TAGLIB 012 STRING"), s2);
}
void testEncode()
{
String jpn(L"\u65E5\u672C\u8A9E");
ByteVector jpn1 = jpn.data(String::Latin1);
ByteVector jpn2 = jpn.data(String::UTF8);
ByteVector jpn3 = jpn.data(String::UTF16);
ByteVector jpn4 = jpn.data(String::UTF16LE);
ByteVector jpn5 = jpn.data(String::UTF16BE);
std::string jpn6 = jpn.to8Bit(false);
std::string jpn7 = jpn.to8Bit(true);
CPPUNIT_ASSERT_EQUAL(ByteVector("\xE5\x2C\x9E"), jpn1);
CPPUNIT_ASSERT_EQUAL(ByteVector("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"), jpn2);
CPPUNIT_ASSERT_EQUAL(ByteVector("\xFF\xFE\xE5\x65\x2C\x67\x9E\x8A"), jpn3);
CPPUNIT_ASSERT_EQUAL(ByteVector("\xE5\x65\x2C\x67\x9E\x8A"), jpn4);
CPPUNIT_ASSERT_EQUAL(ByteVector("\x65\xE5\x67\x2C\x8A\x9E"), jpn5);
CPPUNIT_ASSERT_EQUAL(std::string("\xE5\x2C\x9E"), jpn6);
CPPUNIT_ASSERT_EQUAL(std::string("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"), jpn7);
String empty;
ByteVector empty1 = empty.data(String::Latin1);
ByteVector empty2 = empty.data(String::UTF8);
ByteVector empty3 = empty.data(String::UTF16);
ByteVector empty4 = empty.data(String::UTF16LE);
ByteVector empty5 = empty.data(String::UTF16BE);
std::string empty6 = empty.to8Bit(false);
std::string empty7 = empty.to8Bit(true);
CPPUNIT_ASSERT(empty1.isEmpty());
CPPUNIT_ASSERT(empty2.isEmpty());
CPPUNIT_ASSERT_EQUAL(ByteVector("\xFF\xFE"), empty3);
CPPUNIT_ASSERT(empty4.isEmpty());
CPPUNIT_ASSERT(empty5.isEmpty());
CPPUNIT_ASSERT(empty6.empty());
CPPUNIT_ASSERT(empty7.empty());
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestString);