From 16afdfd8747a1bd5af2d1acb4e0845bf9d0b89e7 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Tue, 29 Jan 2013 23:36:58 +0100
Subject: ArchivePlugin: move instance methods to class ArchiveFile

---
 src/ArchiveFile.hxx                  | 25 +++++++++++++++++
 src/ArchivePlugin.cxx                | 33 -----------------------
 src/ArchivePlugin.hxx                | 33 -----------------------
 src/UpdateArchive.cxx                |  6 ++---
 src/archive/Bzip2ArchivePlugin.cxx   | 52 ++++++++++++++++--------------------
 src/archive/Iso9660ArchivePlugin.cxx | 48 ++++++++++++++-------------------
 src/archive/ZzipArchivePlugin.cxx    | 46 +++++++++++--------------------
 src/input/ArchiveInputPlugin.cxx     |  6 ++---
 test/visit_archive.cxx               |  4 +--
 9 files changed, 92 insertions(+), 161 deletions(-)

diff --git a/src/ArchiveFile.hxx b/src/ArchiveFile.hxx
index 52e5a4910..c7933ebd1 100644
--- a/src/ArchiveFile.hxx
+++ b/src/ArchiveFile.hxx
@@ -26,6 +26,31 @@ public:
 
 	ArchiveFile(const struct archive_plugin &_plugin)
 		:plugin(_plugin) {}
+
+protected:
+	/**
+	 * Use Close() instead of delete.
+	 */
+	~ArchiveFile() {}
+
+public:
+	virtual void Close() = 0;
+
+	/**
+	 * Visit all entries inside this archive.
+	 */
+	virtual void Visit(ArchiveVisitor &visitor) = 0;
+
+	/**
+	 * Opens an input_stream of a file within the archive.
+	 *
+	 * @param path the path within the archive
+	 * @param error_r location to store the error occurring, or
+	 * NULL to ignore errors
+	 */
+	virtual input_stream *OpenStream(const char *path,
+					 Mutex &mutex, Cond &cond,
+					 GError **error_r) = 0;
 };
 
 #endif
