diff --git a/taglib/riff/rifffile.cpp b/taglib/riff/rifffile.cpp index a39fce61..979ec530 100644 --- a/taglib/riff/rifffile.cpp +++ b/taglib/riff/rifffile.cpp @@ -219,22 +219,24 @@ void RIFF::File::removeChunk(uint i) { if(i >= d->chunks.size()) return; - - removeBlock(d->chunks[i].offset - 8, d->chunks[i].size + 8); - d->chunks.erase(d->chunks.begin() + i); + + std::vector::iterator it = d->chunks.begin(); + std::advance(it, i); + + const uint removeSize = it->size + it->padding + 8; + removeBlock(it->offset - 8, removeSize); + it = d->chunks.erase(it); + + for(; it != d->chunks.end(); ++it) + it->offset -= removeSize; } void RIFF::File::removeChunk(const ByteVector &name) { - std::vector newChunks; - for(size_t i = 0; i < d->chunks.size(); ++i) { + for(int i = d->chunks.size() - 1; i >= 0; --i) { if(d->chunks[i].name == name) - removeBlock(d->chunks[i].offset - 8, d->chunks[i].size + 8); - else - newChunks.push_back(d->chunks[i]); + removeChunk(i); } - - d->chunks.swap(newChunks); } //////////////////////////////////////////////////////////////////////////////// diff --git a/taglib/riff/wav/wavfile.cpp b/taglib/riff/wav/wavfile.cpp index abecea35..c8d0578c 100644 --- a/taglib/riff/wav/wavfile.cpp +++ b/taglib/riff/wav/wavfile.cpp @@ -147,24 +147,20 @@ bool RIFF::WAV::File::save(TagTypes tags, bool stripOthers, int id3v2Version) strip(static_cast(AllTags & ~tags)); ID3v2::Tag *id3v2tag = d->tag.access(ID3v2Index, false); - if(!id3v2tag->isEmpty()) { - if(tags & ID3v2) { - setChunkData(d->tagChunkID, id3v2tag->render(id3v2Version)); - d->hasID3v2 = true; - } + if((tags & ID3v2) && !id3v2tag->isEmpty()) { + setChunkData(d->tagChunkID, id3v2tag->render(id3v2Version)); + d->hasID3v2 = true; } Info::Tag *infotag = d->tag.access(InfoIndex, false); - if(!infotag->isEmpty()) { - if(tags & Info) { - int chunkId = findInfoTagChunk(); - if(chunkId != -1) - setChunkData(chunkId, infotag->render()); - else - setChunkData("LIST", infotag->render(), true); + if((tags & Info) && !infotag->isEmpty()) { + int chunkId = findInfoTagChunk(); + if(chunkId != -1) + setChunkData(chunkId, infotag->render()); + else + setChunkData("LIST", infotag->render(), true); - d->hasInfo = true; - } + d->hasInfo = true; } return true; @@ -222,13 +218,17 @@ void RIFF::WAV::File::read(bool readProperties, Properties::ReadStyle properties void RIFF::WAV::File::strip(TagTypes tags) { - if(tags & ID3v2) + if(tags & ID3v2) { removeChunk(d->tagChunkID); + d->hasID3v2 = false; + } if(tags & Info){ TagLib::uint chunkId = findInfoTagChunk(); - if(chunkId != TagLib::uint(-1)) + if(chunkId != TagLib::uint(-1)) { removeChunk(chunkId); + d->hasInfo = false; + } } } diff --git a/tests/test_riff.cpp b/tests/test_riff.cpp index 8e120d06..9b07a7ce 100644 --- a/tests/test_riff.cpp +++ b/tests/test_riff.cpp @@ -20,12 +20,17 @@ public: TagLib::uint chunkDataSize(TagLib::uint i) { return RIFF::File::chunkDataSize(i); }; ByteVector chunkName(TagLib::uint i) { return RIFF::File::chunkName(i); }; ByteVector chunkData(TagLib::uint i) { return RIFF::File::chunkData(i); }; + void setChunkData(uint i, const ByteVector &data) { + RIFF::File::setChunkData(i, data); + } void setChunkData(const ByteVector &name, const ByteVector &data) { RIFF::File::setChunkData(name, data); }; virtual TagLib::Tag* tag() const { return 0; }; virtual TagLib::AudioProperties* audioProperties() const { return 0;}; virtual bool save() { return false; }; + void removeChunk(uint i) { RIFF::File::removeChunk(i); } + void removeChunk(const ByteVector &name) { RIFF::File::removeChunk(name); } }; class TestRIFF : public CppUnit::TestFixture @@ -35,6 +40,7 @@ class TestRIFF : public CppUnit::TestFixture CPPUNIT_TEST(testLastChunkAtEvenPosition); CPPUNIT_TEST(testLastChunkAtEvenPosition2); CPPUNIT_TEST(testLastChunkAtEvenPosition3); + CPPUNIT_TEST(testChunkOffset); CPPUNIT_TEST_SUITE_END(); public: @@ -193,6 +199,63 @@ public: delete f; } + void testChunkOffset() + { + ScopedFileCopy copy("empty", ".aiff"); + string filename = copy.fileName(); + + PublicRIFF *f = new PublicRIFF(filename.c_str()); + + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->chunkName(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->chunkName(1)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0026 + 8), f->chunkOffset(1)); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->chunkName(2)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x1728 + 8), f->chunkOffset(2)); + + const ByteVector data(0x400, ' '); + f->setChunkData("SSND", data); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0026 + 8), f->chunkOffset(1)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x042E + 8), f->chunkOffset(2)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4)); + f->seek(f->chunkOffset(1) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->readBlock(4)); + f->seek(f->chunkOffset(2) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + f->setChunkData(0, data); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0414 + 8), f->chunkOffset(1)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x081C + 8), f->chunkOffset(2)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4)); + f->seek(f->chunkOffset(1) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("SSND"), f->readBlock(4)); + f->seek(f->chunkOffset(2) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + f->removeChunk("SSND"); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x0414 + 8), f->chunkOffset(1)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("COMM"), f->readBlock(4)); + f->seek(f->chunkOffset(1) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + f->removeChunk(0); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(0x000C + 8), f->chunkOffset(0)); + + f->seek(f->chunkOffset(0) - 8); + CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->readBlock(4)); + + delete f; + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestRIFF); diff --git a/tests/test_wav.cpp b/tests/test_wav.cpp index d17ce2cc..518f37cf 100644 --- a/tests/test_wav.cpp +++ b/tests/test_wav.cpp @@ -14,6 +14,7 @@ class TestWAV : public CppUnit::TestFixture CPPUNIT_TEST_SUITE(TestWAV); CPPUNIT_TEST(testLength); CPPUNIT_TEST(testZeroSizeDataChunk); + CPPUNIT_TEST(testStripTags); CPPUNIT_TEST_SUITE_END(); public: @@ -31,6 +32,43 @@ public: CPPUNIT_ASSERT_EQUAL(false, f.isValid()); } + void testStripTags() + { + ScopedFileCopy copy("empty", ".wav"); + string filename = copy.fileName(); + + RIFF::WAV::File *f = new RIFF::WAV::File(filename.c_str()); + f->ID3v2Tag()->setTitle("test title"); + f->InfoTag()->setTitle("test title"); + f->save(); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(f->hasID3v2Tag()); + CPPUNIT_ASSERT(f->hasInfoTag()); + f->save(RIFF::WAV::File::ID3v2, true); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(f->hasID3v2Tag()); + CPPUNIT_ASSERT(!f->hasInfoTag()); + f->ID3v2Tag()->setTitle("test title"); + f->InfoTag()->setTitle("test title"); + f->save(); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(f->hasID3v2Tag()); + CPPUNIT_ASSERT(f->hasInfoTag()); + f->save(RIFF::WAV::File::Info, true); + delete f; + + f = new RIFF::WAV::File(filename.c_str()); + CPPUNIT_ASSERT(!f->hasID3v2Tag()); + CPPUNIT_ASSERT(f->hasInfoTag()); + delete f; + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestWAV);