Tag.cxx 2.71 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2014 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 "TagSettings.h"
25
#include "TagBuilder.hxx"
26
#include "util/ASCII.hxx"
Warren Dukes's avatar
Warren Dukes committed
27

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

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

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

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

	return TAG_NUM_OF_ITEM_TYPES;
}

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

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

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

	return TAG_NUM_OF_ITEM_TYPES;
}

Max Kellermann's avatar
Max Kellermann committed
61 62 63
void
Tag::Clear()
{
64
	duration = SignedSongTime::Negative();
Max Kellermann's avatar
Max Kellermann committed
65 66 67 68 69 70 71
	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();

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

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

Max Kellermann's avatar
Max Kellermann committed
85 86 87 88 89
		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();
	}
90 91
}

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

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

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

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

	return tag;
}

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

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

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

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