]> granicus.if.org Git - taglib/commitdiff
Added support for APE tag binary items
authorStephen F. Booth <me@sbooth.org>
Tue, 10 Apr 2012 11:24:12 +0000 (07:24 -0400)
committerStephen F. Booth <me@sbooth.org>
Tue, 10 Apr 2012 11:24:12 +0000 (07:24 -0400)
taglib/ape/apeitem.cpp
taglib/ape/apeitem.h
taglib/ape/apetag.cpp
taglib/ape/apetag.h

index 350eac0b51fda2b13b4dad36cfe844e7bf92e340..52e0f064da1d472ad83acd02d3cb14528c21e399 100644 (file)
@@ -62,6 +62,14 @@ APE::Item::Item(const String &key, const StringList &values)
   d->text = values;
 }
 
+APE::Item::Item(const String &key, const ByteVector &value)
+{
+  d = new ItemPrivate;
+  d->type = Binary;
+  d->key = key;
+  d->value = value;
+}
+
 APE::Item::Item(const Item &item)
 {
   d = new ItemPrivate(*item.d);
@@ -104,6 +112,17 @@ String APE::Item::key() const
   return d->key;
 }
 
+ByteVector APE::Item::binaryData() const
+{
+  return d->value;
+}
+
+void APE::Item::setBinaryData(const ByteVector &value)
+{
+  d->type = Binary;
+  d->value = value;
+}
+
 ByteVector APE::Item::value() const
 {
   // This seems incorrect as it won't be actually rendering the value to keep it
@@ -119,27 +138,50 @@ void APE::Item::setKey(const String &key)
 
 void APE::Item::setValue(const String &value)
 {
+    d->type = Text;
     d->text = value;
 }
 
 void APE::Item::setValues(const StringList &value)
 {
+    d->type = Text;
     d->text = value;
 }
 
 void APE::Item::appendValue(const String &value)
 {
+    d->type = Text;
     d->text.append(value);
 }
 
 void APE::Item::appendValues(const StringList &values)
 {
+    d->type = Text;
     d->text.append(values);
 }
 
 int APE::Item::size() const
 {
-  return 8 + d->key.size() + 1 + d->value.size();
+  // SFB: Why is d->key.size() used when size() returns the length in UniChars and not UTF-8?
+  int result = 8 + d->key.size() /* d->key.data(String::UTF8).size() */ + 1;
+  switch (d->type) {
+    case Text:
+      {
+        StringList::ConstIterator it = d->text.begin();
+                 
+        result += it->data(String::UTF8).size();
+        it++;
+        for(; it != d->text.end(); ++it)
+          result += 1 + it->data(String::UTF8).size();
+        break;
+      }
+
+    case Binary:
+    case Locator:
+      result += d->value.size();
+      break;
+  }
+  return result;
 }
 
 StringList APE::Item::toStringList() const
@@ -161,12 +203,12 @@ bool APE::Item::isEmpty() const
 {
   switch(d->type) {
     case Text:
-    case Binary:
       if(d->text.isEmpty())
         return true;
       if(d->text.size() == 1 && d->text.front().isEmpty())
         return true;
       return false;
+    case Binary:
     case Locator:
       return d->value.isEmpty();
     default:
@@ -193,7 +235,7 @@ void APE::Item::parse(const ByteVector &data)
   setReadOnly(flags & 1);
   setType(ItemTypes((flags >> 1) & 3));
 
-  if(int(d->type) < 2)
+  if(Text == d->type)
     d->text = StringList(ByteVectorList::split(d->value, '\0'), String::UTF8);
 }
 
index 01fcc764feb14816791b4014a0501db5a53eb356..a42801702a24c74b6cc100b84202154ff84128f7 100644 (file)
@@ -59,16 +59,21 @@ namespace TagLib {
       Item();
 
       /*!
-       * Constructs an item with \a key and \a value.
+       * Constructs a text item with \a key and \a value.
        */
       // BIC: Remove this, StringList has a constructor from a single string
       Item(const String &key, const String &value);
 
       /*!
-       * Constructs an item with \a key and \a values.
+       * Constructs a text item with \a key and \a values.
        */
       Item(const String &key, const StringList &values);
 
+      /*!
+       * Constructs a binary item with \a key and \a value.
+       */
+      Item(const String &key, const ByteVector &value);
+
       /*!
        * Construct an item as a copy of \a item.
        */
@@ -91,12 +96,20 @@ namespace TagLib {
 
       /*!
        * Returns the binary value.
-       *
-       * \deprecated This will be removed in the next binary incompatible version
-       * as it is not kept in sync with the things that are set using setValue()
-       * and friends.
+       * If the item type is not \a Binary, the returned contents are undefined
        */
+      ByteVector binaryData() const;
+
+     /*!
+      * Set the binary value to \a value
+      * The item's type will also be set to \a Binary
+      */
+      void setBinaryData(const ByteVector &value);
+
+#ifndef DO_NOT_DOCUMENT
+      /* Remove in next binary incompatible release */
       ByteVector value() const;
+#endif
 
       /*!
        * Sets the key for the item to \a key.
@@ -104,14 +117,14 @@ namespace TagLib {
       void setKey(const String &key);
 
       /*!
-       * Sets the value of the item to \a value and clears any previous contents.
+       * Sets the text value of the item to \a value and clears any previous contents.
        *
        * \see toString()
        */
       void setValue(const String &value);
 
       /*!
-       * Sets the value of the item to the list of values in \a value and clears
+       * Sets the text value of the item to the list of values in \a value and clears
        * any previous contents.
        *
        * \see toStringList()
@@ -119,14 +132,14 @@ namespace TagLib {
       void setValues(const StringList &values);
 
       /*!
-       * Appends \a value to create (or extend) the current list of values.
+       * Appends \a value to create (or extend) the current list of text values.
        *
        * \see toString()
        */
       void appendValue(const String &value);
 
       /*!
-       * Appends \a values to extend the current list of values.
+       * Appends \a values to extend the current list of text values.
        *
        * \see toStringList()
        */
@@ -143,14 +156,13 @@ namespace TagLib {
        */
       String toString() const;
 
-      /*!
-       * \deprecated
-       * \see values
-       */
+#ifndef DO_NOT_DOCUMENT
+      /* Remove in next binary incompatible release */
       StringList toStringList() const;
+#endif
 
       /*!
-       * Returns the list of values.
+       * Returns the list of text values.
        */
       StringList values() const;
 
index 296c3d4be4c4fe4490ce245c9eaf176b1242ff5c..e925235ef2515c1aa27b116380118010f114e99a 100644 (file)
@@ -277,13 +277,26 @@ void APE::Tag::addValue(const String &key, const String &value, bool replace)
   if(replace)
     removeItem(key);
   if(!key.isEmpty() && !value.isEmpty()) {
-    if(!replace && d->itemListMap.contains(key))
-      d->itemListMap[key.upper()].appendValue(value);
+    if(!replace && d->itemListMap.contains(key)) {
+      // Text items may contain more than one value
+      if(APE::Item::Text == d->itemListMap.begin()->second.type())
+        d->itemListMap[key.upper()].appendValue(value);
+      // Binary or locator items may have only one value
+      else
+        setItem(key, Item(key, value));
+    }
     else
       setItem(key, Item(key, value));
   }
 }
 
+void APE::Tag::setData(const String &key, const ByteVector &value)
+{
+  removeItem(key);
+  if(!key.isEmpty() && !value.isEmpty())
+    setItem(key, Item(key, value));
+}
+
 void APE::Tag::setItem(const String &key, const Item &item)
 {
   if(!key.isEmpty())
index 8520609ebc5cc19a8cc4a84e107acafbac92381e..1a8c30c9bad4e1b567c8a942d683e814a650d68b 100644 (file)
@@ -152,12 +152,19 @@ namespace TagLib {
       void removeItem(const String &key);
 
       /*!
-       * Adds to the item specified by \a key the data \a value.  If \a replace
+       * Adds to the text item specified by \a key the data \a value.  If \a replace
        * is true, then all of the other values on the same key will be removed
-       * first.
+       * first.  If a binary item exists for \a key it will be removed first.
        */
       void addValue(const String &key, const String &value, bool replace = true);
 
+     /*!
+      * Set the binary data for the key specified by \a item to \a value
+      * This will convert the item to type \a Binary if it isn't already and
+      * all of the other values on the same key will be removed.
+      */
+      void setData(const String &key, const ByteVector &value);
+
       /*!
        * Sets the \a key item to the value of \a item. If an item with the \a key is already
        * present, it will be replaced.