From 29747a213f099450537386e917bd485aefd16959 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max.kellermann@gmail.com>
Date: Fri, 12 Jul 2024 15:24:53 +0200
Subject: [PATCH] playlist/Registry: replace playlist_plugins_for_each() with a
 container class

---
 src/CommandLine.cxx               |  5 +++--
 src/playlist/PlaylistRegistry.cxx | 37 ++++++++++++++++++-------------
 src/playlist/PlaylistRegistry.hxx | 17 +++++++-------
 3 files changed, 32 insertions(+), 27 deletions(-)

diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx
index 393269fcb..23ed7816a 100644
--- a/src/CommandLine.cxx
+++ b/src/CommandLine.cxx
@@ -218,8 +218,9 @@ static void version()
 
 	fmt::print("\n\n"
 		   "Playlist plugins:\n");
-	playlist_plugins_for_each(plugin)
-		fmt::print(" {}", plugin->name);
+	for (const auto &plugin : GetAllPlaylistPlugins()) {
+		fmt::print(" {}", plugin.name);
+	}
 
 	fmt::print("\n\n"
 		   "Protocols:\n");
diff --git a/src/playlist/PlaylistRegistry.cxx b/src/playlist/PlaylistRegistry.cxx
index 8af50d800..4a5e97594 100644
--- a/src/playlist/PlaylistRegistry.cxx
+++ b/src/playlist/PlaylistRegistry.cxx
@@ -18,6 +18,7 @@
 #include "plugins/EmbeddedCuePlaylistPlugin.hxx"
 #include "decoder/Features.h"
 #include "input/InputStream.hxx"
+#include "util/FilteredContainer.hxx"
 #include "util/MimeType.hxx"
 #include "util/UriExtract.hxx"
 #include "config/Data.hxx"
@@ -57,9 +58,12 @@ static bool playlist_plugins_enabled[n_playlist_plugins];
 /** which plugins have the "as_folder" option enabled? */
 static bool playlist_plugins_as_folder[n_playlist_plugins];
 
-#define playlist_plugins_for_each_enabled(plugin) \
-	playlist_plugins_for_each(plugin) \
-		if (playlist_plugins_enabled[playlist_plugin_iterator - playlist_plugins])
+static inline auto
+GetEnabledPlaylistPlugins() noexcept
+{
+	const auto all = GetAllPlaylistPlugins();
+	return FilteredContainer{all.begin(), all.end(), playlist_plugins_enabled};
+}
 
 void
 playlist_list_global_init(const ConfigData &config)
@@ -92,8 +96,9 @@ playlist_list_global_init(const ConfigData &config)
 void
 playlist_list_global_finish() noexcept
 {
-	playlist_plugins_for_each_enabled(plugin)
-		playlist_plugin_finish(plugin);
+	for (const auto &plugin : GetEnabledPlaylistPlugins()) {
+		playlist_plugin_finish(&plugin);
+	}
 }
 
 bool
@@ -179,9 +184,9 @@ playlist_list_open_uri(const char *uri, Mutex &mutex)
 static std::unique_ptr<SongEnumerator>
 playlist_list_open_stream_mime2(InputStreamPtr &&is, std::string_view mime)
 {
-	playlist_plugins_for_each_enabled(plugin) {
-		if (plugin->open_stream != nullptr &&
-		    plugin->SupportsMimeType(mime)) {
+	for (const auto &plugin : GetEnabledPlaylistPlugins()) {
+		if (plugin.open_stream != nullptr &&
+		    plugin.SupportsMimeType(mime)) {
 			/* rewind the stream, so each plugin gets a
 			   fresh start */
 			try {
@@ -189,7 +194,7 @@ playlist_list_open_stream_mime2(InputStreamPtr &&is, std::string_view mime)
 			} catch (...) {
 			}
 
-			auto playlist = plugin->open_stream(std::move(is));
+			auto playlist = plugin.open_stream(std::move(is));
 			if (playlist != nullptr)
 				return playlist;
 		}
@@ -209,9 +214,9 @@ playlist_list_open_stream_mime(InputStreamPtr &&is, std::string_view mime)
 std::unique_ptr<SongEnumerator>
 playlist_list_open_stream_suffix(InputStreamPtr &&is, std::string_view suffix)
 {
-	playlist_plugins_for_each_enabled(plugin) {
-		if (plugin->open_stream != nullptr &&
-		    plugin->SupportsSuffix(suffix)) {
+	for (const auto &plugin : GetEnabledPlaylistPlugins()) {
+		if (plugin.open_stream != nullptr &&
+		    plugin.SupportsSuffix(suffix)) {
 			/* rewind the stream, so each plugin gets a
 			   fresh start */
 			try {
@@ -219,7 +224,7 @@ playlist_list_open_stream_suffix(InputStreamPtr &&is, std::string_view suffix)
 			} catch (...) {
 			}
 
-			auto playlist = plugin->open_stream(std::move(is));
+			auto playlist = plugin.open_stream(std::move(is));
 			if (playlist != nullptr)
 				return playlist;
 		}
@@ -257,9 +262,9 @@ playlist_list_open_stream(InputStreamPtr &&is, const char *uri)
 const PlaylistPlugin *
 FindPlaylistPluginBySuffix(std::string_view suffix) noexcept
 {
-	playlist_plugins_for_each_enabled(plugin) {
-		if (plugin->SupportsSuffix(suffix))
-			return plugin;
+	for (const auto &plugin : GetEnabledPlaylistPlugins()) {
+		if (plugin.SupportsSuffix(suffix))
+			return &plugin;
 	}
 
 	return nullptr;
diff --git a/src/playlist/PlaylistRegistry.hxx b/src/playlist/PlaylistRegistry.hxx
index e5f85d47e..2ad66a559 100644
--- a/src/playlist/PlaylistRegistry.hxx
+++ b/src/playlist/PlaylistRegistry.hxx
@@ -1,11 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 // Copyright The Music Player Daemon Project
 
-#ifndef MPD_PLAYLIST_REGISTRY_HXX
-#define MPD_PLAYLIST_REGISTRY_HXX
+#pragma once
 
 #include "input/Ptr.hxx"
 #include "thread/Mutex.hxx"
+#include "util/DereferenceIterator.hxx"
+#include "util/TerminatedArray.hxx"
 
 #include <string_view>
 
@@ -15,11 +16,11 @@ class SongEnumerator;
 
 extern const PlaylistPlugin *const playlist_plugins[];
 
-#define playlist_plugins_for_each(plugin) \
-	for (const PlaylistPlugin *plugin, \
-		*const*playlist_plugin_iterator = &playlist_plugins[0]; \
-		(plugin = *playlist_plugin_iterator) != nullptr; \
-		++playlist_plugin_iterator)
+static inline auto
+GetAllPlaylistPlugins() noexcept
+{
+	return DereferenceContainerAdapter{TerminatedArray<const PlaylistPlugin *const, nullptr>{playlist_plugins}};
+}
 
 /**
  * Initializes all playlist plugins.
@@ -85,5 +86,3 @@ playlist_suffix_supported(std::string_view suffix) noexcept
 {
 	return FindPlaylistPluginBySuffix(suffix) != nullptr;
 }
-
-#endif