diff --git a/src/PlaylistTag.cxx b/src/PlaylistTag.cxx index 5813ec1c1..e158018f5 100644 --- a/src/PlaylistTag.cxx +++ b/src/PlaylistTag.cxx @@ -28,6 +28,7 @@ #include "PlaylistError.hxx" #include "Song.hxx" #include "tag/Tag.hxx" +#include "tag/TagBuilder.hxx" #include "util/Error.hxx" bool @@ -48,9 +49,15 @@ playlist::AddSongIdTag(unsigned id, TagType tag_type, const char *value, return false; } - if (song.tag == nullptr) - song.tag = new Tag(); - song.tag->AddItem(tag_type, value); + TagBuilder tag; + if (song.tag != nullptr) { + tag = std::move(*song.tag); + delete song.tag; + } + + tag.AddItem(tag_type, value); + song.tag = tag.Commit(); + queue.ModifyAtPosition(position); OnModified(); return true; @@ -77,10 +84,15 @@ playlist::ClearSongIdTag(unsigned id, TagType tag_type, if (song.tag == nullptr) return true; + TagBuilder tag(std::move(*song.tag)); + delete song.tag; + if (tag_type == TAG_NUM_OF_ITEM_TYPES) - song.tag->RemoveAll(); + tag.RemoveAll(); else - song.tag->RemoveType(tag_type); + tag.RemoveType(tag_type); + song.tag = tag.Commit(); + queue.ModifyAtPosition(position); OnModified(); return true; diff --git a/src/tag/Tag.cxx b/src/tag/Tag.cxx index 7d1da63df..43ded308a 100644 --- a/src/tag/Tag.cxx +++ b/src/tag/Tag.cxx @@ -187,23 +187,3 @@ Tag::AddItem(TagType type, const char *value) { AddItem(type, value, strlen(value)); } - -void -Tag::RemoveType(TagType type) -{ - auto dest = items, src = items, end = items + num_items; - - tag_pool_lock.lock(); - while (src != end) { - TagItem *item = *src++; - if (item->type == type) - /* remove it */ - tag_pool_put_item(item); - else - /* keep it */ - *dest++ = item; - } - tag_pool_lock.unlock(); - - num_items = dest - items; -} diff --git a/src/tag/Tag.hxx b/src/tag/Tag.hxx index 0e48298a7..e404a4f26 100644 --- a/src/tag/Tag.hxx +++ b/src/tag/Tag.hxx @@ -121,18 +121,6 @@ struct Tag { */ void AddItem(TagType type, const char *value); - /** - * Removes all tag items. - */ - void RemoveAll() { - num_items = 0; - } - - /** - * Removes all tag items of the specified type. - */ - void RemoveType(TagType type); - /** * Merges the data from two tags. If both tags share data for the * same TagType, only data from "add" is used. diff --git a/src/tag/TagBuilder.cxx b/src/tag/TagBuilder.cxx index 2d3b49eb5..5c7da2a1a 100644 --- a/src/tag/TagBuilder.cxx +++ b/src/tag/TagBuilder.cxx @@ -108,13 +108,7 @@ TagBuilder::Clear() { time = -1; has_playlist = false; - - tag_pool_lock.lock(); - for (auto i : items) - tag_pool_put_item(i); - tag_pool_lock.unlock(); - - items.clear(); + RemoveAll(); } void @@ -216,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); +} diff --git a/src/tag/TagBuilder.hxx b/src/tag/TagBuilder.hxx index cd4fa4e57..fe647db08 100644 --- a/src/tag/TagBuilder.hxx +++ b/src/tag/TagBuilder.hxx @@ -147,6 +147,16 @@ public: gcc_nonnull_all void AddItem(TagType type, const char *value); + /** + * Removes all tag items. + */ + void RemoveAll(); + + /** + * Removes all tag items of the specified type. + */ + void RemoveType(TagType type); + private: gcc_nonnull_all void AddItemInternal(TagType type, const char *value, size_t length);