Added support for APE tag binary items

This commit is contained in:
Stephen F. Booth 2012-04-10 07:24:12 -04:00
parent bd03e352cc
commit ca26a9ad3e
4 changed files with 96 additions and 22 deletions

View 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);
}

View 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;

View 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())

View 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.