Support large files over 2GB on Windows (#1089)

Backport of 4dcf0b41c6
b01f45e141
https://github.com/taglib/taglib/pull/77

Tested with files larger than 2GB which have been created using

sox -n -r 44100 -C 320 large.mp3 synth 58916 sine 440 channels 2
sox -n -r 44100 -C 0 large.flac synth 25459 sine 440 channels 2
sox -n -r 44100 -C 10 large.ogg synth 229806 sine 440 channels 2
sox -n -r 44100 large.wav synth 6692 sine 440 channels 2
ffmpeg -f lavfi -i "sine=frequency=440:duration=244676" -y large.m4a

The only file which was readable with the tagreader example
before this commit was large.ogg. The problem is that long on
Windows is only 32-bit (also in LLP64 data model of 64-bit
compilation target) and all the file offsets using long are
too small for large files. Now long is replaced by offset_t
(defined to be long long on Windows and off_t on UNIX) for such
cases and some unsigned long are now size_t, which has the
correct size even on Windows.
This commit is contained in:
Urs Fleisch
2020-04-19 11:13:55 +02:00
parent bc915f5dc8
commit ca8c2e07ec
72 changed files with 378 additions and 364 deletions

View File

@ -58,8 +58,8 @@ public:
Properties *properties;
ByteVector streamInfoData;
ByteVector xiphCommentData;
long streamStart;
long streamLength;
offset_t streamStart;
offset_t streamLength;
bool scanned;
bool hasXiphComment;
@ -206,7 +206,7 @@ ByteVector Ogg::FLAC::File::xiphCommentData()
return d->xiphCommentData;
}
long Ogg::FLAC::File::streamLength()
offset_t Ogg::FLAC::File::streamLength()
{
scan();
return d->streamLength;
@ -223,7 +223,7 @@ void Ogg::FLAC::File::scan()
return;
int ipacket = 0;
long overhead = 0;
offset_t overhead = 0;
ByteVector metadataHeader = packet(ipacket);
if(metadataHeader.isEmpty())

View File

@ -134,7 +134,7 @@ namespace TagLib {
* Returns the length of the audio-stream, used by FLAC::Properties for
* calculating the bitrate.
*/
long streamLength();
offset_t streamLength();
/*!
* Returns whether or not the file on disk actually has a XiphComment.

View File

@ -129,7 +129,7 @@ void Ogg::File::setPacket(unsigned int i, const ByteVector &p)
const Ogg::PageHeader *Ogg::File::firstPageHeader()
{
if(!d->firstPageHeader) {
const long firstPageHeaderOffset = find("OggS");
const offset_t firstPageHeaderOffset = find("OggS");
if(firstPageHeaderOffset < 0)
return 0;
@ -142,7 +142,7 @@ const Ogg::PageHeader *Ogg::File::firstPageHeader()
const Ogg::PageHeader *Ogg::File::lastPageHeader()
{
if(!d->lastPageHeader) {
const long lastPageHeaderOffset = rfind("OggS");
const offset_t lastPageHeaderOffset = rfind("OggS");
if(lastPageHeaderOffset < 0)
return 0;
@ -192,7 +192,7 @@ bool Ogg::File::readPages(unsigned int i)
{
while(true) {
unsigned int packetIndex;
long offset;
offset_t offset;
if(d->pages.isEmpty()) {
packetIndex = 0;
@ -275,8 +275,8 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
for(it = pages.begin(); it != pages.end(); ++it)
data.append((*it)->render());
const unsigned long originalOffset = firstPage->fileOffset();
const unsigned long originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
const offset_t originalOffset = firstPage->fileOffset();
const offset_t originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
insert(data, originalOffset, originalLength);
@ -286,7 +286,7 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
= pages.back()->pageSequenceNumber() - lastPage->pageSequenceNumber();
if(numberOfNewPages != 0) {
long pageOffset = originalOffset + data.size();
offset_t pageOffset = originalOffset + data.size();
while(true) {
Page page(this, pageOffset);

View File

@ -37,14 +37,14 @@ using namespace TagLib;
class Ogg::Page::PagePrivate
{
public:
PagePrivate(File *f = 0, long pageOffset = -1) :
PagePrivate(File *f = 0, offset_t pageOffset = -1) :
file(f),
fileOffset(pageOffset),
header(f, pageOffset),
firstPacketIndex(-1) {}
File *file;
long fileOffset;
offset_t fileOffset;
PageHeader header;
int firstPacketIndex;
ByteVectorList packets;
@ -54,7 +54,7 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
Ogg::Page::Page(Ogg::File *file, long pageOffset) :
Ogg::Page::Page(Ogg::File *file, offset_t pageOffset) :
d(new PagePrivate(file, pageOffset))
{
}
@ -64,7 +64,7 @@ Ogg::Page::~Page()
delete d;
}
long Ogg::Page::fileOffset() const
offset_t Ogg::Page::fileOffset() const
{
return d->fileOffset;
}

View File

@ -55,14 +55,14 @@ namespace TagLib {
/*!
* Read an Ogg page from the \a file at the position \a pageOffset.
*/
Page(File *file, long pageOffset);
Page(File *file, offset_t pageOffset);
virtual ~Page();
/*!
* Returns the page's position within the file (in bytes).
*/
long fileOffset() const;
offset_t fileOffset() const;
/*!
* Returns a pointer to the header for this page. This pointer will become

View File

@ -66,7 +66,7 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) :
Ogg::PageHeader::PageHeader(Ogg::File *file, offset_t pageOffset) :
d(new PageHeaderPrivate())
{
if(file && pageOffset >= 0)
@ -225,7 +225,7 @@ ByteVector Ogg::PageHeader::render() const
// private members
////////////////////////////////////////////////////////////////////////////////
void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
void Ogg::PageHeader::read(Ogg::File *file, offset_t pageOffset)
{
file->seek(pageOffset);

View File

@ -52,7 +52,7 @@ namespace TagLib {
* create a page with no (and as such, invalid) data that must be set
* later.
*/
PageHeader(File *file = 0, long pageOffset = -1);
PageHeader(File *file = 0, offset_t pageOffset = -1);
/*!
* Deletes this instance of the PageHeader.
@ -219,7 +219,7 @@ namespace TagLib {
PageHeader(const PageHeader &);
PageHeader &operator=(const PageHeader &);
void read(Ogg::File *file, long pageOffset);
void read(Ogg::File *file, offset_t pageOffset);
ByteVector lacingValues() const;
class PageHeaderPrivate;

View File

@ -163,7 +163,7 @@ void Opus::Properties::read(File *file)
if(frameCount > 0) {
const double length = frameCount * 1000.0 / 48000.0;
long fileLengthWithoutOverhead = file->length();
offset_t fileLengthWithoutOverhead = file->length();
// Ignore the two mandatory header packets, see "3. Packet Organization"
// in https://tools.ietf.org/html/rfc7845.html
for (unsigned int i = 0; i < 2; ++i) {

View File

@ -182,7 +182,7 @@ void Speex::Properties::read(File *file)
if(frameCount > 0) {
const double length = frameCount * 1000.0 / d->sampleRate;
long fileLengthWithoutOverhead = file->length();
offset_t fileLengthWithoutOverhead = file->length();
// Ignore the two header packets, see "Ogg file format" in
// https://www.speex.org/docs/manual/speex-manual/node8.html
for (unsigned int i = 0; i < 2; ++i) {

View File

@ -186,7 +186,7 @@ void Vorbis::Properties::read(File *file)
if(frameCount > 0) {
const double length = frameCount * 1000.0 / d->sampleRate;
long fileLengthWithoutOverhead = file->length();
offset_t fileLengthWithoutOverhead = file->length();
// Ignore the three initial header packets, see "1.3.1. Decode Setup" in
// https://xiph.org/vorbis/doc/Vorbis_I_spec.html
for (unsigned int i = 0; i < 3; ++i) {