diff options
Diffstat (limited to '')
-rw-r--r-- | src/tag/TagBuilder.cxx | 135 |
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); +} |