mirror of
https://github.com/taglib/taglib.git
synced 2025-07-20 22:14:22 -04:00
Merge branch 'taglib2' of github.com:taglib/taglib into dsf
This commit is contained in:
8
CMakeLists.txt
Executable file → Normal file
8
CMakeLists.txt
Executable file → Normal file
@ -47,8 +47,8 @@ if (MSVC AND ENABLE_STATIC_RUNTIME)
|
||||
endif()
|
||||
|
||||
set(TAGLIB_LIB_MAJOR_VERSION "1")
|
||||
set(TAGLIB_LIB_MINOR_VERSION "8")
|
||||
set(TAGLIB_LIB_PATCH_VERSION "0")
|
||||
set(TAGLIB_LIB_MINOR_VERSION "9")
|
||||
set(TAGLIB_LIB_PATCH_VERSION "1")
|
||||
|
||||
set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}")
|
||||
|
||||
@ -56,9 +56,9 @@ set(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VE
|
||||
# 2. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
|
||||
# 3. If any interfaces have been added since the last public release, then increment age.
|
||||
# 4. If any interfaces have been removed since the last public release, then set age to 0.
|
||||
set(TAGLIB_SOVERSION_CURRENT 13)
|
||||
set(TAGLIB_SOVERSION_CURRENT 15)
|
||||
set(TAGLIB_SOVERSION_REVISION 0)
|
||||
set(TAGLIB_SOVERSION_AGE 12)
|
||||
set(TAGLIB_SOVERSION_AGE 14)
|
||||
|
||||
math(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}")
|
||||
math(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}")
|
||||
|
0
ConfigureChecks.cmake
Executable file → Normal file
0
ConfigureChecks.cmake
Executable file → Normal file
97
INSTALL
97
INSTALL
@ -46,15 +46,102 @@ the include folder to the project's User Header Search Paths.
|
||||
Windows
|
||||
-------
|
||||
|
||||
For building a static library on Windows with Visual Studio 2010, cd to
|
||||
the TagLib folder then:
|
||||
It's Windows ... Systems vary!
|
||||
This means you need to adjust things to suit your system, especially paths.
|
||||
|
||||
cmake -DENABLE_STATIC=ON -DENABLE_STATIC_RUNTIME=ON -G "Visual Studio 10" ...
|
||||
Tested with:
|
||||
Microsoft Visual Studio 2010
|
||||
Gcc by mingw-w64.sf.net v4.6.3 (Strawberry Perl 32b)
|
||||
MinGW32-4.8.0
|
||||
|
||||
Requirements:
|
||||
1. Tool chain, Build Environment, Whatever ya want to call it ...
|
||||
Installed and working.
|
||||
2. CMake program. (Available at: www.cmake.org)
|
||||
Installed and working.
|
||||
|
||||
Optional:
|
||||
1. Zlib library.
|
||||
Available in some Tool Chains, Not all.
|
||||
Search the web, Take your choice.
|
||||
|
||||
Useful configuration options used with CMake (GUI and/or Command line):
|
||||
Any of the ZLIB_ variables may be used at the command line, ZLIB_ROOT is only
|
||||
available on the Command line.
|
||||
ZLIB_ROOT= Where to find ZLib's root directory.
|
||||
Assumes parent of: \include and \lib.
|
||||
ZLIB_INCLUDE_DIR= Where to find ZLib's Include directory.
|
||||
ZLIB_LIBRARY= Where to find ZLib's Library.
|
||||
CMAKE_INSTALL_PREFIX= Where to install Taglib.
|
||||
CMAKE_BUILD_TYPE= Release, Debug, etc ... (Not available in MSVC)
|
||||
|
||||
The easiest way is at the Command Prompt.
|
||||
MSVS Command Prompt for MSVS Users.
|
||||
(Batch file and/or Shortcuts are your friends)
|
||||
|
||||
1. Build the Makefiles:
|
||||
Replace "GENERATOR" with your needs.
|
||||
For MSVS : "Visual Studio X" where X is the single or two digit version.
|
||||
For MinGW: "MinGW Makefiles"
|
||||
|
||||
C:\GitRoot\taglib> cmake -G "GENERATOR" -DCMAKE_INSTALL_PREFIX=C:\Libraries\taglib
|
||||
|
||||
Or use the CMake GUI:
|
||||
1. Open CMake GUI.
|
||||
2. Set Paths.
|
||||
"Where is the source code" and "Where to build the binaries"
|
||||
Example, Both would be: C:\GitRoot\taglib
|
||||
3. Tick: Advanced
|
||||
4. Select: Configure
|
||||
5. Select: Generator
|
||||
6. Tick: Use default native compilers
|
||||
7. Select: Finish
|
||||
Wait until done.
|
||||
5. If using ZLib, Scroll down.
|
||||
(to the bottom of the list of options ... should go over them all)
|
||||
1. Edit: ZLIB_INCLUDE_DIR
|
||||
2. Edit: ZLIB_LIBRARY
|
||||
6. Select: Generate
|
||||
|
||||
2. Build the project:
|
||||
MSVS:
|
||||
C:\GitRoot\taglib> msbuild all_build.vcxproj /p:Configuration=Release
|
||||
OR (Depending on MSVS version or personal choice)
|
||||
C:\GitRoot\taglib> devenv all_build.vcxproj /build Release
|
||||
MinGW:
|
||||
C:\GitRoot\taglib> gmake
|
||||
OR (Depending on MinGW install)
|
||||
C:\GitRoot\taglib> mingw32-make
|
||||
|
||||
Or in the MSVS GUI:
|
||||
1. Open MSVS.
|
||||
2. Open taglib solution.
|
||||
3. Set build type to: Release (look in the tool bars)
|
||||
2. Hit F7 to build the solution. (project)
|
||||
|
||||
3. Install the project:
|
||||
(Change 'install' to 'uninstall' to uninstall the project)
|
||||
MSVS:
|
||||
C:\GitRoot\taglib> msbuild install.vcxproj
|
||||
OR (Depending on MSVC version or personal choice)
|
||||
C:\GitRoot\taglib> devenv install.vcxproj
|
||||
MinGW:
|
||||
C:\GitRoot\taglib> gmake install
|
||||
OR (Depending on MinGW install)
|
||||
C:\GitRoot\taglib> mingw32-make install
|
||||
|
||||
Or in the MSVS GUI:
|
||||
1. Open project.
|
||||
2. Open Solution Explorer.
|
||||
3. Right Click: INSTALL
|
||||
4. Select: Project Only
|
||||
5. Select: Build Only INSTALL
|
||||
|
||||
To build a static library enable the following two options with CMake.
|
||||
-DENABLE_STATIC=ON -DENABLE_STATIC_RUNTIME=ON
|
||||
|
||||
Including ENABLE_STATIC_RUNTIME=ON indicates you want TagLib built using the
|
||||
static runtime library, rather than the DLL form of the runtime.
|
||||
CMake will create a Visual Studio solution, taglib.sln that you can open and
|
||||
build as normal.
|
||||
|
||||
Unit Tests
|
||||
----------
|
||||
|
19
NEWS
19
NEWS
@ -1,16 +1,33 @@
|
||||
TagLib 1.9 (In Development)
|
||||
TagLib 1.9.1 (Oct 8, 2013)
|
||||
==========================
|
||||
|
||||
* Fixed binary incompatible change in TagLib::Map and TagLib::List.
|
||||
* Fixed constructing String from ByteVector.
|
||||
* Fixed compilation on MSVC with the /Zc:wchar_t- option.
|
||||
* Fixed detecting of RIFF files with invalid chunk sizes.
|
||||
* Added TagLib::MP4::PropertyMap::codec().
|
||||
|
||||
TagLib 1.9 (Oct 6, 2013)
|
||||
========================
|
||||
|
||||
* Added support for the Ogg Opus file format.
|
||||
* Added support for INFO tags in WAV files.
|
||||
* Changed FileStream to use Windows file API.
|
||||
* Included taglib-config.cmd script for Windows.
|
||||
* New ID3v1::Tag methods for working directly with genre numbers.
|
||||
* New MPEG::File methods for checking which tags are saved in the file.
|
||||
* Added support for the PropertyMap API to ASF and MP4 files.
|
||||
* Added MusicBrainz identifiers to the PropertyMap API.
|
||||
* Allowed reading of MP4 cover art without an explicitly specified format.
|
||||
* Better parsing of corrupted FLAC files.
|
||||
* Fixed saving of PropertyMap comments without description into ID3v2 tags.
|
||||
* Fixed crash when parsing certain XM files.
|
||||
* Fixed compilation of unit test with clang.
|
||||
* Better handling of files that can't be open or have read-only permissions.
|
||||
* Improved atomic reference counting.
|
||||
* New hookable API for debug messages.
|
||||
* More complete Windows install instructions.
|
||||
* Many smaller bug fixes and performance improvements.
|
||||
|
||||
TagLib 1.8 (Sep 6, 2012)
|
||||
========================
|
||||
|
0
taglib-config.cmd.cmake
Executable file → Normal file
0
taglib-config.cmd.cmake
Executable file → Normal file
0
taglib/CMakeLists.txt
Executable file → Normal file
0
taglib/CMakeLists.txt
Executable file → Normal file
0
taglib/fileref.h
Executable file → Normal file
0
taglib/fileref.h
Executable file → Normal file
@ -25,45 +25,16 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
#include "taglib.h"
|
||||
#include "tdebug.h"
|
||||
#include "tsmartptr.h"
|
||||
#include "mp4item.h"
|
||||
#include "tutils.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
String format(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
char buf[256];
|
||||
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
|
||||
#elif defined(HAVE_SPRINTF_S)
|
||||
|
||||
vsprintf_s(buf, fmt, args);
|
||||
|
||||
#else
|
||||
|
||||
// Be careful. May cause a buffer overflow.
|
||||
vsprintf(buf, fmt, args);
|
||||
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
|
||||
return String(buf);
|
||||
}
|
||||
|
||||
struct ItemData
|
||||
{
|
||||
bool valid;
|
||||
@ -263,26 +234,26 @@ MP4::Item::toString() const
|
||||
case TypeBool:
|
||||
return d->data->m_bool ? "true" : "false";
|
||||
case TypeInt:
|
||||
return format("%d", d->data->m_int);
|
||||
return Utils::formatString("%d", d->data->m_int);
|
||||
case TypeIntPair:
|
||||
return format("%d/%d", d->data->m_intPair.first, d->data->m_intPair.second);
|
||||
return Utils::formatString("%d/%d", d->data->m_intPair.first, d->data->m_intPair.second);
|
||||
case TypeByte:
|
||||
return format("%d", d->data->m_byte);
|
||||
return Utils::formatString("%d", d->data->m_byte);
|
||||
case TypeUInt:
|
||||
return format("%u", d->data->m_uint);
|
||||
return Utils::formatString("%u", d->data->m_uint);
|
||||
case TypeLongLong:
|
||||
return format("%lld", d->data->m_longlong);
|
||||
return Utils::formatString("%lld", d->data->m_longlong);
|
||||
case TypeStringList:
|
||||
return d->data->m_stringList.toString(" / ");
|
||||
case TypeByteVectorList:
|
||||
for(TagLib::uint i = 0; i < d->data->m_byteVectorList.size(); i++) {
|
||||
desc.append(format(
|
||||
desc.append(Utils::formatString(
|
||||
"[%d bytes of data]", static_cast<int>(d->data->m_byteVectorList[i].size())));
|
||||
}
|
||||
return desc.toString(", ");
|
||||
case TypeCoverArtList:
|
||||
for(TagLib::uint i = 0; i < d->data->m_coverArtList.size(); i++) {
|
||||
desc.append(format(
|
||||
desc.append(Utils::formatString(
|
||||
"[%d bytes of data]", static_cast<int>(d->data->m_coverArtList[i].data().size())));
|
||||
}
|
||||
return desc.toString(", ");
|
||||
|
@ -41,13 +41,7 @@ public:
|
||||
channels(0),
|
||||
bitsPerSample(0),
|
||||
encrypted(false),
|
||||
format(Unknown) {}
|
||||
|
||||
enum Format {
|
||||
Unknown = 0,
|
||||
AAC = 1,
|
||||
ALAC = 2,
|
||||
};
|
||||
codec(Unknown) {}
|
||||
|
||||
int length;
|
||||
int bitrate;
|
||||
@ -55,9 +49,13 @@ public:
|
||||
int channels;
|
||||
int bitsPerSample;
|
||||
bool encrypted;
|
||||
Format format;
|
||||
Codec codec;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MP4::AudioProperties::AudioProperties(File *file, MP4::Atoms *atoms, ReadStyle style) :
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
@ -105,14 +103,20 @@ MP4::AudioProperties::isEncrypted() const
|
||||
return d->encrypted;
|
||||
}
|
||||
|
||||
MP4::AudioProperties::Codec
|
||||
MP4::AudioProperties::codec() const
|
||||
{
|
||||
return d->codec;
|
||||
}
|
||||
|
||||
String
|
||||
MP4::AudioProperties::toString() const
|
||||
{
|
||||
String format;
|
||||
if(d->format == PropertiesPrivate::AAC) {
|
||||
if(d->codec == AAC) {
|
||||
format = "AAC";
|
||||
}
|
||||
else if(d->format == PropertiesPrivate::ALAC) {
|
||||
else if(d->codec == ALAC) {
|
||||
format = "ALAC";
|
||||
}
|
||||
else {
|
||||
@ -125,6 +129,10 @@ MP4::AudioProperties::toString() const
|
||||
return desc.toString(", ");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
MP4::AudioProperties::read(File *file, Atoms *atoms)
|
||||
{
|
||||
@ -193,7 +201,7 @@ MP4::AudioProperties::read(File *file, Atoms *atoms)
|
||||
file->seek(atom->offset);
|
||||
data = file->readBlock(atom->length);
|
||||
if(data.mid(20, 4) == "mp4a") {
|
||||
d->format = PropertiesPrivate::AAC;
|
||||
d->codec = AAC;
|
||||
d->channels = data.toInt16BE(40);
|
||||
d->bitsPerSample = data.toInt16BE(42);
|
||||
d->sampleRate = data.toUInt32BE(46);
|
||||
@ -214,7 +222,7 @@ MP4::AudioProperties::read(File *file, Atoms *atoms)
|
||||
}
|
||||
}
|
||||
else if (data.mid(20, 4) == "alac") {
|
||||
d->format = PropertiesPrivate::ALAC;
|
||||
d->codec = ALAC;
|
||||
if (atom->length == 88 && data.mid(56, 4) == "alac") {
|
||||
d->bitsPerSample = data.at(69);
|
||||
d->channels = data.at(73);
|
||||
|
@ -40,6 +40,12 @@ namespace TagLib {
|
||||
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
|
||||
{
|
||||
public:
|
||||
enum Codec {
|
||||
Unknown = 0,
|
||||
AAC,
|
||||
ALAC
|
||||
};
|
||||
|
||||
AudioProperties(File *file, Atoms *atoms, ReadStyle style = Average);
|
||||
virtual ~AudioProperties();
|
||||
|
||||
@ -50,6 +56,9 @@ namespace TagLib {
|
||||
virtual int bitsPerSample() const;
|
||||
bool isEncrypted() const;
|
||||
|
||||
//! Audio codec used in the MP4 file
|
||||
Codec codec() const;
|
||||
|
||||
String toString() const;
|
||||
|
||||
private:
|
||||
|
@ -153,14 +153,14 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns the genre in number.
|
||||
*
|
||||
* /note Normally 255 indicates that this tag contains no genre.
|
||||
* \note Normally 255 indicates that this tag contains no genre.
|
||||
*/
|
||||
TagLib::uint genreNumber() const;
|
||||
|
||||
/*!
|
||||
* Sets the genre in number to \a i.
|
||||
*
|
||||
* /note Valid value is from 0 up to 255. Normally 255 indicates that
|
||||
* \note Valid value is from 0 up to 255. Normally 255 indicates that
|
||||
* this tag contains no genre.
|
||||
*/
|
||||
void setGenreNumber(TagLib::uint i);
|
||||
|
@ -325,7 +325,7 @@ namespace
|
||||
static const TagLib::uint frameTranslationSize = 51;
|
||||
static const char *frameTranslation[][2] = {
|
||||
// Text information frames
|
||||
{ "TALB", "ALBUM"},
|
||||
{ "TALB", "ALBUM" },
|
||||
{ "TBPM", "BPM" },
|
||||
{ "TCOM", "COMPOSER" },
|
||||
{ "TCON", "GENRE" },
|
||||
@ -388,7 +388,7 @@ namespace
|
||||
//{ "USLT", "LYRICS" }, handled specially
|
||||
};
|
||||
|
||||
static const TagLib::uint txxxFrameTranslationSize = 7;
|
||||
static const TagLib::uint txxxFrameTranslationSize = 8;
|
||||
static const char *txxxFrameTranslation[][2] = {
|
||||
{ "MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID" },
|
||||
{ "MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID" },
|
||||
|
@ -89,7 +89,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* Encode a ByteVector with the data from \a s.
|
||||
*
|
||||
* /note Not implemented intentionally. Always returns empty \s ByteVector.
|
||||
* \note Not implemented intentionally. Always returns empty \s ByteVector.
|
||||
*/
|
||||
virtual ByteVector render(const String &s) const;
|
||||
};
|
||||
|
@ -136,11 +136,8 @@ void RIFF::AIFF::AudioProperties::read(const ByteVector &data)
|
||||
d->bitrate = static_cast<int>((sampleRate * d->sampleWidth * d->channels) / 1000.0);
|
||||
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
|
||||
|
||||
if(data.size() < 23) {
|
||||
debug("RIFF::AIFF::AudioProperties::read() - \"COMM\" chunk is too short for AIFF-C.");
|
||||
return;
|
||||
if(data.size() >= 23) {
|
||||
d->compressionType = data.mid(18, 4);
|
||||
d->compressionName = String(data.mid(23, static_cast<uchar>(data[22])));
|
||||
}
|
||||
|
||||
d->compressionType = data.mid(18, 4);
|
||||
d->compressionName = String(data.mid(23, static_cast<uchar>(data[22])));
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <tstring.h>
|
||||
|
||||
#include "rifffile.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
using namespace TagLib;
|
||||
@ -69,6 +70,20 @@ RIFF::File::~File()
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool RIFF::File::isValidChunkName(const ByteVector &name) // static
|
||||
{
|
||||
if(name.size() != 4)
|
||||
return false;
|
||||
|
||||
for(ByteVector::ConstIterator it = name.begin(); it != name.end(); ++it) {
|
||||
const uchar c = static_cast<uchar>(*it);
|
||||
if(c < 32 || 127 < c)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -253,22 +268,6 @@ void RIFF::File::removeChunk(const ByteVector &name)
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isValidChunkID(const ByteVector &name)
|
||||
{
|
||||
if(name.size() != 4) {
|
||||
return false;
|
||||
}
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(name[i] < 32 || name[i] > 127) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void RIFF::File::read()
|
||||
{
|
||||
d->type = readBlock(4);
|
||||
@ -289,13 +288,13 @@ void RIFF::File::read()
|
||||
else
|
||||
chunkSize = readBlock(4).toUInt32LE(0);
|
||||
|
||||
if(!isValidChunkID(chunkName)) {
|
||||
if(!isValidChunkName(chunkName)) {
|
||||
debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(tell() + chunkSize > uint(length())) {
|
||||
if(static_cast<ulonglong>(tell()) + chunkSize > static_cast<ulonglong>(length())) {
|
||||
debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid size (larger than the file size)");
|
||||
setValid(false);
|
||||
break;
|
||||
|
@ -51,6 +51,11 @@ namespace TagLib {
|
||||
*/
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
* Returns whether or not \a name is valid as a chunk name.
|
||||
*/
|
||||
static bool isValidChunkName(const ByteVector &name);
|
||||
|
||||
protected:
|
||||
|
||||
File(FileName file, ByteOrder endianness);
|
||||
|
@ -26,27 +26,12 @@
|
||||
#include <tdebug.h>
|
||||
#include <tfile.h>
|
||||
|
||||
#include "rifffile.h"
|
||||
#include "infotag.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace RIFF::Info;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isValidChunkID(const ByteVector &name)
|
||||
{
|
||||
if(name.size() != 4)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(name[i] < 32 || 127 < name[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class RIFF::Info::Tag::TagPrivate
|
||||
{
|
||||
public:
|
||||
@ -186,6 +171,11 @@ bool RIFF::Info::Tag::isEmpty() const
|
||||
return d->fieldListMap.isEmpty();
|
||||
}
|
||||
|
||||
FieldListMap RIFF::Info::Tag::fieldListMap() const
|
||||
{
|
||||
return d->fieldListMap;
|
||||
}
|
||||
|
||||
String RIFF::Info::Tag::fieldText(const ByteVector &id) const
|
||||
{
|
||||
if(d->fieldListMap.contains(id))
|
||||
@ -197,7 +187,7 @@ String RIFF::Info::Tag::fieldText(const ByteVector &id) const
|
||||
void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s)
|
||||
{
|
||||
// id must be four-byte long pure ASCII string.
|
||||
if(!isValidChunkID(id))
|
||||
if(!RIFF::File::isValidChunkName(id))
|
||||
return;
|
||||
|
||||
if(!s.isEmpty())
|
||||
|
@ -38,7 +38,8 @@ namespace TagLib {
|
||||
|
||||
class File;
|
||||
|
||||
//! A RIFF Info tag implementation.
|
||||
//! A RIFF INFO tag implementation.
|
||||
|
||||
namespace RIFF {
|
||||
namespace Info {
|
||||
|
||||
@ -76,14 +77,15 @@ namespace TagLib {
|
||||
virtual ByteVector render(const String &s) const;
|
||||
};
|
||||
|
||||
//! The main class in the ID3v2 implementation
|
||||
//! The main class in the RIFF INFO tag implementation
|
||||
|
||||
/*!
|
||||
* This is the main class in the INFO tag implementation. RIFF INFO tag is a
|
||||
* metadata format found in WAV audio and AVI video files. Though it is a part
|
||||
* of Microsoft/IBM's RIFF specification, the author could not find the official
|
||||
* documents about it. So, this implementation is referring to unofficial documents
|
||||
* online and some applications' behaviors especially Windows Explorer.
|
||||
* This is the main class in the INFO tag implementation. RIFF INFO tag is
|
||||
* a metadata format found in WAV audio and AVI video files. Though it is a
|
||||
* part of Microsoft/IBM's RIFF specification, the author could not find the
|
||||
* official documents about it. So, this implementation is referring to
|
||||
* unofficial documents on the web and some applications' behaviors especially
|
||||
* Windows Explorer.
|
||||
*/
|
||||
class TAGLIB_EXPORT Tag : public TagLib::Tag
|
||||
{
|
||||
@ -120,6 +122,18 @@ namespace TagLib {
|
||||
|
||||
virtual bool isEmpty() const;
|
||||
|
||||
/*!
|
||||
* Returns a copy of the internal fields of the tag. The returned map directly
|
||||
* reflects the contents of the "INFO" chunk.
|
||||
*
|
||||
* \note Modifying this map does not affect the tag's internal data.
|
||||
* Use setFieldText() and removeField() instead.
|
||||
*
|
||||
* \see setFieldText()
|
||||
* \see removeField()
|
||||
*/
|
||||
FieldListMap fieldListMap() const;
|
||||
|
||||
/*
|
||||
* Gets the value of the field with the ID \a id.
|
||||
*/
|
||||
|
@ -27,8 +27,8 @@
|
||||
#define TAGLIB_H
|
||||
|
||||
#define TAGLIB_MAJOR_VERSION 1
|
||||
#define TAGLIB_MINOR_VERSION 8
|
||||
#define TAGLIB_PATCH_VERSION 0
|
||||
#define TAGLIB_MINOR_VERSION 9
|
||||
#define TAGLIB_PATCH_VERSION 1
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1600)
|
||||
#define TAGLIB_CONSTRUCT_BITSET(x) static_cast<unsigned long long>(x)
|
||||
|
@ -27,11 +27,13 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
||||
#include "tstring.h"
|
||||
#include "tdebug.h"
|
||||
@ -464,60 +466,41 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit
|
||||
if(pattern.size() == 0 || pattern.size() > size())
|
||||
return *this;
|
||||
|
||||
const size_t withSize = with.size();
|
||||
const size_t withSize = with.size();
|
||||
const size_t patternSize = pattern.size();
|
||||
const ptrdiff_t diff = withSize - patternSize;
|
||||
|
||||
size_t offset = 0;
|
||||
while (true)
|
||||
{
|
||||
offset = find(pattern, offset);
|
||||
if(offset == npos)
|
||||
break;
|
||||
|
||||
if(withSize == patternSize) {
|
||||
// I think this case might be common enough to optimize it
|
||||
detach();
|
||||
offset = find(pattern);
|
||||
while(offset != npos) {
|
||||
::memcpy(DATA(d) + offset, DATA(with.d), withSize);
|
||||
offset = find(pattern, offset + withSize);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// calculate new size:
|
||||
size_t newSize = 0;
|
||||
for(;;) {
|
||||
const size_t next = find(pattern, offset);
|
||||
if(next == npos) {
|
||||
if(offset == 0)
|
||||
// pattern not found, do nothing:
|
||||
return *this;
|
||||
newSize += size() - offset;
|
||||
if(diff < 0) {
|
||||
::memmove(
|
||||
data() + offset + withSize,
|
||||
data() + offset + patternSize,
|
||||
size() - offset - patternSize);
|
||||
resize(size() + diff);
|
||||
}
|
||||
else if(diff > 0) {
|
||||
resize(size() + diff);
|
||||
::memmove(
|
||||
data() + offset + withSize,
|
||||
data() + offset + patternSize,
|
||||
size() - diff - offset - patternSize);
|
||||
}
|
||||
|
||||
::memcpy(data() + offset, with.data(), with.size());
|
||||
|
||||
offset += withSize;
|
||||
if(offset > size() - patternSize)
|
||||
break;
|
||||
}
|
||||
newSize += (next - offset) + withSize;
|
||||
offset = next + patternSize;
|
||||
}
|
||||
|
||||
// new private data of appropriate size:
|
||||
ByteVectorPrivate newData(newSize, '\0');
|
||||
char *target = &(*newData.data)[0];
|
||||
const char *source = DATA(d);
|
||||
|
||||
// copy modified data into new private data:
|
||||
offset = 0;
|
||||
for(;;) {
|
||||
const size_t next = find(pattern, offset);
|
||||
if(next == npos) {
|
||||
::memcpy(target, source + offset, size() - offset);
|
||||
break;
|
||||
}
|
||||
const size_t chunkSize = next - offset;
|
||||
::memcpy(target, source + offset, chunkSize);
|
||||
target += chunkSize;
|
||||
::memcpy(target, DATA(with.d), withSize);
|
||||
target += withSize;
|
||||
offset += chunkSize + patternSize;
|
||||
}
|
||||
|
||||
// replace private data:
|
||||
*d = newData;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -29,44 +29,13 @@
|
||||
|
||||
#include "tdebug.h"
|
||||
#include "tstring.h"
|
||||
#include "tutils.h"
|
||||
#include "tdebuglistener.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
String format(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
char buf[256];
|
||||
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
|
||||
#elif defined(HAVE_SPRINTF_S)
|
||||
|
||||
vsprintf_s(buf, fmt, args);
|
||||
|
||||
#else
|
||||
|
||||
// Be careful. May cause a buffer overflow.
|
||||
vsprintf(buf, fmt, args);
|
||||
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
|
||||
return String(buf);
|
||||
}
|
||||
}
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
// The instance is defined in tdebuglistener.cpp.
|
||||
@ -88,7 +57,8 @@ namespace TagLib
|
||||
for(size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
std::string bits = std::bitset<8>(v[i]).to_string();
|
||||
String msg = format("*** [%d] - char '%c' - int %d, 0x%02x, 0b%s\n",
|
||||
String msg = Utils::formatString(
|
||||
"*** [%d] - char '%c' - int %d, 0x%02x, 0b%s\n",
|
||||
i, v[i], v[i], v[i], bits.c_str());
|
||||
|
||||
debugListener->printMessage(msg);
|
||||
|
@ -41,8 +41,12 @@ namespace
|
||||
|
||||
bool supportsUnicode()
|
||||
{
|
||||
#ifdef UNICODE
|
||||
return true;
|
||||
#else
|
||||
const FARPROC p = GetProcAddress(GetModuleHandleA("kernel32"), "CreateFileW");
|
||||
return (p != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Indicates whether the system supports Unicode file names.
|
||||
|
@ -28,15 +28,12 @@
|
||||
|
||||
#include "tbytevector.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "tstring.h"
|
||||
# include "tdebug.h"
|
||||
#endif
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
class String;
|
||||
|
||||
class TAGLIB_EXPORT FileName
|
||||
{
|
||||
public:
|
||||
|
@ -35,6 +35,7 @@
|
||||
*/
|
||||
namespace TagLib
|
||||
{
|
||||
|
||||
class TAGLIB_EXPORT RefCounter
|
||||
{
|
||||
public:
|
||||
@ -49,7 +50,9 @@ namespace TagLib
|
||||
class RefCounterPrivate;
|
||||
RefCounterPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DO_NOT_DOCUMENT
|
||||
#endif
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "tutils.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef HAVE_STD_CODECVT
|
||||
@ -156,11 +155,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
StringPrivate(const std::wstring &s)
|
||||
: data(new std::wstring(s))
|
||||
{
|
||||
}
|
||||
|
||||
StringPrivate(size_t n, wchar_t c)
|
||||
: data(new std::wstring(n, c))
|
||||
{
|
||||
@ -268,6 +262,9 @@ String::String(const ByteVector &v, Type t)
|
||||
copyFromUTF8(v.data(), v.size());
|
||||
else
|
||||
copyFromUTF16(v.data(), v.size(), t);
|
||||
|
||||
// If we hit a null in the ByteVector, shrink the string again.
|
||||
d->data->resize(::wcslen(d->data->c_str()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -390,7 +387,7 @@ String String::upper() const
|
||||
{
|
||||
static const int shift = 'A' - 'a';
|
||||
|
||||
String s(*this);
|
||||
String s(*d->data);
|
||||
for(Iterator it = s.begin(); it != s.end(); ++it) {
|
||||
if(*it >= 'a' && *it <= 'z')
|
||||
*it = *it + shift;
|
||||
@ -559,30 +556,7 @@ bool String::isAscii() const
|
||||
|
||||
String String::number(int n) // static
|
||||
{
|
||||
static const size_t BufferSize = 11; // Sufficient to store "-214748364".
|
||||
static const char *Format = "%d";
|
||||
|
||||
char buffer[BufferSize];
|
||||
int length;
|
||||
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
|
||||
length = snprintf(buffer, BufferSize, Format, n);
|
||||
|
||||
#elif defined(HAVE_SPRINTF_S)
|
||||
|
||||
length = sprintf_s(buffer, Format, n);
|
||||
|
||||
#else
|
||||
|
||||
length = sprintf(buffer, Format, n);
|
||||
|
||||
#endif
|
||||
|
||||
if(length > 0)
|
||||
return String(buffer);
|
||||
else
|
||||
return String::null;
|
||||
return Utils::formatString("%d", n);
|
||||
}
|
||||
|
||||
TagLib::wchar &String::operator[](size_t i)
|
||||
@ -672,54 +646,43 @@ String &String::operator=(const String &s)
|
||||
|
||||
String &String::operator=(const std::string &s)
|
||||
{
|
||||
d->data.reset(new std::wstring());
|
||||
copyFromLatin1(s.c_str(), s.length());
|
||||
|
||||
*this = String(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const std::wstring &s)
|
||||
{
|
||||
d->data.reset(new std::wstring(s));
|
||||
*this = String(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const wchar_t *s)
|
||||
{
|
||||
d->data.reset(new std::wstring());
|
||||
copyFromUTF16(s, ::wcslen(s), WCharByteOrder);
|
||||
|
||||
*this = String(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(char c)
|
||||
{
|
||||
d->data.reset(new std::wstring(1, c));
|
||||
*this = String(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(wchar_t c)
|
||||
{
|
||||
d->data.reset(new std::wstring(1, c));
|
||||
*this = String(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const char *s)
|
||||
{
|
||||
d->data.reset(new std::wstring());
|
||||
copyFromLatin1(s, ::strlen(s));
|
||||
|
||||
*this = String(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(const ByteVector &v)
|
||||
{
|
||||
d->data.reset(new std::wstring());
|
||||
copyFromLatin1(v.data(), v.size());
|
||||
|
||||
// If we hit a null in the ByteVector, shrink the string again.
|
||||
d->data->resize(::wcslen(d->data->c_str()));
|
||||
|
||||
*this = String(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -129,11 +129,21 @@ 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
String(const wchar_t *s, Type t = WCharByteOrder);
|
||||
|
||||
@ -147,8 +157,13 @@ 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
|
||||
*/
|
||||
String(wchar_t c, Type t = Latin1);
|
||||
String(wchar_t c, Type t = WCharByteOrder);
|
||||
|
||||
|
||||
/*!
|
||||
@ -161,9 +176,6 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Makes a deep copy of the data in \a s.
|
||||
*
|
||||
* \note This should only be used with the 8-bit codecs Latin1 and UTF8, when
|
||||
* used with other codecs it will simply print a warning and exit.
|
||||
*/
|
||||
String(const ByteVector &v, Type t = Latin1);
|
||||
|
||||
@ -219,7 +231,7 @@ namespace TagLib {
|
||||
* 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()
|
||||
|
@ -31,7 +31,7 @@
|
||||
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MSC_BYTESWAP)
|
||||
@ -44,6 +44,10 @@
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
#include "tstring.h"
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
namespace Utils
|
||||
@ -144,6 +148,47 @@ namespace TagLib
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
inline String formatString(const char *format, ...)
|
||||
{
|
||||
// Sufficient buffer size for the current internal uses.
|
||||
// Consider changing this value when you use this function.
|
||||
|
||||
static const size_t BufferSize = 128;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
char buf[BufferSize];
|
||||
int length;
|
||||
|
||||
#if defined(HAVE_SNPRINTF)
|
||||
|
||||
length = vsnprintf(buf, BufferSize, format, args);
|
||||
|
||||
#elif defined(HAVE_SPRINTF_S)
|
||||
|
||||
length = vsprintf_s(buf, format, args);
|
||||
|
||||
#else
|
||||
|
||||
// The last resort. May cause a buffer overflow.
|
||||
|
||||
length = vsprintf(buf, format, args);
|
||||
if(length >= BufferSize) {
|
||||
debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
|
||||
length = -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
|
||||
if(length != -1)
|
||||
return String(buf);
|
||||
else
|
||||
return String::null;
|
||||
}
|
||||
|
||||
#ifdef SYSTEM_BYTEORDER
|
||||
|
||||
|
@ -106,6 +106,11 @@
|
||||
bit mask & shift operations.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
// Workaround for when MSVC doesn't have wchar_t as a built-in type.
|
||||
#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
/* Some fundamental constants */
|
||||
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
|
||||
#define UNI_MAX_BMP (UTF32)0x0000FFFF
|
||||
@ -114,10 +119,10 @@
|
||||
|
||||
namespace Unicode {
|
||||
|
||||
typedef unsigned long UTF32; /* at least 32 bits */
|
||||
typedef wchar_t UTF16; /* TagLib assumes that wchar_t is sufficient for UTF-16. */
|
||||
typedef unsigned long UTF32; /* at least 32 bits */
|
||||
typedef wchar_t UTF16; /* TagLib assumes that wchar_t is sufficient for UTF-16. */
|
||||
typedef unsigned char UTF8; /* typically 8 bits */
|
||||
typedef unsigned char Boolean; /* 0 or 1 */
|
||||
typedef unsigned char Boolean; /* 0 or 1 */
|
||||
|
||||
typedef enum {
|
||||
conversionOK = 0, /* conversion successful */
|
||||
|
@ -112,8 +112,9 @@ TagLib::uint WavPack::AudioProperties::sampleFrames() const
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int sample_rates[] = { 6000, 8000, 9600, 11025, 12000,
|
||||
16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 };
|
||||
static const unsigned int sample_rates[] = {
|
||||
6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
|
||||
32000, 44100, 48000, 64000, 88200, 96000, 192000, 0 };
|
||||
}
|
||||
|
||||
#define BYTES_STORED 3
|
||||
|
@ -65,7 +65,12 @@ namespace TagLib {
|
||||
|
||||
virtual int length() const;
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
* Returns the sample rate in Hz. 0 means unknown or custom.
|
||||
*/
|
||||
virtual int sampleRate() const;
|
||||
|
||||
virtual int channels() const;
|
||||
|
||||
/*!
|
||||
|
@ -56,6 +56,7 @@ SET(test_runner_SRCS
|
||||
test_ape.cpp
|
||||
test_apetag.cpp
|
||||
test_wav.cpp
|
||||
test_info.cpp
|
||||
test_wavpack.cpp
|
||||
test_mp4.cpp
|
||||
test_mp4item.cpp
|
||||
|
@ -232,6 +232,11 @@ public:
|
||||
a.replace(ByteVector("ab"), ByteVector());
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("cdf"), a);
|
||||
}
|
||||
{
|
||||
ByteVector a("abcdabf");
|
||||
a.replace(ByteVector("bf"), ByteVector("x"));
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("abcdax"), a);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <tstring.h>
|
||||
#include <mpegfile.h>
|
||||
#include <id3v1tag.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace TagLib;
|
||||
@ -16,8 +19,20 @@ public:
|
||||
|
||||
void testStripWhiteSpace()
|
||||
{
|
||||
ID3v1::StringHandler h;
|
||||
CPPUNIT_ASSERT_EQUAL(String("Foo"), h.parse(ByteVector("Foo ")));
|
||||
ScopedFileCopy copy("xing", ".mp3");
|
||||
string newname = copy.fileName();
|
||||
|
||||
{
|
||||
MPEG::File f(newname.c_str());
|
||||
f.ID3v1Tag(true)->setArtist("Artist ");
|
||||
f.save();
|
||||
}
|
||||
|
||||
{
|
||||
MPEG::File f(newname.c_str());
|
||||
CPPUNIT_ASSERT(f.ID3v1Tag(false));
|
||||
CPPUNIT_ASSERT_EQUAL(String("Artist"), f.ID3v1Tag(false)->artist());
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1,9 +1,7 @@
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <infotag.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tdebug.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
|
||||
using namespace std;
|
||||
@ -23,7 +21,13 @@ public:
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(String(""), tag.title());
|
||||
tag.setTitle("Test title 1");
|
||||
tag.setFieldText("TEST", "Dummy Text");
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(String("Test title 1"), tag.title());
|
||||
|
||||
RIFF::Info::FieldListMap map = tag.fieldListMap();
|
||||
CPPUNIT_ASSERT_EQUAL(String("Test title 1"), map["INAM"]);
|
||||
CPPUNIT_ASSERT_EQUAL(String("Dummy Text"), map["TEST"]);
|
||||
}
|
||||
|
||||
void testNumericFields()
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
|
||||
CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
|
||||
CPPUNIT_ASSERT_EQUAL(16, ((MP4::AudioProperties *)f.audioProperties())->bitsPerSample());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::AudioProperties::AAC, ((MP4::AudioProperties *)f.audioProperties())->codec());
|
||||
}
|
||||
|
||||
void testPropertiesALAC()
|
||||
@ -49,6 +50,7 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
|
||||
CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
|
||||
CPPUNIT_ASSERT_EQUAL(16, ((MP4::AudioProperties *)f.audioProperties())->bitsPerSample());
|
||||
CPPUNIT_ASSERT_EQUAL(MP4::AudioProperties::ALAC, ((MP4::AudioProperties *)f.audioProperties())->codec());
|
||||
}
|
||||
|
||||
void testCheckValid()
|
||||
|
@ -41,14 +41,28 @@ class TestString : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testAppendCharDetach);
|
||||
CPPUNIT_TEST(testAppendStringDetach);
|
||||
CPPUNIT_TEST(testToInt);
|
||||
CPPUNIT_TEST(testFromInt);
|
||||
CPPUNIT_TEST(testSubstr);
|
||||
CPPUNIT_TEST(testNewline);
|
||||
CPPUNIT_TEST(testUpper);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
|
||||
void testString()
|
||||
{
|
||||
// Needs to know the system byte order for some Unicode tests.
|
||||
bool littleEndian;
|
||||
{
|
||||
union {
|
||||
int i;
|
||||
char c;
|
||||
} u;
|
||||
|
||||
u.i = 1;
|
||||
littleEndian = (u.c == 1) ? true : false;
|
||||
}
|
||||
|
||||
String s = "taglib string";
|
||||
ByteVector v = "taglib string";
|
||||
CPPUNIT_ASSERT(v == s.data(String::Latin1));
|
||||
@ -72,8 +86,28 @@ public:
|
||||
String unicode2(unicode.to8Bit(true), String::UTF8);
|
||||
CPPUNIT_ASSERT(unicode == unicode2);
|
||||
|
||||
String unicode3(L"\u65E5\u672C\u8A9E");
|
||||
CPPUNIT_ASSERT(*(unicode3.toCWString() + 1) == L'\u672C');
|
||||
String unicode3(L"\u65E5\u672C\u8A9E");
|
||||
CPPUNIT_ASSERT(*(unicode3.toCWString() + 1) == L'\u672C');
|
||||
|
||||
String unicode4(L"\u65e5\u672c\u8a9e");
|
||||
CPPUNIT_ASSERT(unicode4[1] == L'\u672c');
|
||||
|
||||
String unicode5(L"\u65e5\u672c\u8a9e", String::UTF16BE);
|
||||
CPPUNIT_ASSERT(unicode5[1] == (littleEndian ? L'\u2c67' : L'\u672c'));
|
||||
|
||||
String unicode6(L"\u65e5\u672c\u8a9e", String::UTF16LE);
|
||||
CPPUNIT_ASSERT(unicode6[1] == (littleEndian ? L'\u672c' : L'\u2c67'));
|
||||
|
||||
wstring stduni = L"\u65e5\u672c\u8a9e";
|
||||
|
||||
String unicode7(stduni);
|
||||
CPPUNIT_ASSERT(unicode7[1] == L'\u672c');
|
||||
|
||||
String unicode8(stduni, String::UTF16BE);
|
||||
CPPUNIT_ASSERT(unicode8[1] == (littleEndian ? L'\u2c67' : L'\u672c'));
|
||||
|
||||
String unicode9(stduni, String::UTF16LE);
|
||||
CPPUNIT_ASSERT(unicode9[1] == (littleEndian ? L'\u672c' : L'\u2c67'));
|
||||
|
||||
CPPUNIT_ASSERT(strcmp(String::number(0).toCString(), "0") == 0);
|
||||
CPPUNIT_ASSERT(strcmp(String::number(12345678).toCString(), "12345678") == 0);
|
||||
@ -215,6 +249,12 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(String("-123aa").toInt(), -123);
|
||||
}
|
||||
|
||||
void testFromInt()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(String("123"), String::number(123));
|
||||
CPPUNIT_ASSERT_EQUAL(String("-123"), String::number(-123));
|
||||
}
|
||||
|
||||
void testSubstr()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(String("01"), String("0123456").substr(0, 2));
|
||||
@ -237,6 +277,14 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(L'\x0d', String(crlf)[3]);
|
||||
CPPUNIT_ASSERT_EQUAL(L'\x0a', String(crlf)[4]);
|
||||
}
|
||||
|
||||
void testUpper()
|
||||
{
|
||||
String s1 = "tagLIB 012 strING";
|
||||
String s2 = s1.upper();
|
||||
CPPUNIT_ASSERT_EQUAL(String("tagLIB 012 strING"), s1);
|
||||
CPPUNIT_ASSERT_EQUAL(String("TAGLIB 012 STRING"), s2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user