]> granicus.if.org Git - taglib/commitdiff
Avoid writing duplicate tags when saving ASF files.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Tue, 4 Aug 2015 04:50:09 +0000 (13:50 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Fri, 20 Nov 2015 04:48:25 +0000 (13:48 +0900)
Reduce memory reallocations and copies when saving ASF files.

taglib/asf/asffile.cpp
tests/test_asf.cpp

index 02fe83c3eaed32408e2ad2dc1b7bccab327a92bc..a5e5ea84b5e779d0e110e93d7910112b8abe0768 100644 (file)
@@ -50,7 +50,7 @@ public:
   class MetadataLibraryObject;
 
   FilePrivate():
-    size(0),
+    headerSize(0),
     tag(0),
     properties(0),
     contentDescriptionObject(0),
@@ -68,7 +68,7 @@ public:
     delete properties;
   }
 
-  unsigned long long size;
+  unsigned long long headerSize;
 
   ASF::Tag *tag;
   ASF::Properties *properties;
@@ -556,6 +556,10 @@ bool ASF::File::save()
     d->headerExtensionObject->objects.append(d->metadataLibraryObject);
   }
 
+  d->extendedContentDescriptionObject->attributeData.clear();
+  d->metadataObject->attributeData.clear();
+  d->metadataLibraryObject->attributeData.clear();
+
   const AttributeListMap allAttributes = d->tag->attributeListMap();
 
   for(AttributeListMap::ConstIterator it = allAttributes.begin(); it != allAttributes.end(); ++it) {
@@ -591,8 +595,14 @@ bool ASF::File::save()
     data.append((*it)->render(this));
   }
 
-  data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data;
-  insert(data, 0, (TagLib::ulong)d->size);
+  seek(16);
+  writeBlock(ByteVector::fromLongLong(data.size() + 30, false));
+  writeBlock(ByteVector::fromUInt(d->objects.size(), false));
+  writeBlock(ByteVector("\x01\x02", 2));
+
+  insert(data, 30, static_cast<ulong>(d->headerSize - 30));
+
+  d->headerSize = data.size() + 30;
 
   return true;
 }
@@ -617,7 +627,7 @@ void ASF::File::read()
   d->properties = new ASF::Properties();
 
   bool ok;
-  d->size = readQWORD(this, &ok);
+  d->headerSize = readQWORD(this, &ok);
   if(!ok) {
     setValid(false);
     return;
index 663ae5832a39cc2d06a8ccdcfd5632dd15e2c8c3..37614b0c8ffb26079bb055d1180104b83d03cc2c 100644 (file)
@@ -25,6 +25,7 @@ class TestASF : public CppUnit::TestFixture
   CPPUNIT_TEST(testSavePicture);
   CPPUNIT_TEST(testSaveMultiplePictures);
   CPPUNIT_TEST(testProperties);
+  CPPUNIT_TEST(testRepeatedSave);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -270,6 +271,21 @@ public:
     CPPUNIT_ASSERT_EQUAL(StringList("3"), tags["DISCNUMBER"]);
   }
 
+  void testRepeatedSave()
+  {
+    ScopedFileCopy copy("silence-1", ".wma");
+
+    {
+      ASF::File f(copy.fileName().c_str());
+      f.tag()->setTitle(std::string(128 * 1024, 'X').c_str());
+      f.save();
+      CPPUNIT_ASSERT_EQUAL(297578L, f.length());
+      f.tag()->setTitle(std::string(16 * 1024, 'X').c_str());
+      f.save();
+      CPPUNIT_ASSERT_EQUAL(68202L, f.length());
+    }
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestASF);