playlist/memory: use std::forward_list instead of GSList
This commit is contained in:
		| @@ -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 | ||||
|  | ||||
|   | ||||
							
								
								
									
										63
									
								
								src/SongPointer.hxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/SongPointer.hxx
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <utility> | ||||
|  | ||||
| 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 | ||||
| @@ -40,7 +40,7 @@ struct AsxParser { | ||||
| 	 * The list of songs (in reverse order because that's faster | ||||
| 	 * while adding). | ||||
| 	 */ | ||||
| 	GSList *songs; | ||||
| 	std::forward_list<SongPointer> 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); | ||||
|  | ||||
|   | ||||
| @@ -35,7 +35,8 @@ extern "C" { | ||||
|  | ||||
| struct despotify_playlist { | ||||
| 	struct despotify_session *session; | ||||
| 	GSList *list; | ||||
|  | ||||
| 	std::forward_list<SongPointer> 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 nullptr; | ||||
|  | ||||
| 	return new MemoryPlaylistProvider(g_slist_reverse(ctx.list)); | ||||
|  | ||||
| clean_playlist: | ||||
| 	g_slist_free(ctx.list); | ||||
| clean_none: | ||||
|  | ||||
| 	return nullptr; | ||||
| 	ctx.songs.reverse(); | ||||
| 	return new MemoryPlaylistProvider(std::move(ctx.songs)); | ||||
| } | ||||
|  | ||||
| static const char *const despotify_schemes[] = { | ||||
|   | ||||
| @@ -52,33 +52,18 @@ static constexpr struct playlist_plugin memory_playlist_plugin = { | ||||
| 	nullptr, | ||||
| }; | ||||
|  | ||||
| MemoryPlaylistProvider::MemoryPlaylistProvider(GSList *_songs) | ||||
| 	:songs(_songs) { | ||||
| MemoryPlaylistProvider::MemoryPlaylistProvider(std::forward_list<SongPointer> &&_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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,17 +21,17 @@ | ||||
| #define MPD_MEMORY_PLAYLIST_PROVIDER_HXX | ||||
|  | ||||
| #include "PlaylistPlugin.hxx" | ||||
| #include "SongPointer.hxx" | ||||
|  | ||||
| #include <glib.h> | ||||
| #include <forward_list> | ||||
|  | ||||
| struct song; | ||||
|  | ||||
| class MemoryPlaylistProvider : public playlist_provider { | ||||
| 	GSList *songs; | ||||
| 	std::forward_list<SongPointer> songs; | ||||
|  | ||||
| public: | ||||
| 	MemoryPlaylistProvider(GSList *_songs); | ||||
| 	~MemoryPlaylistProvider(); | ||||
| 	MemoryPlaylistProvider(std::forward_list<SongPointer> &&_songs); | ||||
|  | ||||
| 	song *Read(); | ||||
| }; | ||||
|   | ||||
| @@ -27,11 +27,8 @@ | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| struct PlsPlaylist { | ||||
| 	GSList *songs; | ||||
| }; | ||||
|  | ||||
| static void pls_parser(GKeyFile *keyfile, PlsPlaylist *playlist) | ||||
| static void | ||||
| pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &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<SongPointer> 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[] = { | ||||
|   | ||||
| @@ -40,7 +40,7 @@ struct RssParser { | ||||
| 	 * The list of songs (in reverse order because that's faster | ||||
| 	 * while adding). | ||||
| 	 */ | ||||
| 	GSList *songs; | ||||
| 	std::forward_list<SongPointer> 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); | ||||
|  | ||||
|   | ||||
| @@ -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<SongPointer> 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[] = { | ||||
|   | ||||
| @@ -22,7 +22,6 @@ | ||||
| #include "MemoryPlaylistProvider.hxx" | ||||
| #include "input_stream.h" | ||||
| #include "uri.h" | ||||
| #include "song.h" | ||||
| #include "tag.h" | ||||
|  | ||||
| #include <glib.h> | ||||
| @@ -41,7 +40,7 @@ struct XspfParser { | ||||
| 	 * The list of songs (in reverse order because that's faster | ||||
| 	 * while adding). | ||||
| 	 */ | ||||
| 	GSList *songs; | ||||
| 	std::forward_list<SongPointer> 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); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann