diff --git a/taglib/ape/apeitem.cpp b/taglib/ape/apeitem.cpp index 350eac0b..52e0f064 100644 --- a/taglib/ape/apeitem.cpp +++ b/taglib/ape/apeitem.cpp @@ -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); } diff --git a/taglib/ape/apeitem.h b/taglib/ape/apeitem.h index 01fcc764..a4280170 100644 --- a/taglib/ape/apeitem.h +++ b/taglib/ape/apeitem.h @@ -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; diff --git a/taglib/ape/apetag.cpp b/taglib/ape/apetag.cpp index 296c3d4b..e925235e 100644 --- a/taglib/ape/apetag.cpp +++ b/taglib/ape/apetag.cpp @@ -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()) diff --git a/taglib/ape/apetag.h b/taglib/ape/apetag.h index 8520609e..1a8c30c9 100644 --- a/taglib/ape/apetag.h +++ b/taglib/ape/apetag.h @@ -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.