aboutsummaryrefslogtreecommitdiffstats
path: root/src/tag
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-12-03 11:27:16 +0100
committerMax Kellermann <max@duempel.org>2013-12-03 11:46:24 +0100
commit7e8d254b95716f1253577a9a5d7df1760f9f6e47 (patch)
tree9d22bb8d6d3e1e1b064fca93397d945836e901ab /src/tag
parent6325c3f14a4dd1442d69dc5716b33c9d5b410164 (diff)
downloadmpd-7e8d254b95716f1253577a9a5d7df1760f9f6e47.tar.gz
mpd-7e8d254b95716f1253577a9a5d7df1760f9f6e47.tar.xz
mpd-7e8d254b95716f1253577a9a5d7df1760f9f6e47.zip
Tag: move code from Merge() to TagBuilder::Complement()
Diffstat (limited to 'src/tag')
-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