From 4be479d20c2f81fb0303106b7080af93b3c456c6 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 3 Jan 2009 23:28:51 +0100 Subject: tag: added function tag_merge() tag_merges() merges the data from two tag objects into one. --- src/tag.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/tag.h | 9 +++++++++ 2 files changed, 55 insertions(+) (limited to 'src') diff --git a/src/tag.c b/src/tag.c index 180dbb86a..343f4d91c 100644 --- a/src/tag.c +++ b/src/tag.c @@ -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); diff --git a/src/tag.h b/src/tag.h index c1c7d7e9a..7c7abf50a 100644 --- a/src/tag.h +++ b/src/tag.h @@ -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. -- cgit v1.2.3