diff --git a/src/ArchivePlugin.cxx b/src/ArchivePlugin.cxx
index db4bb1b58..7c5164220 100644
--- a/src/ArchivePlugin.cxx
+++ b/src/ArchivePlugin.cxx
@@ -34,9 +34,6 @@ archive_file_open(const struct archive_plugin *plugin, const char *path,
 	ArchiveFile *file = plugin->open(path, error_r);
 
 	if (file != NULL) {
-		assert(file->plugin.close != NULL);
-		assert(file->plugin.visit != nullptr);
-		assert(file->plugin.open_stream != NULL);
 		assert(error_r == NULL || *error_r == NULL);
 	} else {
 		assert(error_r == NULL || *error_r != NULL);
@@ -44,33 +41,3 @@ archive_file_open(const struct archive_plugin *plugin, const char *path,
 
 	return file;
 }
-
-void
-archive_file_close(ArchiveFile *file)
-{
-	assert(file != NULL);
-	assert(file->plugin.close != NULL);
-
-	file->plugin.close(file);
-}
-
-void
-archive_file_visit(ArchiveFile *file, ArchiveVisitor &visitor)
-{
-	assert(file != NULL);
-	assert(file->plugin.visit != nullptr);
-
-	file->plugin.visit(file, visitor);
-}
-
-struct input_stream *
-archive_file_open_stream(ArchiveFile *file, const char *path,
-			 Mutex &mutex, Cond &cond,
-			 GError **error_r)
-{
-	assert(file != NULL);
-	assert(file->plugin.open_stream != NULL);
-
-	return file->plugin.open_stream(file, path, mutex, cond,
-					 error_r);
-}
diff --git a/src/ArchivePlugin.hxx b/src/ArchivePlugin.hxx
index 6d043dfac..13952940f 100644
--- a/src/ArchivePlugin.hxx
+++ b/src/ArchivePlugin.hxx
@@ -51,28 +51,6 @@ struct archive_plugin {
 	 */
 	ArchiveFile *(*open)(const char *path_fs, GError **error_r);
 
-	/**
-	 * Visit all entries inside this archive.
-	 */
-	void (*visit)(ArchiveFile *af, ArchiveVisitor &visitor);
-
-	/**
-	 * Opens an input_stream of a file within the archive.
-	 *
-	 * @param path the path within the archive
-	 * @param error_r location to store the error occurring, or
-	 * NULL to ignore errors
-	 */
-	struct input_stream *(*open_stream)(ArchiveFile *af,
-					    const char *path,
-					    Mutex &mutex, Cond &cond,
-					    GError **error_r);
-
-	/**
-	 * closes archive file.
-	 */
-	void (*close)(ArchiveFile *);
-
 	/**
 	 * suffixes handled by this plugin.
 	 * last element in these arrays must always be a NULL
@@ -84,15 +62,4 @@ ArchiveFile *
 archive_file_open(const struct archive_plugin *plugin, const char *path,
 		  GError **error_r);
 
-void
-archive_file_close(ArchiveFile *file);
-
-void
-archive_file_visit(ArchiveFile *file, ArchiveVisitor &visitor);
-
-struct input_stream *
-archive_file_open_stream(ArchiveFile *file, const char *path,
-			 Mutex &mutex, Cond &cond,
-			 GError **error_r);
-
 #endif
diff --git a/src/UpdateArchive.cxx b/src/UpdateArchive.cxx
index 41a73b421..133dfd476 100644
--- a/src/UpdateArchive.cxx
+++ b/src/UpdateArchive.cxx
@@ -27,6 +27,7 @@
 #include "fs/Path.hxx"
 #include "ArchiveList.hxx"
 #include "ArchivePlugin.hxx"
+#include "ArchiveFile.hxx"
 #include "ArchiveVisitor.hxx"
 
 #include <glib.h>
@@ -136,9 +137,8 @@ update_archive_file2(Directory *parent, const char *name,
 	};
 
 	UpdateArchiveVisitor visitor(directory);
-	archive_file_visit(file, visitor);
-
-	archive_file_close(file);
+	file->Visit(visitor);
+	file->Close();
 }
 
 bool
diff --git a/src/archive/Bzip2ArchivePlugin.cxx b/src/archive/Bzip2ArchivePlugin.cxx
index d9bbe94ad..182b9ccd1 100644
--- a/src/archive/Bzip2ArchivePlugin.cxx
+++ b/src/archive/Bzip2ArchivePlugin.cxx
@@ -42,7 +42,7 @@
 #define BZ2_bzDecompress bzDecompress
 #endif
 
-class Bzip2ArchiveFile : public ArchiveFile {
+class Bzip2ArchiveFile final : public ArchiveFile {
 public:
 	RefCount ref;
 
@@ -63,6 +63,10 @@ public:
 		input_stream_close(istream);
 	}
 
+	void Ref() {
+		ref.Increment();
+	}
+
 	void Unref() {
 		if (!ref.Decrement())
 			return;
@@ -70,6 +74,18 @@ public:
 		g_free(name);
 		delete this;
 	}
+
+	virtual void Close() override {
+		Unref();
+	}
+
+	virtual void Visit(ArchiveVisitor &visitor) override {
+		visitor.VisitArchiveEntry(name);
+	}
+
+	virtual input_stream *OpenStream(const char *path,
+					 Mutex &mutex, Cond &cond,
+					 GError **error_r) override;
 };
 
 struct Bzip2InputStream {
@@ -142,22 +158,6 @@ bz2_open(const char *pathname, GError **error_r)
 	return new Bzip2ArchiveFile(pathname, is);
 }
 
-static void
-bz2_visit(ArchiveFile *file, ArchiveVisitor &visitor)
-{
-	Bzip2ArchiveFile *context = (Bzip2ArchiveFile *) file;
-
-	visitor.VisitArchiveEntry(context->name);
-}
-
-static void
-bz2_close(ArchiveFile *file)
-{
-	Bzip2ArchiveFile *context = (Bzip2ArchiveFile *) file;
-
-	context->Unref();
-}
-
 /* single archive handling */
 
 Bzip2InputStream::Bzip2InputStream(Bzip2ArchiveFile &_context, const char *uri,
@@ -165,7 +165,7 @@ Bzip2InputStream::Bzip2InputStream(Bzip2ArchiveFile &_context, const char *uri,
 	:base(bz2_inputplugin, uri, mutex, cond),
 	 archive(&_context), eof(false)
 {
-	archive->ref.Increment();
+	archive->Ref();
 }
 
 Bzip2InputStream::~Bzip2InputStream()
@@ -173,15 +173,12 @@ Bzip2InputStream::~Bzip2InputStream()
 	archive->Unref();
 }
 
-static struct input_stream *
-bz2_open_stream(ArchiveFile *file, const char *path,
-		Mutex &mutex, Cond &cond,
-		GError **error_r)
+input_stream *
+Bzip2ArchiveFile::OpenStream(const char *path,
+			     Mutex &mutex, Cond &cond,
+			     GError **error_r)
 {
-	Bzip2ArchiveFile *context = (Bzip2ArchiveFile *) file;
-	Bzip2InputStream *bis =
-		new Bzip2InputStream(*context, path, mutex, cond);
-
+	Bzip2InputStream *bis = new Bzip2InputStream(*this, path, mutex, cond);
 	if (!bis->Open(error_r)) {
 		delete bis;
 		return NULL;
@@ -296,9 +293,6 @@ const struct archive_plugin bz2_archive_plugin = {
 	nullptr,
 	nullptr,
 	bz2_open,
-	bz2_visit,
-	bz2_open_stream,
-	bz2_close,
 	bz2_extensions,
 };
 
diff --git a/src/archive/Iso9660ArchivePlugin.cxx b/src/archive/Iso9660ArchivePlugin.cxx
index 21e2fa41c..97fd8bd52 100644
--- a/src/archive/Iso9660ArchivePlugin.cxx
+++ b/src/archive/Iso9660ArchivePlugin.cxx
@@ -41,7 +41,7 @@
 
 #define CEILING(x, y) ((x+(y-1))/y)
 
-class Iso9660ArchiveFile : public ArchiveFile {
+class Iso9660ArchiveFile final : public ArchiveFile {
 public:
 	RefCount ref;
 
@@ -60,6 +60,16 @@ public:
 	}
 
 	void Visit(const char *path, ArchiveVisitor &visitor);
+
+	virtual void Close() override {
+		Unref();
+	}
+
+	virtual void Visit(ArchiveVisitor &visitor) override;
+
+	virtual input_stream *OpenStream(const char *path,
+					 Mutex &mutex, Cond &cond,
+					 GError **error_r) override;
 };
 
 extern const struct input_plugin iso9660_input_plugin;
@@ -118,22 +128,10 @@ iso9660_archive_open(const char *pathname, GError **error_r)
 	return new Iso9660ArchiveFile(iso);
 }
 
-static void
-iso9660_archive_visit(ArchiveFile *file, ArchiveVisitor &visitor)
-{
-	Iso9660ArchiveFile *context =
-		(Iso9660ArchiveFile *)file;
-
-	context->Visit("/", visitor);
-}
-
-static void
-iso9660_archive_close(ArchiveFile *file)
+void
+Iso9660ArchiveFile::Visit(ArchiveVisitor &visitor)
 {
-	Iso9660ArchiveFile *context =
-		(Iso9660ArchiveFile *)file;
-
-	context->Unref();
+	Visit("/", visitor);
 }
 
 /* single archive handling */
@@ -165,15 +163,12 @@ struct Iso9660InputStream {
 	}
 };
 
-static struct input_stream *
-iso9660_archive_open_stream(ArchiveFile *file, const char *pathname,
-			    Mutex &mutex, Cond &cond,
-			    GError **error_r)
+input_stream *
+Iso9660ArchiveFile::OpenStream(const char *pathname,
+			       Mutex &mutex, Cond &cond,
+			       GError **error_r)
 {
-	Iso9660ArchiveFile *context =
-		(Iso9660ArchiveFile *)file;
-
-	auto statbuf = iso9660_ifs_stat_translate(context->iso, pathname);
+	auto statbuf = iso9660_ifs_stat_translate(iso, pathname);
 	if (statbuf == nullptr) {
 		g_set_error(error_r, iso9660_quark(), 0,
 			    "not found in the ISO file: %s", pathname);
@@ -181,7 +176,7 @@ iso9660_archive_open_stream(ArchiveFile *file, const char *pathname,
 	}
 
 	Iso9660InputStream *iis =
-		new Iso9660InputStream(*context, pathname, mutex, cond,
+		new Iso9660InputStream(*this, pathname, mutex, cond,
 				       statbuf);
 	return &iis->base;
 }
@@ -267,8 +262,5 @@ const struct archive_plugin iso9660_archive_plugin = {
 	nullptr,
 	nullptr,
 	iso9660_archive_open,
-	iso9660_archive_visit,
-	iso9660_archive_open_stream,
-	iso9660_archive_close,
 	iso9660_archive_extensions,
 };
diff --git a/src/archive/ZzipArchivePlugin.cxx b/src/archive/ZzipArchivePlugin.cxx
index 38cb4e92c..d0db7aa37 100644
--- a/src/archive/ZzipArchivePlugin.cxx
+++ b/src/archive/ZzipArchivePlugin.cxx
@@ -35,7 +35,7 @@
 #include <glib.h>
 #include <string.h>
 
-class ZzipArchiveFile : public ArchiveFile {
+class ZzipArchiveFile final : public ArchiveFile {
 public:
 	RefCount ref;
 
@@ -53,7 +53,15 @@ public:
 			delete this;
 	}
 
-	void Visit(ArchiveVisitor &visitor);
+	virtual void Close() override {
+		Unref();
+	}
+
+	virtual void Visit(ArchiveVisitor &visitor) override;
+
+	virtual input_stream *OpenStream(const char *path,
+					 Mutex &mutex, Cond &cond,
+					 GError **error_r) override;
 };
 
 extern const struct input_plugin zzip_input_plugin;
@@ -91,22 +99,6 @@ ZzipArchiveFile::Visit(ArchiveVisitor &visitor)
 			visitor.VisitArchiveEntry(dirent.d_name);
 }
 
-static void
-zzip_archive_visit(ArchiveFile *file, ArchiveVisitor &visitor)
-{
-	ZzipArchiveFile *context = (ZzipArchiveFile *) file;
-
-	context->Visit(visitor);
-}
-
-static void
-zzip_archive_close(ArchiveFile *file)
-{
-	ZzipArchiveFile *context = (ZzipArchiveFile *) file;
-
-	context->Unref();
-}
-
 /* single archive handling */
 
 struct ZzipInputStream {
@@ -138,15 +130,12 @@ struct ZzipInputStream {
 	}
 };
 
-static struct input_stream *
-zzip_archive_open_stream(ArchiveFile *file,
-			 const char *pathname,
-			 Mutex &mutex, Cond &cond,
-			 GError **error_r)
+input_stream *
+ZzipArchiveFile::OpenStream(const char *pathname,
+			    Mutex &mutex, Cond &cond,
+			    GError **error_r)
 {
-	ZzipArchiveFile *context = (ZzipArchiveFile *) file;
-
-	ZZIP_FILE *_file = zzip_file_open(context->dir, pathname, 0);
+	ZZIP_FILE *_file = zzip_file_open(dir, pathname, 0);
 	if (_file == nullptr) {
 		g_set_error(error_r, zzip_quark(), 0,
 			    "not found in the ZIP file: %s", pathname);
@@ -154,7 +143,7 @@ zzip_archive_open_stream(ArchiveFile *file,
 	}
 
 	ZzipInputStream *zis =
-		new ZzipInputStream(*context, pathname,
+		new ZzipInputStream(*this, pathname,
 				    mutex, cond,
 				    _file);
 	return &zis->base;
@@ -237,8 +226,5 @@ const struct archive_plugin zzip_archive_plugin = {
 	nullptr,
 	nullptr,
 	zzip_archive_open,
-	zzip_archive_visit,
-	zzip_archive_open_stream,
-	zzip_archive_close,
 	zzip_archive_extensions,
 };
diff --git a/src/input/ArchiveInputPlugin.cxx b/src/input/ArchiveInputPlugin.cxx
index fde817da7..0d856527f 100644
--- a/src/input/ArchiveInputPlugin.cxx
+++ b/src/input/ArchiveInputPlugin.cxx
@@ -22,6 +22,7 @@
 #include "ArchiveLookup.hxx"
 #include "ArchiveList.hxx"
 #include "ArchivePlugin.hxx"
+#include "ArchiveFile.hxx"
 #include "InputPlugin.hxx"
 
 #include <glib.h>
@@ -69,10 +70,9 @@ input_archive_open(const char *pathname,
 	}
 
 	//setup fileops
-	is = archive_file_open_stream(file, filename, mutex, cond,
-				      error_r);
-	archive_file_close(file);
+	is = file->OpenStream(filename, mutex, cond, error_r);
 	g_free(pname);
+	file->Close();
 
 	return is;
 }
diff --git a/test/visit_archive.cxx b/test/visit_archive.cxx
index eba715c57..6faf4f3ae 100644
--- a/test/visit_archive.cxx
+++ b/test/visit_archive.cxx
@@ -101,8 +101,8 @@ main(int argc, char **argv)
 	ArchiveFile *file = archive_file_open(plugin, path.c_str(), &error);
 	if (file != nullptr) {
 		MyArchiveVisitor visitor;
-		archive_file_visit(file, visitor);
-		archive_file_close(file);
+		file->Visit(visitor);
+		file->Close();
 	} else {
 		fprintf(stderr, "%s\n", error->message);
 		g_error_free(error);
-- 
cgit v1.2.3