]> granicus.if.org Git - taglib/commitdiff
Always update the global RIFF size when updating RIFF files.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Mon, 22 Feb 2016 13:27:18 +0000 (22:27 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Mon, 22 Feb 2016 13:27:18 +0000 (22:27 +0900)
taglib/riff/rifffile.cpp
taglib/riff/rifffile.h
tests/test_riff.cpp

index b1064cc1e0745c4fb69e38c5018b92e0d2be001a..bf52e19e4b73339d9251050b5dcdf73b522e70f1 100644 (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);
+}
index 52e7513483a642ac604770ccb1a933341c600d44..8425d8c92b4a7609594c0c518064b7cd392fb115 100644 (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;
     };
index 5223e9053b102ef530af17f5e9c06ada6b29ce92..f9a20dfb17212c7db481735f32be4b08a655d1d4 100644 (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);