mirror of
https://github.com/taglib/taglib.git
synced 2025-06-04 01:28:21 -04:00
Merge branch 'master' into merge-master
Conflicts: ConfigureChecks.cmake config-taglib.h.cmake taglib/CMakeLists.txt taglib/ape/apefooter.cpp taglib/ape/apeitem.cpp taglib/ape/apeproperties.cpp taglib/asf/asfattribute.cpp taglib/asf/asffile.cpp taglib/asf/asfpicture.cpp taglib/fileref.cpp taglib/flac/flacfile.cpp taglib/flac/flacpicture.cpp taglib/flac/flacproperties.cpp taglib/mp4/mp4atom.cpp taglib/mp4/mp4coverart.cpp taglib/mp4/mp4item.cpp taglib/mp4/mp4properties.cpp taglib/mp4/mp4tag.cpp taglib/mpc/mpcproperties.cpp taglib/mpeg/id3v2/frames/popularimeterframe.cpp taglib/mpeg/id3v2/frames/relativevolumeframe.cpp taglib/mpeg/id3v2/id3v2frame.cpp taglib/mpeg/id3v2/id3v2synchdata.cpp taglib/mpeg/xingheader.cpp taglib/ogg/flac/oggflacfile.cpp taglib/ogg/oggpageheader.cpp taglib/ogg/opus/opusproperties.cpp taglib/ogg/speex/speexproperties.cpp taglib/ogg/vorbis/vorbisproperties.cpp taglib/ogg/xiphcomment.cpp taglib/riff/aiff/aiffproperties.cpp taglib/riff/wav/infotag.cpp taglib/riff/wav/wavproperties.cpp taglib/toolkit/taglib.h taglib/toolkit/tbytevector.cpp taglib/toolkit/tbytevector.h taglib/toolkit/tfilestream.cpp taglib/toolkit/tiostream.h taglib/toolkit/tstring.cpp taglib/toolkit/tstringhandler.cpp taglib/trueaudio/trueaudioproperties.cpp taglib/wavpack/wavpackproperties.cpp
This commit is contained in:
commit
36512745cf
@ -21,7 +21,6 @@ option(BUILD_EXAMPLES "Build the examples" OFF)
|
||||
|
||||
option(NO_ITUNES_HACKS "Disable workarounds for iTunes bugs" OFF)
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
set(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
|
||||
|
||||
## the following are directories where stuff will be installed to
|
||||
|
@ -8,13 +8,18 @@ include(CheckCXXSourceCompiles)
|
||||
include(TestBigEndian)
|
||||
|
||||
# Determine the CPU byte order.
|
||||
|
||||
test_big_endian(TAGLIB_BIG_ENDIAN)
|
||||
|
||||
if(NOT TAGLIB_BIG_ENDIAN)
|
||||
set(TAGLIB_LITTLE_ENDIAN 1)
|
||||
endif()
|
||||
|
||||
# Determine the size of integral types.
|
||||
check_type_size("short" SIZEOF_SHORT)
|
||||
check_type_size("int" SIZEOF_INT)
|
||||
check_type_size("long long" SIZEOF_LONGLONG)
|
||||
check_type_size("wchar_t" SIZEOF_WCHAR_T)
|
||||
|
||||
# Determine whether or not your compiler supports move semantics.
|
||||
check_cxx_source_compiles("
|
||||
#ifdef __clang__
|
||||
@ -25,6 +30,15 @@ check_cxx_source_compiles("
|
||||
int main() { return func(std::move(1)); }
|
||||
" SUPPORT_MOVE_SEMANTICS)
|
||||
|
||||
# Determine if your compiler supports std::wstring.
|
||||
check_cxx_source_compiles("
|
||||
#include <string>
|
||||
int main() {
|
||||
std::wstring x(L\"ABC\");
|
||||
return 0;
|
||||
}
|
||||
" HAVE_STD_WSTRING)
|
||||
|
||||
# Determine which kind of byte swap functions your compiler supports.
|
||||
|
||||
# GCC's __builtin_bswap* should be checked individually
|
||||
@ -179,13 +193,16 @@ if(NOT HAVE_SNPRINTF)
|
||||
" HAVE_SPRINTF_S)
|
||||
endif()
|
||||
|
||||
# Determine whether your compiler supports codecvt header.
|
||||
# Determine whether your compiler supports codecvt.
|
||||
check_cxx_source_compiles("
|
||||
#include <codecvt>
|
||||
int main() { std::codecvt_utf8_utf16<wchar_t> x; return 0; }
|
||||
" HAVE_CODECVT)
|
||||
#include <codecvt>
|
||||
int main() {
|
||||
std::codecvt_utf8_utf16<wchar_t> x;
|
||||
return 0;
|
||||
}
|
||||
" HAVE_STD_CODECVT)
|
||||
|
||||
# check for libz using the cmake supplied FindZLIB.cmake
|
||||
# Check for libz using the cmake supplied FindZLIB.cmake
|
||||
find_package(ZLIB)
|
||||
if(ZLIB_FOUND)
|
||||
set(HAVE_ZLIB 1)
|
||||
@ -193,10 +210,10 @@ else()
|
||||
set(HAVE_ZLIB 0)
|
||||
endif()
|
||||
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||
find_package(CppUnit)
|
||||
if(NOT CppUnit_FOUND AND BUILD_TESTS)
|
||||
message(STATUS "CppUnit not found, disabling tests.")
|
||||
set(BUILD_TESTS OFF)
|
||||
endif()
|
||||
|
||||
|
@ -4,9 +4,18 @@
|
||||
#cmakedefine TAGLIB_LITTLE_ENDIAN 1
|
||||
#cmakedefine TAGLIB_BIG_ENDIAN 1
|
||||
|
||||
/* Size of integral types */
|
||||
#cmakedefine SIZEOF_SHORT ${SIZEOF_SHORT}
|
||||
#cmakedefine SIZEOF_INT ${SIZEOF_INT}
|
||||
#cmakedefine SIZEOF_LONGLONG ${SIZEOF_LONGLONG}
|
||||
#cmakedefine SIZEOF_WCHAR_T ${SIZEOF_WCHAR_T}
|
||||
|
||||
/* Defined if your compiler supports the move semantics */
|
||||
#cmakedefine SUPPORT_MOVE_SEMANTICS 1
|
||||
|
||||
/* Defined if your compiler supports std::wstring */
|
||||
#cmakedefine HAVE_STD_WSTRING 1
|
||||
|
||||
/* Defined if your compiler supports some byte swap functions */
|
||||
#cmakedefine HAVE_GCC_BYTESWAP_16 1
|
||||
#cmakedefine HAVE_GCC_BYTESWAP_32 1
|
||||
@ -31,10 +40,10 @@
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
#cmakedefine HAVE_SPRINTF_S 1
|
||||
|
||||
/* Defined if your compiler has <codecvt> header */
|
||||
#cmakedefine HAVE_CODECVT 1
|
||||
/* Defined if your compiler supports codecvt */
|
||||
#cmakedefine HAVE_STD_CODECVT 1
|
||||
|
||||
/* Define if you have libz */
|
||||
/* Defined if you have libz */
|
||||
#cmakedefine HAVE_ZLIB 1
|
||||
|
||||
#cmakedefine NO_ITUNES_HACKS 1
|
||||
@ -42,4 +51,3 @@
|
||||
#cmakedefine WITH_MP4 1
|
||||
|
||||
#cmakedefine TESTS_DIR "@TESTS_DIR@"
|
||||
|
||||
|
@ -125,7 +125,7 @@ void APE::Properties::read()
|
||||
|
||||
// Then we read the header common for all versions of APE
|
||||
d->file->seek(offset);
|
||||
ByteVector commonHeader=d->file->readBlock(6);
|
||||
ByteVector commonHeader = d->file->readBlock(6);
|
||||
if(!commonHeader.startsWith("MAC "))
|
||||
return;
|
||||
d->version = commonHeader.toUInt16LE(4);
|
||||
@ -182,7 +182,7 @@ void APE::Properties::analyzeCurrent()
|
||||
// Read the descriptor
|
||||
d->file->seek(2, File::Current);
|
||||
ByteVector descriptor = d->file->readBlock(44);
|
||||
uint descriptorBytes = descriptor.toUInt32LE(0);
|
||||
const uint descriptorBytes = descriptor.toUInt32LE(0);
|
||||
|
||||
if ((descriptorBytes - 52) > 0)
|
||||
d->file->seek(descriptorBytes - 52, File::Current);
|
||||
@ -196,9 +196,10 @@ void APE::Properties::analyzeCurrent()
|
||||
d->bitsPerSample = header.toInt16LE(16);
|
||||
//d->compressionLevel =
|
||||
|
||||
uint totalFrames = header.toUInt32LE(12);
|
||||
uint blocksPerFrame = header.toUInt32LE(4);
|
||||
uint finalFrameBlocks = header.toUInt32LE(8);
|
||||
const uint totalFrames = header.toUInt32LE(12);
|
||||
const uint blocksPerFrame = header.toUInt32LE(4);
|
||||
const uint finalFrameBlocks = header.toUInt32LE(8);
|
||||
|
||||
d->sampleFrames = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
|
||||
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
|
||||
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
|
||||
@ -207,13 +208,13 @@ void APE::Properties::analyzeCurrent()
|
||||
void APE::Properties::analyzeOld()
|
||||
{
|
||||
ByteVector header = d->file->readBlock(26);
|
||||
uint totalFrames = header.toUInt32LE(18);
|
||||
const uint totalFrames = header.toUInt32LE(18);
|
||||
|
||||
// Fail on 0 length APE files (catches non-finalized APE files)
|
||||
if(totalFrames == 0)
|
||||
return;
|
||||
|
||||
short compressionLevel = header.toUInt32LE(0);
|
||||
const short compressionLevel = header.toUInt32LE(0);
|
||||
uint blocksPerFrame;
|
||||
if(d->version >= 3950)
|
||||
blocksPerFrame = 73728 * 4;
|
||||
@ -221,6 +222,7 @@ void APE::Properties::analyzeOld()
|
||||
blocksPerFrame = 73728;
|
||||
else
|
||||
blocksPerFrame = 9216;
|
||||
|
||||
d->channels = header.toUInt16LE(4);
|
||||
d->sampleRate = header.toUInt32LE(6);
|
||||
const uint finalFrameBlocks = header.toUInt32LE(22);
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <taglib.h>
|
||||
#include <tdebug.h>
|
||||
#include "asfattribute.h"
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tbytevectorlist.h>
|
||||
#include <tpropertymap.h>
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <taglib.h>
|
||||
#include <tdebug.h>
|
||||
#include "asfattribute.h"
|
||||
@ -161,7 +157,7 @@ void ASF::Picture::parse(const ByteVector& bytes)
|
||||
return;
|
||||
size_t pos = 0;
|
||||
d->type = (Type)bytes[0]; ++pos;
|
||||
uint dataLen = bytes.toUInt32LE(pos); pos+=4;
|
||||
const uint dataLen = bytes.toUInt32LE(pos); pos+=4;
|
||||
|
||||
const ByteVector nullStringTerminator(2, 0);
|
||||
|
||||
|
@ -23,9 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tstring.h>
|
||||
|
@ -23,9 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#include <tpropertymap.h>
|
||||
#include "asftag.h"
|
||||
|
@ -27,13 +27,11 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <Shlwapi.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <tfile.h>
|
||||
#include <tstring.h>
|
||||
@ -231,8 +229,8 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
|
||||
|
||||
#ifdef _WIN32
|
||||
// Avoids direct conversion from FileName to String
|
||||
// because String can't accept non-Latin-1 string in char array.
|
||||
|
||||
// because String can't decode strings in local encodings properly.
|
||||
|
||||
if(!fileName.wstr().empty()) {
|
||||
const wchar_t *pext = PathFindExtensionW(fileName.wstr().c_str());
|
||||
if(*pext == L'.')
|
||||
|
@ -32,6 +32,10 @@
|
||||
#include "taglib_export.h"
|
||||
#include "audioproperties.h"
|
||||
|
||||
#if _WIN32
|
||||
# pragma comment(lib, "shlwapi.lib")
|
||||
#endif
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
class Tag;
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <taglib.h>
|
||||
#include <tdebug.h>
|
||||
#include "flacmetadatablock.h"
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <taglib.h>
|
||||
#include <tdebug.h>
|
||||
#include "flacpicture.h"
|
||||
@ -109,7 +105,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
|
||||
pos += 4;
|
||||
d->numColors = data.toUInt32BE(pos);
|
||||
pos += 4;
|
||||
uint dataLength = data.toUInt32BE(pos);
|
||||
const uint dataLength = data.toUInt32BE(pos);
|
||||
pos += 4;
|
||||
if(pos + dataLength > data.size()) {
|
||||
debug("Invalid picture block.");
|
||||
|
@ -118,7 +118,7 @@ void FLAC::Properties::read()
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
uint pos = 0;
|
||||
|
||||
// Minimum block size (in samples)
|
||||
pos += 2;
|
||||
@ -132,7 +132,7 @@ void FLAC::Properties::read()
|
||||
// Maximum frame size (in bytes)
|
||||
pos += 3;
|
||||
|
||||
uint flags = d->data.toUInt32BE(pos);
|
||||
const uint flags = d->data.toUInt32BE(pos);
|
||||
pos += 4;
|
||||
|
||||
d->sampleRate = flags >> 12;
|
||||
@ -142,8 +142,8 @@ void FLAC::Properties::read()
|
||||
// The last 4 bits are the most significant 4 bits for the 36 bit
|
||||
// stream length in samples. (Audio files measured in days)
|
||||
|
||||
unsigned long long hi = flags & 0xf;
|
||||
unsigned long long lo = d->data.toUInt32BE(pos);
|
||||
const ulonglong hi = flags & 0xf;
|
||||
const ulonglong lo = d->data.toUInt32BE(pos);
|
||||
pos += 4;
|
||||
|
||||
d->sampleFrames = (hi << 32) | lo;
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <taglib.h>
|
||||
#include <tdebug.h>
|
||||
#include <tstring.h>
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tstring.h>
|
||||
#include "mp4atom.h"
|
||||
@ -55,16 +51,16 @@ MP4::Atom::Atom(File *file)
|
||||
length = header.toUInt32BE(0);
|
||||
|
||||
if (length == 1) {
|
||||
long long longLength = file->readBlock(8).toInt64BE(0);
|
||||
const long long longLength = file->readBlock(8).toInt64BE(0);
|
||||
if (longLength >= 8 && longLength <= 0xFFFFFFFF) {
|
||||
// The atom has a 64-bit length, but it's actually a 32-bit value
|
||||
length = (long)longLength;
|
||||
// The atom has a 64-bit length, but it's actually a 32-bit value
|
||||
length = (long)longLength;
|
||||
}
|
||||
else {
|
||||
debug("MP4: 64-bit atoms are not supported");
|
||||
length = 0;
|
||||
file->seek(0, File::End);
|
||||
return;
|
||||
debug("MP4: 64-bit atoms are not supported");
|
||||
length = 0;
|
||||
file->seek(0, File::End);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (length < 8) {
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <taglib.h>
|
||||
#include <tdebug.h>
|
||||
#include "mp4coverart.h"
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tstring.h>
|
||||
#include <tpropertymap.h>
|
||||
|
@ -23,13 +23,8 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <taglib.h>
|
||||
#include <tdebug.h>
|
||||
#include "mp4item.h"
|
||||
|
@ -23,9 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tstring.h>
|
||||
@ -130,7 +128,7 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
|
||||
d->bitsPerSample = data.toInt16BE(42);
|
||||
d->sampleRate = data.toUInt32BE(46);
|
||||
if(data.mid(56, 4) == "esds" && data[64] == 0x03) {
|
||||
long pos = 65;
|
||||
uint pos = 65;
|
||||
if(data.mid(pos, 3) == "\x80\x80\x80") {
|
||||
pos += 3;
|
||||
}
|
||||
|
@ -23,9 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tstring.h>
|
||||
@ -114,9 +112,9 @@ MP4::Tag::parseData2(MP4::Atom *atom, TagLib::File *file, int expectedFlags, boo
|
||||
int i = 0;
|
||||
size_t pos = 0;
|
||||
while(pos < data.size()) {
|
||||
int length = data.toUInt32BE(pos);
|
||||
ByteVector name = data.mid(pos + 4, 4);
|
||||
int flags = data.toUInt32BE(pos + 8);
|
||||
const int length = data.toUInt32BE(pos);
|
||||
const ByteVector name = data.mid(pos + 4, 4);
|
||||
const int flags = data.toUInt32BE(pos + 8);
|
||||
if(freeForm && i < 2) {
|
||||
if(i == 0 && name != "mean") {
|
||||
debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\"");
|
||||
@ -277,9 +275,9 @@ MP4::Tag::parseCovr(MP4::Atom *atom, TagLib::File *file)
|
||||
ByteVector data = file->readBlock(atom->length - 8);
|
||||
size_t pos = 0;
|
||||
while(pos < data.size()) {
|
||||
int length = data.toUInt32BE(pos);
|
||||
ByteVector name = data.mid(pos + 4, 4);
|
||||
int flags = data.toUInt32BE(pos + 8);
|
||||
const int length = data.toUInt32BE(pos);
|
||||
const ByteVector name = data.mid(pos + 4, 4);
|
||||
const int flags = data.toUInt32BE(pos + 8);
|
||||
if(name != "data") {
|
||||
debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\"");
|
||||
break;
|
||||
@ -575,7 +573,7 @@ MP4::Tag::updateOffsets(long delta, offset_t offset)
|
||||
}
|
||||
d->file->seek(atom->offset + 9);
|
||||
ByteVector data = d->file->readBlock(atom->length - 9);
|
||||
unsigned int flags = data.toUInt24BE(0);
|
||||
const uint flags = data.toUInt24BE(0);
|
||||
if(flags & 1) {
|
||||
long long o = data.toInt64BE(7);
|
||||
if(o > offset) {
|
||||
|
@ -293,7 +293,7 @@ void MPC::Properties::readSV7(const ByteVector &data)
|
||||
d->sampleFrames = d->totalFrames * 1152 - 576;
|
||||
}
|
||||
else {
|
||||
uint headerData = data.toUInt32LE(0);
|
||||
const uint headerData = data.toUInt32LE(0);
|
||||
|
||||
d->bitrate = (headerData >> 23) & 0x01ff;
|
||||
d->version = (headerData >> 11) & 0x03ff;
|
||||
|
@ -23,9 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_ZLIB
|
||||
#include <zlib.h>
|
||||
@ -711,7 +709,7 @@ void Frame::Header::setData(const ByteVector &data, uint version)
|
||||
// iTunes writes v2.4 tags with v2.3-like frame sizes
|
||||
if(d->frameSize > 127) {
|
||||
if(!isValidFrameID(data.mid(d->frameSize + 10, 4))) {
|
||||
unsigned int uintSize = data.toUInt32BE(4);
|
||||
const uint uintSize = data.toUInt32BE(4);
|
||||
if(isValidFrameID(data.mid(uintSize + 10, 4))) {
|
||||
d->frameSize = uintSize;
|
||||
}
|
||||
|
@ -23,9 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#include <tdebug.h>
|
||||
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#include <tbytevector.h>
|
||||
|
@ -251,7 +251,7 @@ void Ogg::FLAC::File::scan()
|
||||
return;
|
||||
}
|
||||
|
||||
d->streamInfoData = metadataHeader.mid(4,length);
|
||||
d->streamInfoData = metadataHeader.mid(4, length);
|
||||
|
||||
// Search through the remaining metadata
|
||||
|
||||
|
@ -118,7 +118,7 @@ void Opus::Properties::read()
|
||||
ByteVector data = d->file->packet(0);
|
||||
|
||||
// *Magic Signature*
|
||||
int pos = 8;
|
||||
uint pos = 8;
|
||||
|
||||
// *Version* (8 bits, unsigned)
|
||||
d->opusVersion = uchar(data.at(pos));
|
||||
@ -129,7 +129,7 @@ void Opus::Properties::read()
|
||||
pos += 1;
|
||||
|
||||
// *Pre-skip* (16 bits, unsigned, little endian)
|
||||
ushort preSkip = data.toUInt16LE(pos);
|
||||
const ushort preSkip = data.toUInt16LE(pos);
|
||||
pos += 2;
|
||||
|
||||
// *Input Sample Rate* (32 bits, unsigned, little endian)
|
||||
|
@ -142,7 +142,7 @@ void Ogg::Vorbis::Properties::read()
|
||||
|
||||
ByteVector data = d->file->packet(0);
|
||||
|
||||
int pos = 0;
|
||||
uint pos = 0;
|
||||
|
||||
if(data.mid(pos, 7) != vorbisSetupHeaderID) {
|
||||
debug("Ogg::Vorbis::Properties::read() -- invalid Ogg::Vorbis identification header");
|
||||
|
@ -354,7 +354,7 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
|
||||
// Next the number of fields in the comment vector.
|
||||
|
||||
uint commentFields = data.toUInt32LE(pos);
|
||||
const uint commentFields = data.toUInt32LE(pos);
|
||||
pos += 4;
|
||||
|
||||
if(commentFields > (data.size() - 8) / 4) {
|
||||
@ -366,7 +366,7 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
// Each comment field is in the format "KEY=value" in a UTF8 string and has
|
||||
// 4 bytes before the text starts that gives the length.
|
||||
|
||||
uint commentLength = data.toUInt32LE(pos);
|
||||
const uint commentLength = data.toUInt32LE(pos);
|
||||
pos += 4;
|
||||
|
||||
String comment = String(data.mid(pos, commentLength), String::UTF8);
|
||||
|
@ -48,7 +48,7 @@ static double ConvertFromIeeeExtended(const ByteVector &v, size_t offset)
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
const unsigned char *bytes = reinterpret_cast<const unsigned char*>(v.data() + offset);
|
||||
const uchar *bytes = reinterpret_cast<const uchar*>(v.data() + offset);
|
||||
double f;
|
||||
int expon;
|
||||
unsigned long hiMant, loMant;
|
||||
|
@ -161,6 +161,11 @@ void RIFF::File::setChunkData(uint i, const ByteVector &data)
|
||||
d->chunks[i].offset = d->chunks[i-1].offset + 8 + d->chunks[i-1].size + d->chunks[i-1].padding;
|
||||
}
|
||||
|
||||
void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data)
|
||||
{
|
||||
setChunkData(name, data, false);
|
||||
}
|
||||
|
||||
void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate)
|
||||
{
|
||||
if(d->chunks.size() == 0) {
|
||||
|
@ -102,17 +102,27 @@ namespace TagLib {
|
||||
*/
|
||||
void setChunkData(uint i, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Sets the data for the chunk \a name to \a data. If a chunk with the
|
||||
* given name already exists it will be overwritten, otherwise it will be
|
||||
* created after the existing chunks.
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
void setChunkData(const ByteVector &name, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Sets the data for the chunk \a name to \a data. If a chunk with the
|
||||
* given name already exists it will be overwritten, otherwise it will be
|
||||
* created after the existing chunks.
|
||||
*
|
||||
* \note If \a alwaysCreate is true, a new chunk is created regardless of
|
||||
* existence of chunk \a name. It should be used for only "LIST" chunks.
|
||||
* whether or not the chunk \a name exists. It should only be used for
|
||||
* "LIST" chunks.
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
void setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate = false);
|
||||
void setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate);
|
||||
|
||||
/*!
|
||||
* Removes the specified chunk.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002 - 2008 by Scott Wheeler
|
||||
copyright : (C) 2012 by Tsuda Kageyu
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
@ -84,17 +84,18 @@ ByteVector RIFF::Info::StringHandler::render(const String &s) const
|
||||
|
||||
RIFF::Info::Tag::Tag(const ByteVector &data) : TagLib::Tag()
|
||||
{
|
||||
d = new TagPrivate;
|
||||
parse(data);
|
||||
}
|
||||
|
||||
RIFF::Info::Tag::Tag() : TagLib::Tag()
|
||||
RIFF::Info::Tag::Tag()
|
||||
: TagLib::Tag()
|
||||
, d(new TagPrivate())
|
||||
{
|
||||
d = new TagPrivate;
|
||||
}
|
||||
|
||||
RIFF::Info::Tag::~Tag()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
String RIFF::Info::Tag::title() const
|
||||
@ -245,7 +246,7 @@ void RIFF::Info::Tag::parse(const ByteVector &data)
|
||||
{
|
||||
size_t p = 4;
|
||||
while(p < data.size()) {
|
||||
uint size = data.toUInt32LE(p + 4);
|
||||
const uint size = data.toUInt32LE(p + 4);
|
||||
d->fieldListMap[data.mid(p, 4)] = TagPrivate::stringHandler->parse(data.mid(p + 8, size));
|
||||
|
||||
p += ((size + 1) & ~1) + 8;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002 - 2008 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
copyright : (C) 2012 by Tsuda Kageyu
|
||||
email : tsuda.kageyu@gmail.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
@ -82,7 +82,7 @@ namespace TagLib {
|
||||
* 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 refering to unofficial documents
|
||||
* documents about it. So, this implementation is referring to unofficial documents
|
||||
* online and some applications' behaviors especially Windows Explorer.
|
||||
*/
|
||||
class TAGLIB_EXPORT Tag : public TagLib::Tag
|
||||
@ -119,6 +119,7 @@ namespace TagLib {
|
||||
virtual void setTrack(uint i);
|
||||
|
||||
virtual bool isEmpty() const;
|
||||
|
||||
/*
|
||||
* Gets the value of the field with the ID \a id.
|
||||
*/
|
||||
@ -129,7 +130,7 @@ namespace TagLib {
|
||||
* If the field does not exist, it is created.
|
||||
* If \s is empty, the field is removed.
|
||||
*
|
||||
* \note fieldId must be four-byte long pure ascii string. This function
|
||||
* \note fieldId must be four-byte long pure ASCII string. This function
|
||||
* performs nothing if fieldId is invalid.
|
||||
*/
|
||||
void setFieldText(const ByteVector &id, const String &s);
|
||||
|
27
taglib/toolkit/taglib.h
Executable file → Normal file
27
taglib/toolkit/taglib.h
Executable file → Normal file
@ -52,31 +52,24 @@
|
||||
# endif
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
# include <sys/types.h>
|
||||
|
||||
#endif
|
||||
|
||||
// Check the widths of integral types.
|
||||
|
||||
#if UCHAR_MAX != 255U
|
||||
# error TagLib assumes that char is 8-bit wide.
|
||||
#if SIZEOF_SHORT != 2
|
||||
# error TagLib requires that short is 16-bit wide.
|
||||
#endif
|
||||
|
||||
#if USHRT_MAX != 65535U
|
||||
# error TagLib assumes that short is 16-bit wide.
|
||||
#if SIZEOF_INT != 4
|
||||
# error TagLib requires that int is 32-bit wide.
|
||||
#endif
|
||||
|
||||
#if UINT_MAX != 4294967295U
|
||||
# error TagLib assumes that int is 32-bit wide.
|
||||
#if SIZEOF_LONGLONG != 8
|
||||
# error TagLib requires that long long is 64-bit wide.
|
||||
#endif
|
||||
|
||||
#if !defined(ULLONG_MAX) && !defined(ULONGLONG_MAX) && !defined(ULONG_LONG_MAX)
|
||||
# error TagLib assumes that long long is 64-bit wide.
|
||||
#elif defined(ULLONG_MAX) && ULLONG_MAX != 18446744073709551615ULL
|
||||
# error TagLib assumes that long long is 64-bit wide.
|
||||
#elif defined(ULONGLONG_MAX) && ULONGLONG_MAX != 18446744073709551615ULL
|
||||
# error TagLib assumes that long long is 64-bit wide.
|
||||
#elif defined(ULONG_LONG_MAX) && ULONG_LONG_MAX != 18446744073709551615ULL
|
||||
# error TagLib assumes that long long is 64-bit wide.
|
||||
#if SIZEOF_WCHAR_T < 2
|
||||
# error TagLib requires that wchar_t is sufficient to store a UTF-16 char.
|
||||
#endif
|
||||
|
||||
// Optimized byte swap functions.
|
||||
@ -162,7 +155,11 @@ namespace TagLib {
|
||||
* Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3)
|
||||
* so I'm providing something here that should be constant.
|
||||
*/
|
||||
#ifdef HAVE_STD_WSTRING
|
||||
typedef std::wstring wstring;
|
||||
#else
|
||||
typedef std::basic_string<wchar> wstring;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -24,9 +24,10 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tbytevector.h"
|
||||
|
||||
@ -493,11 +494,8 @@ const char *ByteVector::data() const
|
||||
|
||||
ByteVector ByteVector::mid(size_t index, size_t length) const
|
||||
{
|
||||
if(index > size())
|
||||
index = size();
|
||||
|
||||
if(length > size() - index)
|
||||
length = size() - index;
|
||||
index = std::min(index, size());
|
||||
length = std::min(length, size() - index);
|
||||
|
||||
return ByteVector(*this, index, length);
|
||||
}
|
||||
@ -793,7 +791,6 @@ long long ByteVector::toInt64BE(size_t offset) const
|
||||
return static_cast<long long>(toNumber<ulonglong, 8, BigEndian>(*this, offset));
|
||||
}
|
||||
|
||||
|
||||
const char &ByteVector::operator[](size_t index) const
|
||||
{
|
||||
return DATA(d)[d->offset + index];
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "tbytevectorlist.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
@ -40,48 +40,79 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
// For Windows
|
||||
// Using Win32 native API instead of standard C file I/O to reduce the resource consumption.
|
||||
|
||||
typedef FileName FileNameHandle;
|
||||
|
||||
// Using native file handles instead of file descriptors for reducing the resource consumption.
|
||||
|
||||
const HANDLE InvalidFile = INVALID_HANDLE_VALUE;
|
||||
# define INVALID_FILE INVALID_HANDLE_VALUE
|
||||
|
||||
HANDLE openFile(const FileName &path, bool readOnly)
|
||||
{
|
||||
DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
|
||||
const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
|
||||
|
||||
if(!path.wstr().empty())
|
||||
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
else
|
||||
else if(!path.str().empty())
|
||||
return CreateFileA(path.str().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
else
|
||||
return INVALID_FILE;
|
||||
}
|
||||
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, HANDLE stream)
|
||||
{
|
||||
DWORD readLen;
|
||||
ReadFile(stream, ptr, static_cast<DWORD>(size * nmemb), &readLen, NULL);
|
||||
|
||||
return (readLen / size);
|
||||
if(ReadFile(stream, ptr, size * nmemb, &readLen, NULL))
|
||||
return (readLen / size);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, HANDLE stream)
|
||||
{
|
||||
DWORD writtenLen;
|
||||
WriteFile(stream, ptr, static_cast<DWORD>(size * nmemb), &writtenLen, NULL);
|
||||
|
||||
return writtenLen;
|
||||
if(WriteFile(stream, ptr, size * nmemb, &writtenLen, NULL))
|
||||
return (writtenLen / size);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
# if _DEBUG
|
||||
|
||||
// Convert a string in a local encoding into a UTF-16 string.
|
||||
|
||||
// This function should only be used to generate an error message.
|
||||
// In actual use, file names in local encodings are passed to CreateFileA()
|
||||
// without any conversions.
|
||||
|
||||
String fileNameToString(const FileName &name)
|
||||
{
|
||||
if(!name.wstr().empty()) {
|
||||
return String(name.wstr());
|
||||
}
|
||||
else if(!name.str().empty()) {
|
||||
const int len = MultiByteToWideChar(CP_ACP, 0, name.str().c_str(), -1, NULL, 0);
|
||||
if(len == 0)
|
||||
return String::null;
|
||||
|
||||
wstring wstr(len, L'\0');
|
||||
MultiByteToWideChar(CP_ACP, 0, name.str().c_str(), -1, &wstr[0], len);
|
||||
|
||||
return String(wstr);
|
||||
}
|
||||
else {
|
||||
return String::null;
|
||||
}
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
// For non-Windows
|
||||
|
||||
FILE *const InvalidFile = 0;
|
||||
# define INVALID_FILE 0
|
||||
|
||||
struct FileNameHandle : public std::string
|
||||
{
|
||||
@ -100,7 +131,7 @@ namespace {
|
||||
class FileStream::FileStreamPrivate
|
||||
{
|
||||
public:
|
||||
FileStreamPrivate(FileName fileName, bool openReadOnly);
|
||||
FileStreamPrivate(const FileName &fileName, bool openReadOnly);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@ -128,8 +159,8 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
FileStream::FileStreamPrivate::FileStreamPrivate(FileName fileName, bool openReadOnly) :
|
||||
file(InvalidFile),
|
||||
FileStream::FileStreamPrivate::FileStreamPrivate(const FileName &fileName, bool openReadOnly) :
|
||||
file(INVALID_FILE),
|
||||
name(fileName),
|
||||
readOnly(true),
|
||||
size(0)
|
||||
@ -139,23 +170,22 @@ FileStream::FileStreamPrivate::FileStreamPrivate(FileName fileName, bool openRea
|
||||
if(!openReadOnly)
|
||||
file = openFile(name, false);
|
||||
|
||||
if(file != InvalidFile)
|
||||
if(file != INVALID_FILE)
|
||||
readOnly = false;
|
||||
else
|
||||
file = openFile(name, true);
|
||||
|
||||
if(file == InvalidFile) {
|
||||
#ifdef _WIN32
|
||||
String n;
|
||||
if(!name.wstr().empty())
|
||||
n = name.wstr();
|
||||
else
|
||||
n = name.str();
|
||||
#else
|
||||
String n(name);
|
||||
#endif // DEBUG
|
||||
if(file == INVALID_FILE)
|
||||
{
|
||||
# ifdef _WIN32
|
||||
|
||||
debug("Could not open file " + n);
|
||||
debug("Could not open file " + fileNameToString(name));
|
||||
|
||||
# else
|
||||
|
||||
debug("Could not open file " + String((const char *) name));
|
||||
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,20 +194,20 @@ FileStream::FileStreamPrivate::FileStreamPrivate(FileName fileName, bool openRea
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FileStream::FileStream(FileName file, bool openReadOnly)
|
||||
: d(new FileStreamPrivate(file, openReadOnly))
|
||||
{
|
||||
d = new FileStreamPrivate(file, openReadOnly);
|
||||
}
|
||||
|
||||
FileStream::~FileStream()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
if(d->file)
|
||||
if(isOpen())
|
||||
CloseHandle(d->file);
|
||||
|
||||
#else
|
||||
|
||||
if(d->file)
|
||||
if(isOpen())
|
||||
fclose(d->file);
|
||||
|
||||
#endif
|
||||
@ -192,8 +222,8 @@ FileName FileStream::name() const
|
||||
|
||||
ByteVector FileStream::readBlock(size_t length)
|
||||
{
|
||||
if(!d->file) {
|
||||
debug("FileStream::readBlock() -- Invalid File");
|
||||
if(!isOpen()) {
|
||||
debug("File::readBlock() -- invalid file.");
|
||||
return ByteVector::null;
|
||||
}
|
||||
|
||||
@ -211,11 +241,13 @@ ByteVector FileStream::readBlock(size_t length)
|
||||
|
||||
void FileStream::writeBlock(const ByteVector &data)
|
||||
{
|
||||
if(!d->file)
|
||||
if(!isOpen()) {
|
||||
debug("File::writeBlock() -- invalid file.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(d->readOnly) {
|
||||
debug("File::writeBlock() -- attempted to write to a file that is not writable");
|
||||
if(readOnly()) {
|
||||
debug("File::writeBlock() -- read only file.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -224,8 +256,15 @@ void FileStream::writeBlock(const ByteVector &data)
|
||||
|
||||
void FileStream::insert(const ByteVector &data, offset_t start, size_t replace)
|
||||
{
|
||||
if(!d->file)
|
||||
if(!isOpen()) {
|
||||
debug("File::insert() -- invalid file.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(readOnly()) {
|
||||
debug("File::insert() -- read only file.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(data.size() == replace) {
|
||||
seek(start);
|
||||
@ -325,8 +364,10 @@ void FileStream::insert(const ByteVector &data, offset_t start, size_t replace)
|
||||
|
||||
void FileStream::removeBlock(offset_t start, size_t length)
|
||||
{
|
||||
if(!d->file)
|
||||
if(!isOpen()) {
|
||||
debug("File::removeBlock() -- invalid file.");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bufferLength = FileStreamPrivate::bufferSize;
|
||||
|
||||
@ -362,13 +403,13 @@ bool FileStream::readOnly() const
|
||||
|
||||
bool FileStream::isOpen() const
|
||||
{
|
||||
return (d->file != NULL);
|
||||
return (d->file != INVALID_FILE);
|
||||
}
|
||||
|
||||
void FileStream::seek(offset_t offset, Position p)
|
||||
{
|
||||
if(!d->file) {
|
||||
debug("FileStream::seek() -- trying to seek in a file that isn't opened.");
|
||||
if(!isOpen()) {
|
||||
debug("File::seek() -- invalid file.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -390,9 +431,10 @@ void FileStream::seek(offset_t offset, Position p)
|
||||
return;
|
||||
}
|
||||
|
||||
LARGE_INTEGER largeOffset = {};
|
||||
largeOffset.QuadPart = offset;
|
||||
SetFilePointerEx(d->file, largeOffset, nullptr, whence);
|
||||
SetFilePointer(d->file, offset, NULL, whence);
|
||||
if(GetLastError() != NO_ERROR) {
|
||||
debug("File::seek() -- Failed to set the file size.");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@ -442,12 +484,14 @@ offset_t FileStream::tell() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
const LARGE_INTEGER largeOffset = {};
|
||||
LARGE_INTEGER newPointer;
|
||||
|
||||
SetFilePointerEx(d->file, largeOffset, &newPointer, FILE_CURRENT);
|
||||
|
||||
return newPointer.QuadPart;
|
||||
const DWORD position = SetFilePointer(d->file, 0, NULL, FILE_CURRENT);
|
||||
if(GetLastError() == NO_ERROR) {
|
||||
return static_cast<long>(position);
|
||||
}
|
||||
else {
|
||||
debug("File::tell() -- Failed to get the file pointer.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@ -466,13 +510,30 @@ offset_t FileStream::tell() const
|
||||
|
||||
offset_t FileStream::length()
|
||||
{
|
||||
if(!isOpen()) {
|
||||
debug("File::length() -- invalid file.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Do some caching in case we do multiple calls.
|
||||
|
||||
if(d->size > 0)
|
||||
return d->size;
|
||||
|
||||
if(!d->file)
|
||||
#ifdef _WIN32
|
||||
|
||||
const DWORD fileSize = GetFileSize(d->file, NULL);
|
||||
if(GetLastError() == NO_ERROR) {
|
||||
d->size = static_cast<ulong>(fileSize);
|
||||
return d->size;
|
||||
}
|
||||
else {
|
||||
debug("File::length() -- Failed to get the file size.");
|
||||
d->size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const offset_t currentPosition = tell();
|
||||
|
||||
@ -483,6 +544,8 @@ offset_t FileStream::length()
|
||||
|
||||
d->size = endPosition;
|
||||
return endPosition;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -493,14 +556,15 @@ void FileStream::truncate(offset_t length)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
const offset_t currentPosition = tell();
|
||||
const offset_t currentPos = tell();
|
||||
|
||||
seek(length);
|
||||
BOOL set = SetEndOfFile(d->file);
|
||||
if(!set) {
|
||||
debug("FileStream::truncate() -- Coundn't truncate the file.");
|
||||
SetEndOfFile(d->file);
|
||||
if(GetLastError() != NO_ERROR) {
|
||||
debug("File::truncate() -- Failed to truncate the file.");
|
||||
}
|
||||
seek(currentPosition);
|
||||
|
||||
seek(currentPos);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -27,6 +27,87 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// MSVC 2008 or later can't produce the binary for Win9x.
|
||||
#if !defined(_MSC_VER) || (_MSC_VER < 1500)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Determines whether or not the running system is WinNT.
|
||||
// In other words, whether the system supports Unicode.
|
||||
|
||||
bool isWinNT()
|
||||
{
|
||||
OSVERSIONINFOA ver = {};
|
||||
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
||||
if(GetVersionExA(&ver)) {
|
||||
return (ver.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool IsWinNT = isWinNT();
|
||||
|
||||
// Converts a UTF-16 string into a local encoding.
|
||||
|
||||
std::string unicodeToAnsi(const std::wstring &wstr)
|
||||
{
|
||||
const int len = WideCharToMultiByte(CP_ACP, 0, &wstr[0], -1, NULL, 0, NULL, NULL);
|
||||
if(len == 0)
|
||||
return std::string();
|
||||
|
||||
std::string str(len, '\0');
|
||||
WideCharToMultiByte(CP_ACP, 0, &wstr[0], -1, &str[0], len, NULL, NULL);
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// If WinNT, stores a Unicode string into m_wname directly.
|
||||
// If Win9x, converts and stores it into m_name to avoid calling Unicode version functions.
|
||||
|
||||
FileName::FileName(const wchar_t *name)
|
||||
: m_wname(IsWinNT ? name : L"")
|
||||
, m_name(IsWinNT ? "" : unicodeToAnsi(name))
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
FileName::FileName(const wchar_t *name)
|
||||
: m_wname(name)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FileName::FileName(const char *name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
FileName::FileName(const FileName &name)
|
||||
: m_wname(name.m_wname)
|
||||
, m_name(name.m_name)
|
||||
{
|
||||
}
|
||||
|
||||
const std::wstring &FileName::wstr() const
|
||||
{
|
||||
return m_wname;
|
||||
}
|
||||
|
||||
const std::string &FileName::str() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -39,14 +39,16 @@ namespace TagLib {
|
||||
class TAGLIB_EXPORT FileName
|
||||
{
|
||||
public:
|
||||
FileName(const wchar_t *name) : m_wname(name) {}
|
||||
FileName(const char *name) : m_name(name) {}
|
||||
FileName(const wchar_t *name);
|
||||
FileName(const char *name);
|
||||
|
||||
const std::wstring &wstr() const { return m_wname; }
|
||||
const std::string &str() const { return m_name; }
|
||||
FileName(const FileName &name);
|
||||
|
||||
const std::wstring &wstr() const;
|
||||
const std::string &str() const;
|
||||
|
||||
private:
|
||||
const std::string m_name;
|
||||
const std::string m_name;
|
||||
const std::wstring m_wname;
|
||||
};
|
||||
#else
|
||||
|
@ -23,10 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <config.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace TagLib {
|
||||
|
@ -23,9 +23,7 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <config.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
|
@ -26,9 +26,7 @@
|
||||
#ifndef TAGLIB_REFCOUNTPTR_H
|
||||
#define TAGLIB_REFCOUNTPTR_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include "config.h"
|
||||
|
||||
#if defined(HAVE_STD_SHARED_PTR)
|
||||
# include <memory>
|
||||
|
@ -25,21 +25,20 @@
|
||||
|
||||
// This class assumes that std::basic_string<T> has a contiguous and null-terminated buffer.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "tstring.h"
|
||||
#include "tdebug.h"
|
||||
#include "tstringlist.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CODECVT
|
||||
// x86 CPUs are alignment-tolerant or allow pointer casts from smaller types to larger types.
|
||||
#if defined(__i386__) || defined(_M_IX86) || defined(__amd64) || defined(__amd64__) \
|
||||
|| defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define TAGLIB_ALIGNMENT_TOLERANT 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STD_CODECVT
|
||||
# include <codecvt>
|
||||
namespace {
|
||||
typedef std::codecvt_utf8_utf16<wchar_t> utf8_utf16_t;
|
||||
}
|
||||
#else
|
||||
# include "unicode.h"
|
||||
#endif
|
||||
@ -63,6 +62,98 @@ namespace
|
||||
{
|
||||
return (c1 << 8) | c2;
|
||||
}
|
||||
|
||||
void UTF16toUTF8(const wchar_t *src, size_t srcLength, char *dst, size_t dstLength)
|
||||
{
|
||||
#ifdef HAVE_STD_CODECVT
|
||||
|
||||
typedef std::codecvt_utf8_utf16<wchar_t> utf8_utf16_t;
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
const wchar_t *srcBegin = src;
|
||||
const wchar_t *srcEnd = srcBegin + srcLength;
|
||||
|
||||
char *dstBegin = dst;
|
||||
char *dstEnd = dstBegin + dstLength;
|
||||
|
||||
std::mbstate_t st;
|
||||
const wchar_t *source;
|
||||
char *target;
|
||||
memset(&st, 0, sizeof(st));
|
||||
std::codecvt_base::result result = utf8_utf16_t().out(
|
||||
st, srcBegin, srcEnd, source, dstBegin, dstEnd, target);
|
||||
|
||||
if(result != utf8_utf16_t::ok) {
|
||||
debug("String::copyFromUTF8() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
using namespace Unicode;
|
||||
using namespace TagLib;
|
||||
|
||||
const Unicode::UTF16 *srcBegin = src;
|
||||
const Unicode::UTF16 *srcEnd = srcBegin + srcLength;
|
||||
|
||||
Unicode::UTF8 *dstBegin = reinterpret_cast<Unicode::UTF8*>(dst);
|
||||
Unicode::UTF8 *dstEnd = dstBegin + dstLength;
|
||||
|
||||
Unicode::ConversionResult result = Unicode::ConvertUTF16toUTF8(
|
||||
&srcBegin, srcEnd, &dstBegin, dstEnd, Unicode::lenientConversion);
|
||||
|
||||
if(result != Unicode::conversionOK) {
|
||||
debug("String::to8Bit() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void UTF8toUTF16(const char *src, size_t srcLength, wchar_t *dst, size_t dstLength)
|
||||
{
|
||||
#ifdef HAVE_STD_CODECVT
|
||||
|
||||
typedef std::codecvt_utf8_utf16<wchar_t> utf8_utf16_t;
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
const char *srcBegin = src;
|
||||
const char *srcEnd = srcBegin + srcLength;
|
||||
|
||||
wchar_t *dstBegin = dst;
|
||||
wchar_t *dstEnd = dstBegin + dstLength;
|
||||
|
||||
std::mbstate_t st;
|
||||
const char *source;
|
||||
wchar_t *target;
|
||||
memset(&st, 0, sizeof(st));
|
||||
std::codecvt_base::result result = utf8_utf16_t().in(
|
||||
st, srcBegin, srcEnd, source, dstBegin, dstEnd, target);
|
||||
|
||||
if(result != utf8_utf16_t::ok) {
|
||||
debug("String::copyFromUTF8() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
using namespace Unicode;
|
||||
using namespace TagLib;
|
||||
|
||||
const Unicode::UTF8 *srcBegin = reinterpret_cast<const Unicode::UTF8*>(src);
|
||||
const Unicode::UTF8 *srcEnd = srcBegin + srcLength;
|
||||
|
||||
Unicode::UTF16 *dstBegin = dst;
|
||||
Unicode::UTF16 *dstEnd = dstBegin + dstLength;
|
||||
|
||||
Unicode::ConversionResult result = Unicode::ConvertUTF8toUTF16(
|
||||
&srcBegin, srcEnd, &dstBegin, dstEnd, Unicode::lenientConversion);
|
||||
|
||||
if(result != Unicode::conversionOK) {
|
||||
debug("String::copyFromUTF8() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
namespace TagLib {
|
||||
@ -87,6 +178,11 @@ public:
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
StringPrivate(size_t n, wchar_t c)
|
||||
: data(n, c)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* Stores string in UTF-16. The byte order depends on the CPU endian.
|
||||
@ -180,14 +276,10 @@ String::String(wchar_t c, Type t)
|
||||
}
|
||||
|
||||
String::String(char c, Type t)
|
||||
: d(new StringPrivate())
|
||||
: d(new StringPrivate(1, static_cast<uchar>(c)))
|
||||
{
|
||||
if(t == Latin1 || t == UTF8) {
|
||||
d->data.resize(1);
|
||||
d->data[0] = static_cast<uchar>(c);
|
||||
}
|
||||
else {
|
||||
debug("String::String() -- A char should not contain UTF16.");
|
||||
if(t != Latin1 && t != UTF8) {
|
||||
debug("String::String() -- A char should not contain UTF16.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,34 +319,7 @@ std::string String::to8Bit(bool unicode) const
|
||||
else {
|
||||
s.resize(d->data.size() * 4 + 1);
|
||||
|
||||
#ifdef HAVE_CODECVT
|
||||
|
||||
std::mbstate_t st = 0;
|
||||
const wchar_t *source;
|
||||
char *target;
|
||||
std::codecvt_base::result result = utf8_utf16_t().out(
|
||||
st, &d->data[0], &d->data[d->data.size()], source, &s[0], &s[s.size()], target);
|
||||
|
||||
if(result != utf8_utf16_t::ok) {
|
||||
debug("String::copyFromUTF8() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const Unicode::UTF16 *source = &d->data[0];
|
||||
Unicode::UTF8 *target = reinterpret_cast<Unicode::UTF8*>(&s[0]);
|
||||
|
||||
Unicode::ConversionResult result = Unicode::ConvertUTF16toUTF8(
|
||||
&source, source + d->data.size(),
|
||||
&target, target + s.size(),
|
||||
Unicode::lenientConversion);
|
||||
|
||||
if(result != Unicode::conversionOK) {
|
||||
debug("String::to8Bit() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
UTF16toUTF8(&d->data[0], d->data.size(), &s[0], s.size());
|
||||
s.resize(::strlen(s.c_str()));
|
||||
}
|
||||
|
||||
@ -398,34 +463,7 @@ ByteVector String::data(Type t) const
|
||||
{
|
||||
ByteVector v(size() * 4 + 1, 0);
|
||||
|
||||
#ifdef HAVE_CODECVT
|
||||
|
||||
std::mbstate_t st = 0;
|
||||
const wchar_t *source;
|
||||
char *target;
|
||||
std::codecvt_base::result result = utf8_utf16_t().out(
|
||||
st, &d->data[0], &d->data[d->data.size()], source, v.data(), v.data() + v.size(), target);
|
||||
|
||||
if(result != utf8_utf16_t::ok) {
|
||||
debug("String::data() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const Unicode::UTF16 *source = &d->data[0];
|
||||
Unicode::UTF8 *target = reinterpret_cast<Unicode::UTF8*>(v.data());
|
||||
|
||||
Unicode::ConversionResult result = Unicode::ConvertUTF16toUTF8(
|
||||
&source, source + d->data.size(),
|
||||
&target, target + v.size(),
|
||||
Unicode::lenientConversion);
|
||||
|
||||
if(result != Unicode::conversionOK) {
|
||||
debug("String::data() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
UTF16toUTF8(&d->data[0], d->data.size(), v.data(), v.size());
|
||||
v.resize(::strlen(v.data()));
|
||||
|
||||
return v;
|
||||
@ -703,19 +741,13 @@ String &String::operator=(const wchar_t *s)
|
||||
|
||||
String &String::operator=(char c)
|
||||
{
|
||||
d.reset(new StringPrivate());
|
||||
d->data.resize(1);
|
||||
d->data[0] = static_cast<uchar>(c);
|
||||
|
||||
d.reset(new StringPrivate(1, static_cast<uchar>(c)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator=(wchar_t c)
|
||||
{
|
||||
d.reset(new StringPrivate());
|
||||
d->data.resize(1);
|
||||
d->data[0] = c;
|
||||
|
||||
d.reset(new StringPrivate(1, c));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -769,34 +801,7 @@ void String::copyFromUTF8(const char *s, size_t length)
|
||||
{
|
||||
d->data.resize(length);
|
||||
|
||||
#ifdef HAVE_CODECVT
|
||||
|
||||
std::mbstate_t st = 0;
|
||||
const char *source;
|
||||
wchar_t *target;
|
||||
std::codecvt_base::result result = utf8_utf16_t().in(
|
||||
st, s, s + length, source, &d->data[0], &d->data[d->data.size()], target);
|
||||
|
||||
if(result != utf8_utf16_t::ok) {
|
||||
debug("String::copyFromUTF8() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const Unicode::UTF8 *source = reinterpret_cast<const Unicode::UTF8 *>(s);
|
||||
Unicode::UTF16 *target = &d->data[0];
|
||||
|
||||
Unicode::ConversionResult result = Unicode::ConvertUTF8toUTF16(
|
||||
&source, source + length,
|
||||
&target, target + length,
|
||||
Unicode::lenientConversion);
|
||||
|
||||
if(result != Unicode::conversionOK) {
|
||||
debug("String::copyFromUTF8() - Unicode conversion error.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
UTF8toUTF16(s, length, &d->data[0], d->data.size());
|
||||
d->data.resize(::wcslen(d->data.c_str()));
|
||||
}
|
||||
|
||||
@ -824,20 +829,32 @@ void String::copyFromUTF16(const wchar_t *s, size_t length, Type t)
|
||||
|
||||
if(swap) {
|
||||
for(size_t i = 0; i < length; ++i)
|
||||
d->data[i] = byteSwap(static_cast<unsigned short>(s[i]));
|
||||
d->data[i] = byteSwap(static_cast<ushort>(s[i]));
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t sizeOfWcharT>
|
||||
void String::internalCopyFromUTF16(const char *s, size_t length, Type t)
|
||||
void String::copyFromUTF16(const char *s, size_t length, Type t)
|
||||
{
|
||||
// Non specialized version. Used where sizeof(wchar_t) != 2.
|
||||
#if SIZEOF_WCHAR_T == 2 && defined(TAGLIB_ALIGNMENT_TOLERANT)
|
||||
|
||||
copyFromUTF16(reinterpret_cast<const wchar_t*>(s), length / 2, t);
|
||||
|
||||
#else
|
||||
|
||||
bool swap;
|
||||
if(t == UTF16) {
|
||||
if(length >= 2 && *reinterpret_cast<const TagLib::ushort*>(s) == 0xfeff)
|
||||
if(length < 2) {
|
||||
debug("String::copyFromUTF16() - Invalid UTF16 string.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Uses memcpy instead of reinterpret_cast to avoid an alignment exception.
|
||||
ushort bom;
|
||||
::memcpy(&bom, s, 2);
|
||||
|
||||
if(bom == 0xfeff)
|
||||
swap = false; // Same as CPU endian. No need to swap bytes.
|
||||
else if(length >= 2 && *reinterpret_cast<const TagLib::ushort*>(s) == 0xfffe)
|
||||
else if(bom == 0xfffe)
|
||||
swap = true; // Not same as CPU endian. Need to swap bytes.
|
||||
else {
|
||||
debug("String::copyFromUTF16() - Invalid UTF16 string.");
|
||||
@ -855,19 +872,8 @@ void String::internalCopyFromUTF16(const char *s, size_t length, Type t)
|
||||
d->data[i] = swap ? combine(*s, *(s + 1)) : combine(*(s + 1), *s);
|
||||
s += 2;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void String::internalCopyFromUTF16<2>(const char *s, size_t length, Type t)
|
||||
{
|
||||
// Specialized version for where sizeof(wchar_t) == 2.
|
||||
|
||||
copyFromUTF16(reinterpret_cast<const wchar_t*>(s), length / 2, t);
|
||||
}
|
||||
|
||||
void String::copyFromUTF16(const char *s, size_t length, Type t)
|
||||
{
|
||||
internalCopyFromUTF16<sizeof(wchar_t)>(s, length, t);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TAGLIB_LITTLE_ENDIAN
|
||||
|
@ -511,9 +511,6 @@ namespace TagLib {
|
||||
* \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);
|
||||
|
||||
template <size_t sizeOfWcharT>
|
||||
void internalCopyFromUTF16(const char *s, size_t length, Type t);
|
||||
|
||||
/*!
|
||||
* Indicates which byte order of UTF-16 is used to store strings internally.
|
||||
|
@ -23,10 +23,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "tstringlist.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
@ -62,6 +62,13 @@ public:
|
||||
String latin = "Jos\xe9 Carlos";
|
||||
CPPUNIT_ASSERT(strcmp(latin.toCString(true), "José Carlos") == 0);
|
||||
|
||||
String c;
|
||||
c = "1";
|
||||
CPPUNIT_ASSERT(c == L"1");
|
||||
|
||||
c = L'\u4E00';
|
||||
CPPUNIT_ASSERT(c == L"\u4E00");
|
||||
|
||||
String unicode2(unicode.to8Bit(true), String::UTF8);
|
||||
CPPUNIT_ASSERT(unicode == unicode2);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user