Always update the global RIFF size when updating RIFF files.

This commit is contained in:
Tsuda Kageyu 2016-02-22 22:27:18 +09:00
parent c0a909b709
commit 520da50bc5
3 changed files with 43 additions and 12 deletions

View File

@ -48,11 +48,14 @@ class RIFF::File::FilePrivate
public:
FilePrivate(Endianness endianness) :
endianness(endianness),
size(0) {}
size(0),
sizeOffset(0) {}
const Endianness endianness;
unsigned int size;
long sizeOffset;
std::vector<Chunk> chunks;
};
@ -129,11 +132,6 @@ ByteVector RIFF::File::chunkData(unsigned int i)
void RIFF::File::setChunkData(unsigned int i, const ByteVector &data)
{
// First we update the global size
d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding);
insert(ByteVector::fromUInt(d->size, d->endianness == BigEndian), 4, 4);
// Now update the specific chunk
writeChunk(chunkName(i), data, d->chunks[i].offset - 8, d->chunks[i].size + d->chunks[i].padding + 8);
@ -145,6 +143,10 @@ void RIFF::File::setChunkData(unsigned int i, const ByteVector &data)
for(i++; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i-1].offset + 8 + d->chunks[i-1].size + d->chunks[i-1].padding;
// Update the global size.
updateGlobalSize();
}
void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data)
@ -177,11 +179,6 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bo
unsigned long offset = d->chunks.back().offset + d->chunks.back().size;
// First we update the global size
d->size += (offset & 1) + data.size() + 8;
insert(ByteVector::fromUInt(d->size, d->endianness == BigEndian), 4, 4);
// Now add the chunk to the file
writeChunk(name, data, offset, std::max<long>(0, length() - offset), (offset & 1) ? 1 : 0);
@ -200,6 +197,10 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bo
chunk.padding = (data.size() & 0x01) ? 1 : 0;
d->chunks.push_back(chunk);
// Update the global size.
updateGlobalSize();
}
void RIFF::File::removeChunk(unsigned int i)
@ -216,6 +217,10 @@ void RIFF::File::removeChunk(unsigned int i)
for(; it != d->chunks.end(); ++it)
it->offset -= removeSize;
// Update the global size.
updateGlobalSize();
}
void RIFF::File::removeChunk(const ByteVector &name)
@ -237,6 +242,7 @@ void RIFF::File::read()
seek(baseOffset + 4);
d->size = readBlock(4).toUInt(bigEndian);
d->sizeOffset = baseOffset + 4;
seek(baseOffset + 12);
@ -298,3 +304,13 @@ void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
}
insert(combined, offset, replace);
}
void RIFF::File::updateGlobalSize()
{
const Chunk first = d->chunks.front();
const Chunk last = d->chunks.back();
d->size = last.offset + last.size + last.padding - first.offset + 12;
const ByteVector data = ByteVector::fromUInt(d->size, d->endianness == BigEndian);
insert(data, d->sizeOffset, 4);
}

View File

@ -148,6 +148,11 @@ namespace TagLib {
unsigned long offset, unsigned long replace = 0,
unsigned int leadingPadding = 0);
/*!
* Update the global RIFF size based on the current internal structure.
*/
void updateGlobalSize();
class FilePrivate;
FilePrivate *d;
};

View File

@ -211,7 +211,7 @@ public:
CPPUNIT_ASSERT_EQUAL((unsigned int)(3), f.chunkDataSize(3));
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.chunkName(3));
CPPUNIT_ASSERT_EQUAL((unsigned int)(1), f.chunkPadding(3));
CPPUNIT_ASSERT_EQUAL((unsigned int)(4411 - 8), f.riffSize());
CPPUNIT_ASSERT_EQUAL((unsigned int)(4412 - 8), f.riffSize());
}
{
PublicRIFF f(filename.c_str());
@ -234,6 +234,8 @@ public:
PublicRIFF f(filename.c_str());
CPPUNIT_ASSERT_EQUAL(5928U, f.riffSize());
CPPUNIT_ASSERT_EQUAL(5936L, f.length());
CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f.chunkName(0));
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x000C + 8), f.chunkOffset(0));
CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f.chunkName(1));
@ -243,6 +245,8 @@ public:
const ByteVector data(0x400, ' ');
f.setChunkData("SSND", data);
CPPUNIT_ASSERT_EQUAL(1070U, f.riffSize());
CPPUNIT_ASSERT_EQUAL(1078L, f.length());
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x000C + 8), f.chunkOffset(0));
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x0026 + 8), f.chunkOffset(1));
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x042E + 8), f.chunkOffset(2));
@ -255,6 +259,8 @@ public:
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.readBlock(4));
f.setChunkData(0, data);
CPPUNIT_ASSERT_EQUAL(2076U, f.riffSize());
CPPUNIT_ASSERT_EQUAL(2084L, f.length());
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x000C + 8), f.chunkOffset(0));
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x0414 + 8), f.chunkOffset(1));
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x081C + 8), f.chunkOffset(2));
@ -267,6 +273,8 @@ public:
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.readBlock(4));
f.removeChunk("SSND");
CPPUNIT_ASSERT_EQUAL(1044U, f.riffSize());
CPPUNIT_ASSERT_EQUAL(1052L, f.length());
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x000C + 8), f.chunkOffset(0));
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x0414 + 8), f.chunkOffset(1));
@ -276,6 +284,8 @@ public:
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f.readBlock(4));
f.removeChunk(0);
CPPUNIT_ASSERT_EQUAL(12U, f.riffSize());
CPPUNIT_ASSERT_EQUAL(20L, f.length());
CPPUNIT_ASSERT_EQUAL((unsigned int)(0x000C + 8), f.chunkOffset(0));
f.seek(f.chunkOffset(0) - 8);