Commit 41a7203c authored by Max Kellermann's avatar Max Kellermann

Tag: add class const_iterator and methods begin(), end()

Enables using range-based "for".
parent 543a58bb
......@@ -92,10 +92,10 @@ SongFilter::Item::Match(const Tag &_tag) const
bool visited_types[TAG_NUM_OF_ITEM_TYPES];
std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
for (unsigned i = 0; i < _tag.num_items; i++) {
visited_types[_tag.items[i]->type] = true;
for (const auto &i : _tag) {
visited_types[i.type] = true;
if (Match(*_tag.items[i]))
if (Match(i))
return true;
}
......@@ -112,14 +112,12 @@ SongFilter::Item::Match(const Tag &_tag) const
if (tag == TAG_ALBUM_ARTIST && visited_types[TAG_ARTIST]) {
/* if we're looking for "album artist", but
only "artist" exists, use that */
for (unsigned i = 0; i < _tag.num_items; i++) {
const TagItem &item = *_tag.items[i];
for (const auto &item : _tag)
if (item.type == TAG_ARTIST &&
StringMatch(item.value))
return true;
}
}
}
return false;
}
......
......@@ -47,9 +47,7 @@ void tag_print(Client &client, const Tag &tag)
if (tag.time >= 0)
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",
tag_item_names[tag.items[i]->type],
tag.items[i]->value);
}
tag_item_names[i.type], i.value);
}
......@@ -32,8 +32,7 @@ tag_save(FILE *file, const Tag &tag)
if (tag.has_playlist)
fprintf(file, "Playlist: yes\n");
for (unsigned i = 0; i < tag.num_items; i++)
for (const auto &i : tag)
fprintf(file, "%s: %s\n",
tag_item_names[tag.items[i]->type],
tag.items[i]->value);
tag_item_names[i.type], i.value);
}
......@@ -73,9 +73,7 @@ static bool
CollectGroupCounts(TagCountMap &map, TagType group, const Tag &tag)
{
bool found = false;
for (unsigned i = 0; i < tag.num_items; ++i) {
const TagItem &item = *tag.items[i];
for (const auto &item : tag) {
if (item.type == group) {
auto r = map.insert(std::make_pair(item.value,
SearchStats()));
......
......@@ -184,12 +184,10 @@ PrintUniqueTag(Client &client, TagType tag_type,
assert(value != nullptr);
client_printf(client, "%s: %s\n", tag_item_names[tag_type], value);
for (unsigned i = 0, n = tag.num_items; i < n; i++) {
const TagItem &item = *tag.items[i];
for (const auto &item : tag)
if (item.type != tag_type)
client_printf(client, "%s: %s\n",
tag_item_names[item.type], item.value);
}
return true;
}
......
......@@ -43,9 +43,7 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
if (tag.time > 0)
stats.total_duration += tag.time;
for (unsigned i = 0; i < tag.num_items; ++i) {
const TagItem &item = *tag.items[i];
for (const auto &item : tag) {
switch (item.type) {
case TAG_ARTIST:
#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
......
......@@ -272,8 +272,7 @@ vorbis_encoder_pre_tag(Encoder *_encoder, gcc_unused Error &error)
static void
copy_tag_to_vorbis_comment(vorbis_comment *vc, const Tag *tag)
{
for (unsigned i = 0; i < tag->num_items; i++) {
const TagItem &item = *tag->items[i];
for (const auto &item : *tag) {
char *name = g_ascii_strup(tag_item_names[item.type], -1);
vorbis_comment_add_tag(vc, name, item.value);
g_free(name);
......
......@@ -374,20 +374,22 @@ RoarOutput::SendTag(const Tag &tag)
vals[0].key = const_cast<char *>("LENGTH");
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;
const char *key = roar_tag_convert(tag.items[i]->type,
const char *key = roar_tag_convert(item.type,
&is_uuid);
if (key != nullptr) {
vals[cnt].key = const_cast<char *>(key);
if (is_uuid) {
snprintf(uuid_buf[cnt], sizeof(uuid_buf[0]), "{UUID}%s",
tag.items[i]->value);
item.value);
vals[cnt].value = uuid_buf[cnt];
} else {
vals[cnt].value = tag.items[i]->value;
vals[cnt].value = const_cast<char *>(item.value);
}
cnt++;
......
......@@ -470,13 +470,13 @@ shout_tag_to_metadata(const Tag *tag, char *dest, size_t size)
artist[0] = 0;
title[0] = 0;
for (unsigned i = 0; i < tag->num_items; i++) {
switch (tag->items[i]->type) {
for (const auto &item : *tag) {
switch (item.type) {
case TAG_ARTIST:
strncpy(artist, tag->items[i]->value, size);
strncpy(artist, item.value, size);
break;
case TAG_TITLE:
strncpy(title, tag->items[i]->value, size);
strncpy(title, item.value, size);
break;
default:
......
......@@ -30,10 +30,10 @@ CopyTagItem(TagBuilder &dest, TagType dest_type,
const Tag &src, TagType src_type)
{
bool found = false;
const unsigned n = src.num_items;
for (unsigned i = 0; i < n; ++i) {
if (src.items[i]->type == src_type) {
dest.AddItem(dest_type, src.items[i]->value);
for (const auto &item : src) {
if (item.type == src_type) {
dest.AddItem(dest_type, item.value);
found = true;
}
}
......@@ -87,11 +87,10 @@ TagSet::CheckUnique(TagType dest_type,
uint32_t group_mask)
{
bool found = false;
for (unsigned i = 0; i < tag.num_items; ++i) {
if (tag.items[i]->type == src_type) {
InsertUnique(tag, dest_type,
tag.items[i]->value,
group_mask);
for (const auto &item : tag) {
if (item.type == src_type) {
InsertUnique(tag, dest_type, item.value, group_mask);
found = true;
}
}
......
......@@ -118,9 +118,9 @@ Tag::GetValue(TagType type) const
{
assert(type < TAG_NUM_OF_ITEM_TYPES);
for (unsigned i = 0; i < num_items; i++)
if (items[i]->type == type)
return items[i]->value;
for (const auto &item : *this)
if (item.type == type)
return item.value;
return nullptr;
}
......
......@@ -25,6 +25,7 @@
#include "Compiler.h"
#include <algorithm>
#include <iterator>
#include <stddef.h>
......@@ -136,6 +137,59 @@ struct Tag {
*/
gcc_pure
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;
for (unsigned i = 0, n = tag.num_items; i != n; ++i) {
const TagItem &item = *tag.items[i];
for (const auto &item : tag) {
result.push_back('|');
result.append(tag_item_names[item.type]);
result.push_back('=');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment