TagBuilder: allow adding duplicate tag types in Complement()

Build a table of pre-existing tag types before adding new items.  The
old way would check HasType() each time, which would return true after
the first instance of that tag type had been added, preventing
duplicate tag types to be merged.

This broke duplicate tag types loaded from the state file, because
this code path uses TagBuilder::Complement().
This commit is contained in:
Max Kellermann 2015-02-06 12:25:34 +01:00
parent 8a6b4db19f
commit b3fe3e8b3d
2 changed files with 11 additions and 1 deletions

1
NEWS
View File

@ -1,6 +1,7 @@
ver 0.19.9 (not yet released) ver 0.19.9 (not yet released)
* decoder * decoder
- dsdiff, dsf: raise ID3 tag limit to 1 MB - dsdiff, dsf: raise ID3 tag limit to 1 MB
* playlist: fix loading duplicate tag types from state file
* fix clock integer overflow on OS X * fix clock integer overflow on OS X
* fix build failure with uClibc * fix build failure with uClibc
* fix build failure on non-POSIX operating systems * fix build failure on non-POSIX operating systems

View File

@ -25,6 +25,8 @@
#include "Tag.hxx" #include "Tag.hxx"
#include "util/WritableBuffer.hxx" #include "util/WritableBuffer.hxx"
#include <array>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -168,12 +170,19 @@ TagBuilder::Complement(const Tag &other)
has_playlist |= other.has_playlist; has_playlist |= other.has_playlist;
/* build a table of tag types that were already present in
this object, which will not be copied from #other */
std::array<bool, TAG_NUM_OF_ITEM_TYPES> present;
present.fill(false);
for (const TagItem *i : items)
present[i->type] = true;
items.reserve(items.size() + other.num_items); items.reserve(items.size() + other.num_items);
tag_pool_lock.lock(); tag_pool_lock.lock();
for (unsigned i = 0, n = other.num_items; i != n; ++i) { for (unsigned i = 0, n = other.num_items; i != n; ++i) {
TagItem *item = other.items[i]; TagItem *item = other.items[i];
if (!HasType(item->type)) if (!present[item->type])
items.push_back(tag_pool_dup_item(item)); items.push_back(tag_pool_dup_item(item));
} }
tag_pool_lock.unlock(); tag_pool_lock.unlock();