Tag.cxx 2.69 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2015 The Music Player Daemon Project
3
 * http://www.musicpd.org
Warren Dukes's avatar
Warren Dukes committed
4 5 6 7 8 9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Warren Dukes's avatar
Warren Dukes committed
18 19
 */

20
#include "config.h"
Max Kellermann's avatar
Max Kellermann committed
21
#include "Tag.hxx"
Max Kellermann's avatar
Max Kellermann committed
22
#include "TagPool.hxx"
23
#include "TagString.hxx"
24
#include "TagBuilder.hxx"
25
#include "util/ASCII.hxx"
Warren Dukes's avatar
Warren Dukes committed
26

27
#include <assert.h>
Max Kellermann's avatar
Max Kellermann committed
28
#include <string.h>
29

30
TagType
31 32
tag_name_parse(const char *name)
{
Max Kellermann's avatar
Max Kellermann committed
33
	assert(name != nullptr);
34 35

	for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) {
Max Kellermann's avatar
Max Kellermann committed
36
		assert(tag_item_names[i] != nullptr);
37 38

		if (strcmp(name, tag_item_names[i]) == 0)
39
			return (TagType)i;
40 41 42 43 44
	}

	return TAG_NUM_OF_ITEM_TYPES;
}

45
TagType
46 47
tag_name_parse_i(const char *name)
{
Max Kellermann's avatar
Max Kellermann committed
48
	assert(name != nullptr);
49 50

	for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) {
Max Kellermann's avatar
Max Kellermann committed
51
		assert(tag_item_names[i] != nullptr);
52

53
		if (StringEqualsCaseASCII(name, tag_item_names[i]))
54
			return (TagType)i;
55 56 57 58 59
	}

	return TAG_NUM_OF_ITEM_TYPES;
}

Max Kellermann's avatar
Max Kellermann committed
60 61 62
void
Tag::Clear()
{
63
	duration = SignedSongTime::Negative();
Max Kellermann's avatar
Max Kellermann committed
64 65 66 67 68 69 70
	has_playlist = false;

	tag_pool_lock.lock();
	for (unsigned i = 0; i < num_items; ++i)
		tag_pool_put_item(items[i]);
	tag_pool_lock.unlock();

71
	delete[] items;
Max Kellermann's avatar
Max Kellermann committed
72 73 74 75
	items = nullptr;
	num_items = 0;
}

Max Kellermann's avatar
Max Kellermann committed
76
Tag::Tag(const Tag &other)
77
	:duration(other.duration), has_playlist(other.has_playlist),
78 79
	 num_items(other.num_items),
	 items(nullptr)
Avuton Olrich's avatar
Avuton Olrich committed
80
{
Max Kellermann's avatar
Max Kellermann committed
81
	if (num_items > 0) {
82
		items = new TagItem *[num_items];
Warren Dukes's avatar
Warren Dukes committed
83

Max Kellermann's avatar
Max Kellermann committed
84 85 86 87 88
		tag_pool_lock.lock();
		for (unsigned i = 0; i < num_items; i++)
			items[i] = tag_pool_dup_item(other.items[i]);
		tag_pool_lock.unlock();
	}
89 90
}

Max Kellermann's avatar
Max Kellermann committed
91 92
Tag *
Tag::Merge(const Tag &base, const Tag &add)
93
{
94 95
	TagBuilder builder(add);
	builder.Complement(base);
96
	return builder.CommitNew();
97 98
}

Max Kellermann's avatar
Max Kellermann committed
99 100
Tag *
Tag::MergeReplace(Tag *base, Tag *add)
101
{
Max Kellermann's avatar
Max Kellermann committed
102
	if (add == nullptr)
103 104
		return base;

Max Kellermann's avatar
Max Kellermann committed
105
	if (base == nullptr)
106 107
		return add;

Max Kellermann's avatar
Max Kellermann committed
108 109 110
	Tag *tag = Merge(*base, *add);
	delete base;
	delete add;
111 112 113 114

	return tag;
}

115
const char *
116
Tag::GetValue(TagType type) const
117 118 119
{
	assert(type < TAG_NUM_OF_ITEM_TYPES);

120 121 122
	for (const auto &item : *this)
		if (item.type == type)
			return item.value;
123

Max Kellermann's avatar
Max Kellermann committed
124
	return nullptr;
125
}
126

Max Kellermann's avatar
Max Kellermann committed
127
bool
128
Tag::HasType(TagType type) const
129
{
Max Kellermann's avatar
Max Kellermann committed
130
	return GetValue(type) != nullptr;
131
}