Song: embed the Tag object statically into class Song
Reduces overhead because we need to manage only one memory allocation. According to valgrind/massif, we save 7%.
This commit is contained in:
parent
bc966577ff
commit
d2cf74027c
@ -39,9 +39,7 @@ typedef std::set<const char *, StringLess> StringSet;
|
||||
static bool
|
||||
CollectTags(StringSet &set, TagType tag_type, Song &song)
|
||||
{
|
||||
Tag *tag = song.tag;
|
||||
if (tag == nullptr)
|
||||
return true;
|
||||
const Tag *tag = &song.tag;
|
||||
|
||||
bool found = false;
|
||||
for (unsigned i = 0; i < tag->num_items; ++i) {
|
||||
@ -108,8 +106,7 @@ StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
|
||||
{
|
||||
++stats.song_count;
|
||||
|
||||
if (song.tag != nullptr)
|
||||
StatsVisitTag(stats, artists, albums, *song.tag);
|
||||
StatsVisitTag(stats, artists, albums, song.tag);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ PrintSongBrief(Client &client, const Song &song)
|
||||
{
|
||||
song_print_uri(client, song);
|
||||
|
||||
if (song.tag != nullptr && song.tag->has_playlist)
|
||||
if (song.tag.has_playlist)
|
||||
/* this song file has an embedded CUE sheet */
|
||||
print_playlist_in_directory(client, song.parent, song.uri);
|
||||
|
||||
@ -82,7 +82,7 @@ PrintSongFull(Client &client, const Song &song)
|
||||
{
|
||||
song_print_info(client, song);
|
||||
|
||||
if (song.tag != nullptr && song.tag->has_playlist)
|
||||
if (song.tag.has_playlist)
|
||||
/* this song file has an embedded CUE sheet */
|
||||
print_playlist_in_directory(client, song.parent, song.uri);
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
DetachedSong::DetachedSong(const Song &other)
|
||||
:uri(other.GetURI().c_str()),
|
||||
tag(other.tag != nullptr ? *other.tag : Tag()),
|
||||
tag(other.tag),
|
||||
mtime(other.mtime),
|
||||
start_ms(other.start_ms), end_ms(other.end_ms) {}
|
||||
|
||||
|
@ -49,9 +49,7 @@ UpdatePlaylistSong(const Database &db, DetachedSong &song)
|
||||
}
|
||||
|
||||
song.SetLastModified(original->mtime);
|
||||
|
||||
if (original->tag != nullptr)
|
||||
song.SetTag(*original->tag);
|
||||
song.SetTag(original->tag);
|
||||
|
||||
db.ReturnSong(original);
|
||||
return true;
|
||||
|
@ -29,14 +29,13 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
inline Song::Song(const char *_uri, size_t uri_length, Directory *_parent)
|
||||
:tag(nullptr), parent(_parent), mtime(0), start_ms(0), end_ms(0)
|
||||
:parent(_parent), mtime(0), start_ms(0), end_ms(0)
|
||||
{
|
||||
memcpy(uri, _uri, uri_length + 1);
|
||||
}
|
||||
|
||||
inline Song::~Song()
|
||||
{
|
||||
delete tag;
|
||||
}
|
||||
|
||||
static Song *
|
||||
@ -57,7 +56,7 @@ Song *
|
||||
Song::NewFrom(DetachedSong &&other, Directory *parent)
|
||||
{
|
||||
Song *song = song_alloc(other.GetURI(), parent);
|
||||
song->tag = new Tag(std::move(other.WritableTag()));
|
||||
song->tag = std::move(other.WritableTag());
|
||||
song->mtime = other.GetLastModified();
|
||||
song->start_ms = other.GetStartMS();
|
||||
song->end_ms = other.GetEndMS();
|
||||
@ -101,8 +100,8 @@ Song::GetDuration() const
|
||||
if (end_ms > 0)
|
||||
return (end_ms - start_ms) / 1000.0;
|
||||
|
||||
if (tag == nullptr)
|
||||
if (tag.time <= 0)
|
||||
return 0;
|
||||
|
||||
return tag->time - start_ms / 1000.0;
|
||||
return tag.time - start_ms / 1000.0;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define MPD_SONG_HXX
|
||||
|
||||
#include "util/list.h"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "Compiler.h"
|
||||
|
||||
#include <string>
|
||||
@ -31,7 +32,6 @@
|
||||
#define SONG_FILE "file: "
|
||||
#define SONG_TIME "Time: "
|
||||
|
||||
struct Tag;
|
||||
struct Directory;
|
||||
class DetachedSong;
|
||||
|
||||
@ -49,7 +49,7 @@ struct Song {
|
||||
*/
|
||||
struct list_head siblings;
|
||||
|
||||
Tag *tag;
|
||||
Tag tag;
|
||||
|
||||
/**
|
||||
* The #Directory that contains this song. May be nullptr if
|
||||
|
@ -149,7 +149,7 @@ SongFilter::Item::Match(const Song &song) const
|
||||
return StringMatch(uri.c_str());
|
||||
}
|
||||
|
||||
return song.tag != NULL && Match(*song.tag);
|
||||
return Match(song.tag);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -74,8 +74,7 @@ song_print_info(Client &client, const Song &song)
|
||||
if (song.mtime > 0)
|
||||
time_print(client, "Last-Modified", song.mtime);
|
||||
|
||||
if (song.tag != nullptr)
|
||||
tag_print(client, *song.tag);
|
||||
tag_print(client, song.tag);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -53,8 +53,7 @@ song_save(FILE *fp, const Song &song)
|
||||
|
||||
range_save(fp, song.start_ms, song.end_ms);
|
||||
|
||||
if (song.tag != nullptr)
|
||||
tag_save(fp, *song.tag);
|
||||
tag_save(fp, song.tag);
|
||||
|
||||
fprintf(fp, SONG_MTIME ": %li\n", (long)song.mtime);
|
||||
fprintf(fp, SONG_END "\n");
|
||||
|
@ -30,14 +30,6 @@ extern "C" {
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char *
|
||||
tag_get_value_checked(const Tag *tag, TagType type)
|
||||
{
|
||||
return tag != nullptr
|
||||
? tag->GetValue(type)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_utf8_string(const char *a, const char *b)
|
||||
{
|
||||
@ -55,11 +47,11 @@ compare_utf8_string(const char *a, const char *b)
|
||||
* nullptr.
|
||||
*/
|
||||
static int
|
||||
compare_string_tag_item(const Tag *a, const Tag *b,
|
||||
compare_string_tag_item(const Tag &a, const Tag &b,
|
||||
TagType type)
|
||||
{
|
||||
return compare_utf8_string(tag_get_value_checked(a, type),
|
||||
tag_get_value_checked(b, type));
|
||||
return compare_utf8_string(a.GetValue(type),
|
||||
b.GetValue(type));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,10 +74,10 @@ compare_number_string(const char *a, const char *b)
|
||||
}
|
||||
|
||||
static int
|
||||
compare_tag_item(const Tag *a, const Tag *b, TagType type)
|
||||
compare_tag_item(const Tag &a, const Tag &b, TagType type)
|
||||
{
|
||||
return compare_number_string(tag_get_value_checked(a, type),
|
||||
tag_get_value_checked(b, type));
|
||||
return compare_number_string(a.GetValue(type),
|
||||
b.GetValue(type));
|
||||
}
|
||||
|
||||
/* Only used for sorting/searchin a songvec, not general purpose compares */
|
||||
|
@ -98,8 +98,7 @@ Song::UpdateFile()
|
||||
|
||||
mtime = st.st_mtime;
|
||||
|
||||
delete tag;
|
||||
tag = tag_builder.CommitNew();
|
||||
tag_builder.Commit(tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -123,8 +122,7 @@ Song::UpdateFileInArchive()
|
||||
if (!tag_stream_scan(path_fs.c_str(), full_tag_handler, &tag_builder))
|
||||
return false;
|
||||
|
||||
delete tag;
|
||||
tag = tag_builder.CommitNew();
|
||||
tag_builder.Commit(tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,7 @@ update_container_file(Directory &directory,
|
||||
plugin.ScanFile(child_path_fs.c_str(),
|
||||
add_tag_handler, &tag_builder);
|
||||
|
||||
if (tag_builder.IsDefined())
|
||||
song->tag = tag_builder.CommitNew();
|
||||
else
|
||||
tag_builder.Clear();
|
||||
tag_builder.Commit(song->tag);
|
||||
|
||||
db_lock();
|
||||
contdir->AddSong(song);
|
||||
|
@ -524,7 +524,7 @@ Convert(const struct mpd_song *song)
|
||||
for (const auto *i = &tag_table[0]; i->d != TAG_NUM_OF_ITEM_TYPES; ++i)
|
||||
Copy(tag, i->d, song, i->s);
|
||||
|
||||
s->tag = tag.CommitNew();
|
||||
tag.Commit(s->tag);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ upnpItemToSong(UPnPDirObject &&dirent, const char *uri)
|
||||
uri = dirent.url.c_str();
|
||||
|
||||
Song *s = Song::NewFile(uri, nullptr);
|
||||
s->tag = new Tag(std::move(dirent.tag));
|
||||
s->tag = std::move(dirent.tag);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user