aboutsummaryrefslogtreecommitdiffstats
path: root/src/tag/TagBuilder.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tag/TagBuilder.cxx135
1 files changed, 129 insertions, 6 deletions
diff --git a/src/tag/TagBuilder.cxx b/src/tag/TagBuilder.cxx
index 25e5cc24b..37aa08cee 100644
--- a/src/tag/TagBuilder.cxx
+++ b/src/tag/TagBuilder.cxx
@@ -29,18 +29,86 @@
#include <assert.h>
#include <string.h>
-void
-TagBuilder::Clear()
+TagBuilder::TagBuilder(const Tag &other)
+ :time(other.time), has_playlist(other.has_playlist)
{
- time = -1;
- has_playlist = false;
+ items.reserve(other.num_items);
tag_pool_lock.lock();
+ for (unsigned i = 0, n = other.num_items; i != n; ++i)
+ items.push_back(tag_pool_dup_item(other.items[i]));
+ tag_pool_lock.unlock();
+}
+
+TagBuilder::TagBuilder(Tag &&other)
+ :time(other.time), has_playlist(other.has_playlist)
+{
+ /* move all TagItem pointers from the Tag object; we don't
+ need to contact the tag pool, because all we do is move
+ references */
+ items.reserve(other.num_items);
+ std::copy_n(other.items, other.num_items, std::back_inserter(items));
+
+ /* discard the pointers from the Tag object */
+ other.num_items = 0;
+ delete[] other.items;
+ other.items = nullptr;
+}
+
+TagBuilder &
+TagBuilder::operator=(const TagBuilder &other)
+{
+ /* copy all attributes */
+ time = other.time;
+ has_playlist = other.has_playlist;
+ items = other.items;
+
+ /* increment the tag pool refcounters */
+ tag_pool_lock.lock();
for (auto i : items)
- tag_pool_put_item(i);
+ tag_pool_dup_item(i);
tag_pool_lock.unlock();
+ return *this;
+}
+
+TagBuilder &
+TagBuilder::operator=(TagBuilder &&other)
+{
+ time = other.time;
+ has_playlist = other.has_playlist;
+ items = std::move(other.items);
+
+ return *this;
+}
+
+TagBuilder &
+TagBuilder::operator=(Tag &&other)
+{
+ time = other.time;
+ has_playlist = other.has_playlist;
+
+ /* move all TagItem pointers from the Tag object; we don't
+ need to contact the tag pool, because all we do is move
+ references */
items.clear();
+ items.reserve(other.num_items);
+ std::copy_n(other.items, other.num_items, std::back_inserter(items));
+
+ /* discard the pointers from the Tag object */
+ other.num_items = 0;
+ delete[] other.items;
+ other.items = nullptr;
+
+ return *this;
+}
+
+void
+TagBuilder::Clear()
+{
+ time = -1;
+ has_playlist = false;
+ RemoveAll();
}
void
@@ -57,7 +125,7 @@ TagBuilder::Commit(Tag &tag)
object */
const unsigned n_items = items.size();
tag.num_items = n_items;
- tag.items = g_new(TagItem *, n_items);
+ tag.items = new TagItem *[n_items];
std::copy_n(items.begin(), n_items, tag.items);
items.clear();
@@ -74,6 +142,35 @@ TagBuilder::Commit()
return tag;
}
+bool
+TagBuilder::HasType(TagType type) const
+{
+ for (auto i : items)
+ if (i->type == type)
+ return true;
+
+ 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)
{
@@ -113,3 +210,29 @@ TagBuilder::AddItem(TagType type, const char *value)
AddItem(type, value, strlen(value));
}
+
+void
+TagBuilder::RemoveAll()
+{
+ tag_pool_lock.lock();
+ for (auto i : items)
+ tag_pool_put_item(i);
+ tag_pool_lock.unlock();
+
+ items.clear();
+}
+
+void
+TagBuilder::RemoveType(TagType type)
+{
+ const auto begin = items.begin(), end = items.end();
+
+ items.erase(std::remove_if(begin, end,
+ [type](TagItem *item) {
+ if (item->type != type)
+ return false;
+ tag_pool_put_item(item);
+ return true;
+ }),
+ end);
+}