summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tag/Tag.cxx44
-rw-r--r--src/tag/TagBuilder.cxx19
-rw-r--r--src/tag/TagBuilder.hxx6
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