From 8cad20585dbbf5987d6649bea9c6b6ba688b7bff Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 29 Jan 2013 18:51:40 +0100 Subject: playlist/memory: use std::forward_list instead of GSList --- Makefile.am | 1 + src/SongPointer.hxx | 63 +++++++++++++++++++++++++++++++ src/playlist/AsxPlaylistPlugin.cxx | 25 +++--------- src/playlist/DespotifyPlaylistPlugin.cxx | 21 ++++------- src/playlist/MemoryPlaylistProvider.cxx | 27 +++---------- src/playlist/MemoryPlaylistProvider.hxx | 8 ++-- src/playlist/PlsPlaylistPlugin.cxx | 18 ++++----- src/playlist/RssPlaylistPlugin.cxx | 24 +++--------- src/playlist/SoundCloudPlaylistPlugin.cxx | 9 +++-- src/playlist/XspfPlaylistPlugin.cxx | 25 +++--------- 10 files changed, 109 insertions(+), 112 deletions(-) create mode 100644 src/SongPointer.hxx diff --git a/Makefile.am b/Makefile.am index f39ab87c0..f8b4b581d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -269,6 +269,7 @@ src_mpd_SOURCES = \ src/string_util.c \ src/Volume.cxx src/Volume.hxx \ src/SongFilter.cxx src/SongFilter.hxx \ + src/SongPointer.hxx \ src/PlaylistFile.cxx src/PlaylistFile.hxx \ src/timer.c diff --git a/src/SongPointer.hxx b/src/SongPointer.hxx new file mode 100644 index 000000000..c80f96f4d --- /dev/null +++ b/src/SongPointer.hxx @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * 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. + * + * 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. + */ + +#ifndef MPD_SONG_POINTER_HXX +#define MPD_SONG_POINTER_HXX + +#include "song.h" + +#include + +class SongPointer { + struct song *song; + +public: + explicit SongPointer(struct song *_song) + :song(_song) {} + + SongPointer(const SongPointer &) = delete; + + SongPointer(SongPointer &&other):song(other.song) { + other.song = nullptr; + } + + ~SongPointer() { + if (song != nullptr) + song_free(song); + } + + SongPointer &operator=(const SongPointer &) = delete; + + SongPointer &operator=(SongPointer &&other) { + std::swap(song, other.song); + return *this; + } + + operator const struct song *() const { + return song; + } + + struct song *Steal() { + auto result = song; + song = nullptr; + return result; + } +}; + +#endif diff --git a/src/playlist/AsxPlaylistPlugin.cxx b/src/playlist/AsxPlaylistPlugin.cxx index db571417c..25319ca6b 100644 --- a/src/playlist/AsxPlaylistPlugin.cxx +++ b/src/playlist/AsxPlaylistPlugin.cxx @@ -40,7 +40,7 @@ struct AsxParser { * The list of songs (in reverse order because that's faster * while adding). */ - GSList *songs; + std::forward_list songs; /** * The current position in the XML file. @@ -63,8 +63,7 @@ struct AsxParser { struct song *song; AsxParser() - :songs(nullptr), - state(ROOT) {} + :state(ROOT) {} }; @@ -144,8 +143,7 @@ asx_end_element(G_GNUC_UNUSED GMarkupParseContext *context, case AsxParser::ENTRY: if (g_ascii_strcasecmp(element_name, "entry") == 0) { if (strcmp(parser->song->uri, "asx:") != 0) - parser->songs = g_slist_prepend(parser->songs, - parser->song); + parser->songs.emplace_front(parser->song); else song_free(parser->song); @@ -188,14 +186,6 @@ static const GMarkupParser asx_parser = { nullptr, }; -static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = (struct song *)data; - - song_free(song); -} - static void asx_parser_destroy(gpointer data) { @@ -203,9 +193,6 @@ asx_parser_destroy(gpointer data) if (parser->state >= AsxParser::ENTRY) song_free(parser->song); - - g_slist_foreach(parser->songs, song_free_callback, NULL); - g_slist_free(parser->songs); } /* @@ -261,11 +248,9 @@ asx_open_stream(struct input_stream *is) return NULL; } - /* create a #AsxPlaylist object from the parsed song list */ - + parser.songs.reverse(); MemoryPlaylistProvider *playlist = - new MemoryPlaylistProvider(g_slist_reverse(parser.songs)); - parser.songs = NULL; + new MemoryPlaylistProvider(std::move(parser.songs)); g_markup_parse_context_free(context); diff --git a/src/playlist/DespotifyPlaylistPlugin.cxx b/src/playlist/DespotifyPlaylistPlugin.cxx index 09c1aa899..17bcf0f6c 100644 --- a/src/playlist/DespotifyPlaylistPlugin.cxx +++ b/src/playlist/DespotifyPlaylistPlugin.cxx @@ -35,7 +35,8 @@ extern "C" { struct despotify_playlist { struct despotify_session *session; - GSList *list; + + std::forward_list songs; }; static void @@ -59,7 +60,7 @@ add_song(struct despotify_playlist *ctx, struct ds_track *track) song = song_remote_new(uri); song->tag = mpd_despotify_tag_from_track(track); - ctx->list = g_slist_prepend(ctx->list, song); + ctx->songs.emplace_front(song); } static bool @@ -115,17 +116,16 @@ despotify_playlist_open_uri(const char *url, session = mpd_despotify_get_session(); if (!session) - goto clean_none; + return nullptr; /* Get link without spt:// */ link = despotify_link_from_uri(url + strlen(despotify_playlist_plugin.schemes[0]) + 3); if (!link) { g_debug("Can't find %s\n", url); - goto clean_none; + return nullptr; } struct despotify_playlist ctx; - ctx.list = nullptr; ctx.session = session; switch (link->type) @@ -142,15 +142,10 @@ despotify_playlist_open_uri(const char *url, } despotify_free_link(link); if (!parse_result) - goto clean_playlist; - - return new MemoryPlaylistProvider(g_slist_reverse(ctx.list)); - -clean_playlist: - g_slist_free(ctx.list); -clean_none: + return nullptr; - return nullptr; + ctx.songs.reverse(); + return new MemoryPlaylistProvider(std::move(ctx.songs)); } static const char *const despotify_schemes[] = { diff --git a/src/playlist/MemoryPlaylistProvider.cxx b/src/playlist/MemoryPlaylistProvider.cxx index b643ec50c..4fe3d6cef 100644 --- a/src/playlist/MemoryPlaylistProvider.cxx +++ b/src/playlist/MemoryPlaylistProvider.cxx @@ -52,33 +52,18 @@ static constexpr struct playlist_plugin memory_playlist_plugin = { nullptr, }; -MemoryPlaylistProvider::MemoryPlaylistProvider(GSList *_songs) - :songs(_songs) { +MemoryPlaylistProvider::MemoryPlaylistProvider(std::forward_list &&_songs) + :songs(std::move(_songs)) { playlist_provider_init(this, &memory_playlist_plugin); } -static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = (struct song *)data; - - song_free(song); -} - -MemoryPlaylistProvider::~MemoryPlaylistProvider() -{ - g_slist_foreach(songs, song_free_callback, NULL); - g_slist_free(songs); -} - inline song * MemoryPlaylistProvider::Read() { - if (songs == nullptr) - return nullptr; + if (songs.empty()) + return NULL; - song *result = (song *)songs->data; - songs = g_slist_remove(songs, result); + auto result = songs.front().Steal(); + songs.pop_front(); return result; } - diff --git a/src/playlist/MemoryPlaylistProvider.hxx b/src/playlist/MemoryPlaylistProvider.hxx index ad0a74d8a..246ffd10a 100644 --- a/src/playlist/MemoryPlaylistProvider.hxx +++ b/src/playlist/MemoryPlaylistProvider.hxx @@ -21,17 +21,17 @@ #define MPD_MEMORY_PLAYLIST_PROVIDER_HXX #include "PlaylistPlugin.hxx" +#include "SongPointer.hxx" -#include +#include struct song; class MemoryPlaylistProvider : public playlist_provider { - GSList *songs; + std::forward_list songs; public: - MemoryPlaylistProvider(GSList *_songs); - ~MemoryPlaylistProvider(); + MemoryPlaylistProvider(std::forward_list &&_songs); song *Read(); }; diff --git a/src/playlist/PlsPlaylistPlugin.cxx b/src/playlist/PlsPlaylistPlugin.cxx index cecabc88e..3cf5f46e5 100644 --- a/src/playlist/PlsPlaylistPlugin.cxx +++ b/src/playlist/PlsPlaylistPlugin.cxx @@ -27,11 +27,8 @@ #include -struct PlsPlaylist { - GSList *songs; -}; - -static void pls_parser(GKeyFile *keyfile, PlsPlaylist *playlist) +static void +pls_parser(GKeyFile *keyfile, std::forward_list &songs) { gchar *key; gchar *value; @@ -96,7 +93,7 @@ static void pls_parser(GKeyFile *keyfile, PlsPlaylist *playlist) if(error) g_error_free(error); error = NULL; - playlist->songs = g_slist_prepend(playlist->songs, song); + songs.emplace_front(song); num_entries--; } @@ -150,13 +147,12 @@ pls_open_stream(struct input_stream *is) return NULL; } - PlsPlaylist playlist; - playlist.songs = nullptr; - - pls_parser(keyfile, &playlist); + std::forward_list songs; + pls_parser(keyfile, songs); g_key_file_free(keyfile); - return new MemoryPlaylistProvider(g_slist_reverse(playlist.songs)); + songs.reverse(); + return new MemoryPlaylistProvider(std::move(songs)); } static const char *const pls_suffixes[] = { diff --git a/src/playlist/RssPlaylistPlugin.cxx b/src/playlist/RssPlaylistPlugin.cxx index 1c714a965..3b69202e6 100644 --- a/src/playlist/RssPlaylistPlugin.cxx +++ b/src/playlist/RssPlaylistPlugin.cxx @@ -40,7 +40,7 @@ struct RssParser { * The list of songs (in reverse order because that's faster * while adding). */ - GSList *songs; + std::forward_list songs; /** * The current position in the XML file. @@ -63,7 +63,7 @@ struct RssParser { struct song *song; RssParser() - :songs(nullptr), state(ROOT) {} + :state(ROOT) {} }; static const gchar * @@ -140,8 +140,7 @@ rss_end_element(G_GNUC_UNUSED GMarkupParseContext *context, case RssParser::ITEM: if (g_ascii_strcasecmp(element_name, "item") == 0) { if (strcmp(parser->song->uri, "rss:") != 0) - parser->songs = g_slist_prepend(parser->songs, - parser->song); + parser->songs.emplace_front(parser->song); else song_free(parser->song); @@ -184,14 +183,6 @@ static const GMarkupParser rss_parser = { nullptr, }; -static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = (struct song *)data; - - song_free(song); -} - static void rss_parser_destroy(gpointer data) { @@ -199,9 +190,6 @@ rss_parser_destroy(gpointer data) if (parser->state >= RssParser::ITEM) song_free(parser->song); - - g_slist_foreach(parser->songs, song_free_callback, NULL); - g_slist_free(parser->songs); } /* @@ -257,11 +245,9 @@ rss_open_stream(struct input_stream *is) return NULL; } - /* create a #rss_playlist object from the parsed song list */ - + parser.songs.reverse(); MemoryPlaylistProvider *playlist = - new MemoryPlaylistProvider(g_slist_reverse(parser.songs)); - parser.songs = NULL; + new MemoryPlaylistProvider(std::move(parser.songs)); g_markup_parse_context_free(context); diff --git a/src/playlist/SoundCloudPlaylistPlugin.cxx b/src/playlist/SoundCloudPlaylistPlugin.cxx index b236481a0..5a258865c 100644 --- a/src/playlist/SoundCloudPlaylistPlugin.cxx +++ b/src/playlist/SoundCloudPlaylistPlugin.cxx @@ -101,7 +101,8 @@ struct parse_data { long duration; char* title; int got_url; /* nesting level of last stream_url */ - GSList* songs; + + std::forward_list songs; }; static int handle_integer(void *ctx, @@ -215,7 +216,7 @@ static int handle_end_map(void *ctx) tag_add_item(t, TAG_NAME, data->title); s->tag = t; - data->songs = g_slist_prepend(data->songs, s); + data->songs.emplace_front(s); return 1; } @@ -370,7 +371,6 @@ soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond) struct parse_data data; data.got_url = 0; - data.songs = NULL; data.title = NULL; data.stream_url = NULL; #ifdef HAVE_YAJL1 @@ -391,7 +391,8 @@ soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond) if (ret == -1) return NULL; - return new MemoryPlaylistProvider(g_slist_reverse(data.songs)); + data.songs.reverse(); + return new MemoryPlaylistProvider(std::move(data.songs)); } static const char *const soundcloud_schemes[] = { diff --git a/src/playlist/XspfPlaylistPlugin.cxx b/src/playlist/XspfPlaylistPlugin.cxx index 38bcbdf9d..bd84d86b7 100644 --- a/src/playlist/XspfPlaylistPlugin.cxx +++ b/src/playlist/XspfPlaylistPlugin.cxx @@ -22,7 +22,6 @@ #include "MemoryPlaylistProvider.hxx" #include "input_stream.h" #include "uri.h" -#include "song.h" #include "tag.h" #include @@ -41,7 +40,7 @@ struct XspfParser { * The list of songs (in reverse order because that's faster * while adding). */ - GSList *songs; + std::forward_list songs; /** * The current position in the XML file. @@ -65,7 +64,7 @@ struct XspfParser { struct song *song; XspfParser() - :songs(nullptr), state(ROOT) {} + :state(ROOT) {} }; static void @@ -148,8 +147,7 @@ xspf_end_element(G_GNUC_UNUSED GMarkupParseContext *context, case XspfParser::TRACK: if (strcmp(element_name, "track") == 0) { if (parser->song != NULL) - parser->songs = g_slist_prepend(parser->songs, - parser->song); + parser->songs.emplace_front(parser->song); parser->state = XspfParser::TRACKLIST; } else @@ -206,14 +204,6 @@ static const GMarkupParser xspf_parser = { nullptr, }; -static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = (struct song *)data; - - song_free(song); -} - static void xspf_parser_destroy(gpointer data) { @@ -221,9 +211,6 @@ xspf_parser_destroy(gpointer data) if (parser->state >= XspfParser::TRACK && parser->song != NULL) song_free(parser->song); - - g_slist_foreach(parser->songs, song_free_callback, NULL); - g_slist_free(parser->songs); } /* @@ -279,11 +266,9 @@ xspf_open_stream(struct input_stream *is) return NULL; } - /* create a #xspf_playlist object from the parsed song list */ - + parser.songs.reverse(); MemoryPlaylistProvider *playlist = - new MemoryPlaylistProvider(g_slist_reverse(parser.songs)); - parser.songs = NULL; + new MemoryPlaylistProvider(std::move(parser.songs)); g_markup_parse_context_free(context); -- cgit v1.2.3