From 9f0fb8f6a8f58ff9a760d40bccfadd010b9ddef9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 29 Jan 2013 21:21:07 +0100 Subject: ArchivePlugin: replace scan_reset(), scan_next() with visit() Add the interface ArchiveVisitor. --- Makefile.am | 1 + src/ArchivePlugin.cxx | 20 +++----------- src/ArchivePlugin.hxx | 19 +++----------- src/ArchiveVisitor.hxx | 28 ++++++++++++++++++++ src/UpdateArchive.cxx | 22 +++++++++++----- src/archive/Bzip2ArchivePlugin.cxx | 22 +++------------- src/archive/Iso9660ArchivePlugin.cxx | 45 +++++++------------------------ src/archive/ZzipArchivePlugin.cxx | 51 ++++++++++++------------------------ 8 files changed, 83 insertions(+), 125 deletions(-) create mode 100644 src/ArchiveVisitor.hxx diff --git a/Makefile.am b/Makefile.am index f8b4b581d..c3b52ebd6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -398,6 +398,7 @@ libarchive_a_SOURCES = \ src/ArchiveLookup.cxx src/ArchiveLookup.hxx \ src/ArchiveList.cxx src/ArchiveList.hxx \ src/ArchivePlugin.cxx src/ArchivePlugin.hxx \ + src/ArchiveVisitor.hxx \ src/ArchiveInternal.hxx \ src/input/ArchiveInputPlugin.cxx src/input/ArchiveInputPlugin.hxx libarchive_a_CPPFLAGS = $(AM_CPPFLAGS) \ diff --git a/src/ArchivePlugin.cxx b/src/ArchivePlugin.cxx index 55721efc3..95f49a2f8 100644 --- a/src/ArchivePlugin.cxx +++ b/src/ArchivePlugin.cxx @@ -38,8 +38,7 @@ archive_file_open(const struct archive_plugin *plugin, const char *path, if (file != NULL) { assert(file->plugin != NULL); assert(file->plugin->close != NULL); - assert(file->plugin->scan_reset != NULL); - assert(file->plugin->scan_next != NULL); + assert(file->plugin->visit != nullptr); assert(file->plugin->open_stream != NULL); assert(error_r == NULL || *error_r == NULL); } else { @@ -60,24 +59,13 @@ archive_file_close(struct archive_file *file) } void -archive_file_scan_reset(struct archive_file *file) +archive_file_visit(archive_file *file, ArchiveVisitor &visitor) { assert(file != NULL); assert(file->plugin != NULL); - assert(file->plugin->scan_reset != NULL); - assert(file->plugin->scan_next != NULL); + assert(file->plugin->visit != nullptr); - file->plugin->scan_reset(file); -} - -const char * -archive_file_scan_next(struct archive_file *file) -{ - assert(file != NULL); - assert(file->plugin != NULL); - assert(file->plugin->scan_next != NULL); - - return file->plugin->scan_next(file); + file->plugin->visit(file, visitor); } struct input_stream * diff --git a/src/ArchivePlugin.hxx b/src/ArchivePlugin.hxx index 448a1941c..007a4f15a 100644 --- a/src/ArchivePlugin.hxx +++ b/src/ArchivePlugin.hxx @@ -26,6 +26,7 @@ struct input_stream; struct archive_file; +class ArchiveVisitor; struct archive_plugin { const char *name; @@ -51,18 +52,9 @@ struct archive_plugin { struct archive_file *(*open)(const char *path_fs, GError **error_r); /** - * reset routine will move current read index in archive to default - * position and then the filenames from archives can be read - * via scan_next routine + * Visit all entries inside this archive. */ - void (*scan_reset)(struct archive_file *); - - /** - * the read method will return corresponding files from archive - * (as pathnames) and move read index to next file. When there is no - * next file it return NULL. - */ - const char *(*scan_next)(struct archive_file *); + void (*visit)(archive_file *af, ArchiveVisitor &visitor); /** * Opens an input_stream of a file within the archive. @@ -96,10 +88,7 @@ void archive_file_close(struct archive_file *file); void -archive_file_scan_reset(struct archive_file *file); - -const char * -archive_file_scan_next(struct archive_file *file); +archive_file_visit(archive_file *file, ArchiveVisitor &visitor); struct input_stream * archive_file_open_stream(struct archive_file *file, const char *path, diff --git a/src/ArchiveVisitor.hxx b/src/ArchiveVisitor.hxx new file mode 100644 index 000000000..e951cb5e9 --- /dev/null +++ b/src/ArchiveVisitor.hxx @@ -0,0 +1,28 @@ +/* + * 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_ARCHIVE_VISITOR_HXX +#define MPD_ARCHIVE_VISITOR_HXX + +class ArchiveVisitor { +public: + virtual void VisitArchiveEntry(const char *path_utf8) = 0; +}; + +#endif diff --git a/src/UpdateArchive.cxx b/src/UpdateArchive.cxx index 5da212e9d..88d67fbc0 100644 --- a/src/UpdateArchive.cxx +++ b/src/UpdateArchive.cxx @@ -27,6 +27,7 @@ #include "fs/Path.hxx" #include "ArchiveList.hxx" #include "ArchivePlugin.hxx" +#include "ArchiveVisitor.hxx" #include @@ -122,14 +123,21 @@ update_archive_file2(Directory *parent, const char *name, directory->mtime = st->st_mtime; - archive_file_scan_reset(file); + class UpdateArchiveVisitor final : public ArchiveVisitor { + Directory *directory; - const char *filepath; - while ((filepath = archive_file_scan_next(file)) != NULL) { - /* split name into directory and file */ - g_debug("adding archive file: %s", filepath); - update_archive_tree(directory, filepath); - } + public: + UpdateArchiveVisitor(Directory *_directory) + :directory(_directory) {} + + virtual void VisitArchiveEntry(const char *path_utf8) override { + g_debug("adding archive file: %s", path_utf8); + update_archive_tree(directory, path_utf8); + } + }; + + UpdateArchiveVisitor visitor(directory); + archive_file_visit(file, visitor); archive_file_close(file); } diff --git a/src/archive/Bzip2ArchivePlugin.cxx b/src/archive/Bzip2ArchivePlugin.cxx index 4b0d5223e..be7388d5b 100644 --- a/src/archive/Bzip2ArchivePlugin.cxx +++ b/src/archive/Bzip2ArchivePlugin.cxx @@ -25,6 +25,7 @@ #include "Bzip2ArchivePlugin.hxx" #include "ArchiveInternal.hxx" #include "ArchivePlugin.hxx" +#include "ArchiveVisitor.hxx" #include "InputInternal.hxx" #include "InputStream.hxx" #include "InputPlugin.hxx" @@ -47,7 +48,6 @@ struct Bzip2ArchiveFile { struct refcount ref; char *name; - bool reset; struct input_stream *istream; Bzip2ArchiveFile() { @@ -152,24 +152,11 @@ bz2_open(const char *pathname, GError **error_r) } static void -bz2_scan_reset(struct archive_file *file) +bz2_visit(archive_file *file, ArchiveVisitor &visitor) { Bzip2ArchiveFile *context = (Bzip2ArchiveFile *) file; - context->reset = true; -} - -static const char * -bz2_scan_next(struct archive_file *file) -{ - Bzip2ArchiveFile *context = (Bzip2ArchiveFile *) file; - const char *name = NULL; - - if (context->reset) { - name = context->name; - context->reset = false; - } - return name; + visitor.VisitArchiveEntry(context->name); } static void @@ -318,8 +305,7 @@ const struct archive_plugin bz2_archive_plugin = { nullptr, nullptr, bz2_open, - bz2_scan_reset, - bz2_scan_next, + bz2_visit, bz2_open_stream, bz2_close, bz2_extensions, diff --git a/src/archive/Iso9660ArchivePlugin.cxx b/src/archive/Iso9660ArchivePlugin.cxx index fe752ff3b..895087efc 100644 --- a/src/archive/Iso9660ArchivePlugin.cxx +++ b/src/archive/Iso9660ArchivePlugin.cxx @@ -25,6 +25,7 @@ #include "Iso9660ArchivePlugin.hxx" #include "ArchiveInternal.hxx" #include "ArchivePlugin.hxx" +#include "ArchiveVisitor.hxx" #include "InputInternal.hxx" #include "InputStream.hxx" #include "InputPlugin.hxx" @@ -46,22 +47,14 @@ struct Iso9660ArchiveFile { struct refcount ref; iso9660_t *iso; - GSList *list; - GSList *iter; Iso9660ArchiveFile(iso9660_t *_iso) - :iso(_iso), list(nullptr) { + :iso(_iso) { archive_file_init(&base, &iso9660_archive_plugin); refcount_init(&ref); } ~Iso9660ArchiveFile() { - //free list - for (GSList *tmp = list; tmp != NULL; tmp = g_slist_next(tmp)) - g_free(tmp->data); - g_slist_free(list); - - //close archive iso9660_close(iso); } @@ -70,7 +63,7 @@ struct Iso9660ArchiveFile { delete this; } - void CollectRecursive(const char *path); + void Visit(const char *path, ArchiveVisitor &visitor); }; extern const struct input_plugin iso9660_input_plugin; @@ -83,8 +76,8 @@ iso9660_quark(void) /* archive open && listing routine */ -void -Iso9660ArchiveFile::CollectRecursive(const char *psz_path) +inline void +Iso9660ArchiveFile::Visit(const char *psz_path, ArchiveVisitor &visitor) { CdioList_t *entlist; CdioListNode_t *entnode; @@ -105,11 +98,11 @@ Iso9660ArchiveFile::CollectRecursive(const char *psz_path) if (iso9660_stat_s::_STAT_DIR == statbuf->type ) { if (strcmp(statbuf->filename, ".") && strcmp(statbuf->filename, "..")) { strcat(pathname, "/"); - CollectRecursive(pathname); + Visit(pathname, visitor); } } else { //remove leading / - list = g_slist_prepend(list, g_strdup(pathname + 1)); + visitor.VisitArchiveEntry(pathname + 1); } } _cdio_list_free (entlist, true); @@ -127,33 +120,16 @@ iso9660_archive_open(const char *pathname, GError **error_r) } Iso9660ArchiveFile *archive = new Iso9660ArchiveFile(iso); - archive->CollectRecursive("/"); return &archive->base; } static void -iso9660_archive_scan_reset(struct archive_file *file) -{ - Iso9660ArchiveFile *context = - (Iso9660ArchiveFile *)file; - - //reset iterator - context->iter = context->list; -} - -static const char * -iso9660_archive_scan_next(struct archive_file *file) +iso9660_archive_visit(archive_file *file, ArchiveVisitor &visitor) { Iso9660ArchiveFile *context = (Iso9660ArchiveFile *)file; - const char *data = NULL; - if (context->iter != NULL) { - ///fetch data and goto next - data = (const char *)context->iter->data; - context->iter = g_slist_next(context->iter); - } - return data; + context->Visit("/", visitor); } static void @@ -296,8 +272,7 @@ const struct archive_plugin iso9660_archive_plugin = { nullptr, nullptr, iso9660_archive_open, - iso9660_archive_scan_reset, - iso9660_archive_scan_next, + 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 81bf91f07..4075e2179 100644 --- a/src/archive/ZzipArchivePlugin.cxx +++ b/src/archive/ZzipArchivePlugin.cxx @@ -25,6 +25,7 @@ #include "ZzipArchivePlugin.hxx" #include "ArchiveInternal.hxx" #include "ArchivePlugin.hxx" +#include "ArchiveVisitor.hxx" #include "InputInternal.hxx" #include "InputStream.hxx" #include "InputPlugin.hxx" @@ -40,8 +41,6 @@ struct ZzipArchiveFile { struct refcount ref; ZZIP_DIR *dir; - GSList *list; - GSList *iter; ZzipArchiveFile() { archive_file_init(&base, &zzip_archive_plugin); @@ -52,17 +51,13 @@ struct ZzipArchiveFile { if (!refcount_dec(&ref)) return; - if (list) { - //free list - for (GSList *tmp = list; tmp != NULL; tmp = g_slist_next(tmp)) - g_free(tmp->data); - g_slist_free(list); - } //close archive zzip_dir_close (dir); delete this; } + + void Visit(ArchiveVisitor &visitor); }; extern const struct input_plugin zzip_input_plugin; @@ -79,10 +74,8 @@ static struct archive_file * zzip_archive_open(const char *pathname, GError **error_r) { ZzipArchiveFile *context = new ZzipArchiveFile(); - ZZIP_DIRENT dirent; // open archive - context->list = NULL; context->dir = zzip_dir_open(pathname, NULL); if (context->dir == NULL) { g_set_error(error_r, zzip_quark(), 0, @@ -90,36 +83,27 @@ zzip_archive_open(const char *pathname, GError **error_r) return NULL; } - while (zzip_dir_read(context->dir, &dirent)) { - //add only files - if (dirent.st_size > 0) { - context->list = g_slist_prepend(context->list, - g_strdup(dirent.d_name)); - } - } - return &context->base; } -static void -zzip_archive_scan_reset(struct archive_file *file) +inline void +ZzipArchiveFile::Visit(ArchiveVisitor &visitor) { - ZzipArchiveFile *context = (ZzipArchiveFile *) file; - //reset iterator - context->iter = context->list; + zzip_rewinddir(dir); + + ZZIP_DIRENT dirent; + while (zzip_dir_read(dir, &dirent)) + //add only files + if (dirent.st_size > 0) + visitor.VisitArchiveEntry(dirent.d_name); } -static const char * -zzip_archive_scan_next(struct archive_file *file) +static void +zzip_archive_visit(archive_file *file, ArchiveVisitor &visitor) { ZzipArchiveFile *context = (ZzipArchiveFile *) file; - const char *data = NULL; - if (context->iter != NULL) { - ///fetch data and goto next - data = (const char *)context->iter->data; - context->iter = g_slist_next(context->iter); - } - return data; + + context->Visit(visitor); } static void @@ -260,8 +244,7 @@ const struct archive_plugin zzip_archive_plugin = { nullptr, nullptr, zzip_archive_open, - zzip_archive_scan_reset, - zzip_archive_scan_next, + zzip_archive_visit, zzip_archive_open_stream, zzip_archive_close, zzip_archive_extensions, -- cgit v1.2.3