Tag: add class const_iterator and methods begin(), end()
Enables using range-based "for".
This commit is contained in:
parent
543a58bb87
commit
41a7203c28
@ -92,10 +92,10 @@ SongFilter::Item::Match(const Tag &_tag) const
|
|||||||
bool visited_types[TAG_NUM_OF_ITEM_TYPES];
|
bool visited_types[TAG_NUM_OF_ITEM_TYPES];
|
||||||
std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
|
std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
|
||||||
|
|
||||||
for (unsigned i = 0; i < _tag.num_items; i++) {
|
for (const auto &i : _tag) {
|
||||||
visited_types[_tag.items[i]->type] = true;
|
visited_types[i.type] = true;
|
||||||
|
|
||||||
if (Match(*_tag.items[i]))
|
if (Match(i))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,14 +112,12 @@ SongFilter::Item::Match(const Tag &_tag) const
|
|||||||
if (tag == TAG_ALBUM_ARTIST && visited_types[TAG_ARTIST]) {
|
if (tag == TAG_ALBUM_ARTIST && visited_types[TAG_ARTIST]) {
|
||||||
/* if we're looking for "album artist", but
|
/* if we're looking for "album artist", but
|
||||||
only "artist" exists, use that */
|
only "artist" exists, use that */
|
||||||
for (unsigned i = 0; i < _tag.num_items; i++) {
|
for (const auto &item : _tag)
|
||||||
const TagItem &item = *_tag.items[i];
|
|
||||||
if (item.type == TAG_ARTIST &&
|
if (item.type == TAG_ARTIST &&
|
||||||
StringMatch(item.value))
|
StringMatch(item.value))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,7 @@ void tag_print(Client &client, const Tag &tag)
|
|||||||
if (tag.time >= 0)
|
if (tag.time >= 0)
|
||||||
client_printf(client, SONG_TIME "%i\n", tag.time);
|
client_printf(client, SONG_TIME "%i\n", tag.time);
|
||||||
|
|
||||||
for (unsigned i = 0; i < tag.num_items; i++) {
|
for (const auto &i : tag)
|
||||||
client_printf(client, "%s: %s\n",
|
client_printf(client, "%s: %s\n",
|
||||||
tag_item_names[tag.items[i]->type],
|
tag_item_names[i.type], i.value);
|
||||||
tag.items[i]->value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,7 @@ tag_save(FILE *file, const Tag &tag)
|
|||||||
if (tag.has_playlist)
|
if (tag.has_playlist)
|
||||||
fprintf(file, "Playlist: yes\n");
|
fprintf(file, "Playlist: yes\n");
|
||||||
|
|
||||||
for (unsigned i = 0; i < tag.num_items; i++)
|
for (const auto &i : tag)
|
||||||
fprintf(file, "%s: %s\n",
|
fprintf(file, "%s: %s\n",
|
||||||
tag_item_names[tag.items[i]->type],
|
tag_item_names[i.type], i.value);
|
||||||
tag.items[i]->value);
|
|
||||||
}
|
}
|
||||||
|
@ -73,9 +73,7 @@ static bool
|
|||||||
CollectGroupCounts(TagCountMap &map, TagType group, const Tag &tag)
|
CollectGroupCounts(TagCountMap &map, TagType group, const Tag &tag)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (unsigned i = 0; i < tag.num_items; ++i) {
|
for (const auto &item : tag) {
|
||||||
const TagItem &item = *tag.items[i];
|
|
||||||
|
|
||||||
if (item.type == group) {
|
if (item.type == group) {
|
||||||
auto r = map.insert(std::make_pair(item.value,
|
auto r = map.insert(std::make_pair(item.value,
|
||||||
SearchStats()));
|
SearchStats()));
|
||||||
|
@ -184,12 +184,10 @@ PrintUniqueTag(Client &client, TagType tag_type,
|
|||||||
assert(value != nullptr);
|
assert(value != nullptr);
|
||||||
client_printf(client, "%s: %s\n", tag_item_names[tag_type], value);
|
client_printf(client, "%s: %s\n", tag_item_names[tag_type], value);
|
||||||
|
|
||||||
for (unsigned i = 0, n = tag.num_items; i < n; i++) {
|
for (const auto &item : tag)
|
||||||
const TagItem &item = *tag.items[i];
|
|
||||||
if (item.type != tag_type)
|
if (item.type != tag_type)
|
||||||
client_printf(client, "%s: %s\n",
|
client_printf(client, "%s: %s\n",
|
||||||
tag_item_names[item.type], item.value);
|
tag_item_names[item.type], item.value);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -43,9 +43,7 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
|
|||||||
if (tag.time > 0)
|
if (tag.time > 0)
|
||||||
stats.total_duration += tag.time;
|
stats.total_duration += tag.time;
|
||||||
|
|
||||||
for (unsigned i = 0; i < tag.num_items; ++i) {
|
for (const auto &item : tag) {
|
||||||
const TagItem &item = *tag.items[i];
|
|
||||||
|
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case TAG_ARTIST:
|
case TAG_ARTIST:
|
||||||
#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
|
#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
|
||||||
|
@ -272,8 +272,7 @@ vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused Error &error)
|
|||||||
static void
|
static void
|
||||||
copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag)
|
copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < tag->num_items; i++) {
|
for (const auto &item : *tag) {
|
||||||
const TagItem &item = *tag->items[i];
|
|
||||||
char *name = g_ascii_strup(tag_item_names[item.type], -1);
|
char *name = g_ascii_strup(tag_item_names[item.type], -1);
|
||||||
vorbis_comment_add_tag(vc, name, item.value);
|
vorbis_comment_add_tag(vc, name, item.value);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
|
@ -374,20 +374,22 @@ RoarOutput::SendTag(const Tag &tag)
|
|||||||
vals[0].key = const_cast<char *>("LENGTH");
|
vals[0].key = const_cast<char *>("LENGTH");
|
||||||
vals[0].value = timebuf;
|
vals[0].value = timebuf;
|
||||||
|
|
||||||
for (unsigned i = 0; i < tag.num_items && cnt < 32; i++)
|
for (const auto &item : tag) {
|
||||||
{
|
if (cnt >= 32)
|
||||||
|
break;
|
||||||
|
|
||||||
bool is_uuid = false;
|
bool is_uuid = false;
|
||||||
const char *key = roar_tag_convert(tag.items[i]->type,
|
const char *key = roar_tag_convert(item.type,
|
||||||
&is_uuid);
|
&is_uuid);
|
||||||
if (key != nullptr) {
|
if (key != nullptr) {
|
||||||
vals[cnt].key = const_cast<char *>(key);
|
vals[cnt].key = const_cast<char *>(key);
|
||||||
|
|
||||||
if (is_uuid) {
|
if (is_uuid) {
|
||||||
snprintf(uuid_buf[cnt], sizeof(uuid_buf[0]), "{UUID}%s",
|
snprintf(uuid_buf[cnt], sizeof(uuid_buf[0]), "{UUID}%s",
|
||||||
tag.items[i]->value);
|
item.value);
|
||||||
vals[cnt].value = uuid_buf[cnt];
|
vals[cnt].value = uuid_buf[cnt];
|
||||||
} else {
|
} else {
|
||||||
vals[cnt].value = tag.items[i]->value;
|
vals[cnt].value = const_cast<char *>(item.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
cnt++;
|
cnt++;
|
||||||
|
@ -470,13 +470,13 @@ shout_tag_to_metadata(const Tag *tag, char *dest, size_t size)
|
|||||||
artist[0] = 0;
|
artist[0] = 0;
|
||||||
title[0] = 0;
|
title[0] = 0;
|
||||||
|
|
||||||
for (unsigned i = 0; i < tag->num_items; i++) {
|
for (const auto &item : *tag) {
|
||||||
switch (tag->items[i]->type) {
|
switch (item.type) {
|
||||||
case TAG_ARTIST:
|
case TAG_ARTIST:
|
||||||
strncpy(artist, tag->items[i]->value, size);
|
strncpy(artist, item.value, size);
|
||||||
break;
|
break;
|
||||||
case TAG_TITLE:
|
case TAG_TITLE:
|
||||||
strncpy(title, tag->items[i]->value, size);
|
strncpy(title, item.value, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -30,10 +30,10 @@ CopyTagItem(TagBuilder &dest, TagType dest_type,
|
|||||||
const Tag &src, TagType src_type)
|
const Tag &src, TagType src_type)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
const unsigned n = src.num_items;
|
|
||||||
for (unsigned i = 0; i < n; ++i) {
|
for (const auto &item : src) {
|
||||||
if (src.items[i]->type == src_type) {
|
if (item.type == src_type) {
|
||||||
dest.AddItem(dest_type, src.items[i]->value);
|
dest.AddItem(dest_type, item.value);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,11 +87,10 @@ TagSet::CheckUnique(TagType dest_type,
|
|||||||
uint32_t group_mask)
|
uint32_t group_mask)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (unsigned i = 0; i < tag.num_items; ++i) {
|
|
||||||
if (tag.items[i]->type == src_type) {
|
for (const auto &item : tag) {
|
||||||
InsertUnique(tag, dest_type,
|
if (item.type == src_type) {
|
||||||
tag.items[i]->value,
|
InsertUnique(tag, dest_type, item.value, group_mask);
|
||||||
group_mask);
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,9 +118,9 @@ Tag::GetValue(TagType type) const
|
|||||||
{
|
{
|
||||||
assert(type < TAG_NUM_OF_ITEM_TYPES);
|
assert(type < TAG_NUM_OF_ITEM_TYPES);
|
||||||
|
|
||||||
for (unsigned i = 0; i < num_items; i++)
|
for (const auto &item : *this)
|
||||||
if (items[i]->type == type)
|
if (item.type == type)
|
||||||
return items[i]->value;
|
return item.value;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@ -136,6 +137,59 @@ struct Tag {
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool HasType(TagType type) const;
|
bool HasType(TagType type) const;
|
||||||
|
|
||||||
|
class const_iterator {
|
||||||
|
friend struct Tag;
|
||||||
|
const TagItem *const*cursor;
|
||||||
|
|
||||||
|
constexpr const_iterator(const TagItem *const*_cursor)
|
||||||
|
:cursor(_cursor) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr const TagItem &operator*() const {
|
||||||
|
return **cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const TagItem *operator->() const {
|
||||||
|
return *cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator &operator++() {
|
||||||
|
++cursor;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator operator++(int) {
|
||||||
|
auto result = cursor++;
|
||||||
|
return const_iterator{result};
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator &operator--() {
|
||||||
|
--cursor;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator operator--(int) {
|
||||||
|
auto result = cursor--;
|
||||||
|
return const_iterator{result};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const_iterator other) const {
|
||||||
|
return cursor == other.cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const_iterator other) const {
|
||||||
|
return cursor != other.cursor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return const_iterator{items};
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return const_iterator{items + num_items};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,8 +160,7 @@ ToString(const Tag &tag)
|
|||||||
|
|
||||||
std::string result = buffer;
|
std::string result = buffer;
|
||||||
|
|
||||||
for (unsigned i = 0, n = tag.num_items; i != n; ++i) {
|
for (const auto &item : tag) {
|
||||||
const TagItem &item = *tag.items[i];
|
|
||||||
result.push_back('|');
|
result.push_back('|');
|
||||||
result.append(tag_item_names[item.type]);
|
result.append(tag_item_names[item.type]);
|
||||||
result.push_back('=');
|
result.push_back('=');
|
||||||
|
Loading…
Reference in New Issue
Block a user