diff options
Diffstat (limited to 'src/tag')
-rw-r--r-- | src/tag/Tag.cxx | 44 | ||||
-rw-r--r-- | src/tag/TagBuilder.cxx | 19 | ||||
-rw-r--r-- | src/tag/TagBuilder.hxx | 6 |
3 files changed, 29 insertions, 40 deletions
diff --git a/src/tag/Tag.cxx b/src/tag/Tag.cxx index 0fb7ea93b..7d1da63df 100644 --- a/src/tag/Tag.cxx +++ b/src/tag/Tag.cxx @@ -22,6 +22,7 @@ #include "TagPool.hxx" #include "TagString.hxx" #include "TagSettings.h" +#include "TagBuilder.hxx" #include "util/ASCII.hxx" #include <glib.h> @@ -108,46 +109,9 @@ Tag::Tag(const Tag &other) Tag * Tag::Merge(const Tag &base, const Tag &add) { - unsigned n; - - /* allocate new tag object */ - - Tag *ret = new Tag(); - ret->time = add.time > 0 ? add.time : base.time; - ret->num_items = base.num_items + add.num_items; - ret->items = ret->num_items > 0 - ? (TagItem **)g_malloc(items_size(*ret)) - : nullptr; - - tag_pool_lock.lock(); - - /* copy all items from "add" */ - - for (unsigned i = 0; i < add.num_items; ++i) - ret->items[i] = tag_pool_dup_item(add.items[i]); - - n = add.num_items; - - /* copy additional items from "base" */ - - for (unsigned i = 0; i < base.num_items; ++i) - if (!add.HasType(base.items[i]->type)) - ret->items[n++] = tag_pool_dup_item(base.items[i]); - - tag_pool_lock.unlock(); - - assert(n <= ret->num_items); - - if (n < ret->num_items) { - /* some tags were not copied - shrink ret->items */ - assert(n > 0); - - ret->num_items = n; - ret->items = (TagItem **) - g_realloc(ret->items, items_size(*ret)); - } - - return ret; + TagBuilder builder(base); + builder.Complement(add); + return builder.Commit(); } Tag * diff --git a/src/tag/TagBuilder.cxx b/src/tag/TagBuilder.cxx index 15e32bb01..6ba8c12db 100644 --- a/src/tag/TagBuilder.cxx +++ b/src/tag/TagBuilder.cxx @@ -109,6 +109,25 @@ TagBuilder::HasType(TagType type) const return false; } +void +TagBuilder::Complement(const Tag &other) +{ + if (time <= 0) + time = other.time; + + has_playlist |= other.has_playlist; + + items.reserve(items.size() + other.num_items); + + tag_pool_lock.lock(); + for (unsigned i = 0, n = other.num_items; i != n; ++i) { + TagItem *item = other.items[i]; + if (!HasType(item->type)) + items.push_back(tag_pool_dup_item(item)); + } + tag_pool_lock.unlock(); +} + inline void TagBuilder::AddItemInternal(TagType type, const char *value, size_t length) { diff --git a/src/tag/TagBuilder.hxx b/src/tag/TagBuilder.hxx index 5804a7940..52ccf466c 100644 --- a/src/tag/TagBuilder.hxx +++ b/src/tag/TagBuilder.hxx @@ -119,6 +119,12 @@ public: bool HasType(TagType type) const; /** + * Copy attributes and items from the other object that do not + * exist in this object. + */ + void Complement(const Tag &other); + + /** * Appends a new tag item. * * @param type the type of the new tag item |