tag: added function tag_merge()

tag_merges() merges the data from two tag objects into one.
This commit is contained in:
Max Kellermann 2009-01-03 23:28:51 +01:00
parent 149f4e10cf
commit 4be479d20c
2 changed files with 55 additions and 0 deletions

View File

@ -318,6 +318,52 @@ struct tag *tag_dup(const struct tag *tag)
return ret;
}
struct tag *
tag_merge(const struct tag *base, const struct tag *add)
{
struct tag *ret;
unsigned n;
assert(base != NULL);
assert(add != NULL);
/* allocate new tag object */
ret = tag_new();
ret->time = add->time > 0 ? add->time : base->time;
ret->numOfItems = base->numOfItems + add->numOfItems;
ret->items = ret->numOfItems > 0 ? g_malloc(items_size(ret)) : NULL;
g_mutex_lock(tag_pool_lock);
/* copy all items from "add" */
for (unsigned i = 0; i < add->numOfItems; ++i)
ret->items[i] = tag_pool_dup_item(add->items[i]);
n = add->numOfItems;
/* copy additional items from "base" */
for (unsigned i = 0; i < base->numOfItems; ++i)
if (!tag_has_type(add, base->items[i]->type))
ret->items[n++] = tag_pool_dup_item(base->items[i]);
g_mutex_unlock(tag_pool_lock);
assert(n <= ret->numOfItems);
if (n < ret->numOfItems) {
/* some tags were not copied - shrink ret->items */
assert(n > 0);
ret->numOfItems = n;
ret->items = g_realloc(ret->items, items_size(ret));
}
return ret;
}
bool tag_has_type(const struct tag *tag, enum tag_type type)
{
assert(tag != NULL);

View File

@ -89,6 +89,15 @@ static inline void tag_add_item(struct tag *tag, enum tag_type itemType,
struct tag *tag_dup(const struct tag *tag);
/**
* Merges the data from two tags. If both tags share data for the
* same tag_type, only data from "add" is used.
*
* @return a newly allocated tag, which must be freed with tag_free()
*/
struct tag *
tag_merge(const struct tag *base, const struct tag *add);
/**
* Returns true if the tag contains no items. This ignores the "time"
* attribute.