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