Author: John Keeping <john@keeping.me.uk>
filter: add interface layer Change the existing cgit_{open,close,fprintf}_filter functions to delegate to filter-specific implementations accessed via function pointers on the cgit_filter object. We treat the "exec" filter type slightly specially here by putting its structure definition in the header file and providing an "init" function to set up the function pointers. This is required so that the ui-snapshot.c code that applies a compression filter can continue to use the filter interface to do so. Signed-off-by: John Keeping <john@keeping.me.uk>
cgit.h | 8 ++++++ filter.c | 66 ++++++++++++++++++++++++++++++++++++++++------------ ui-snapshot.c | 11 ++++----
diff --git a/cgit.h b/cgit.h index 9b4be26bc342e551b12699e82d488d2b9d18ca32..92e8c558dab46e402381f084e437cf5be90b0b21 100644 --- a/cgit.h +++ b/cgit.h @@ -57,6 +57,13 @@ ABOUT, COMMIT, SOURCE } filter_type; struct cgit_filter { + int (*open)(struct cgit_filter *, va_list ap); + int (*close)(struct cgit_filter *); + void (*fprintf)(struct cgit_filter *, FILE *, const char *prefix); +}; + +struct cgit_exec_filter { + struct cgit_filter base; char *cmd; char **argv; int extra_args; @@ -346,6 +353,7 @@ extern int cgit_open_filter(struct cgit_filter *filter, ...); extern int cgit_close_filter(struct cgit_filter *filter); extern void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix); +extern void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv); extern struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype); extern void cgit_prepare_repo_env(struct cgit_repo * repo); diff --git a/filter.c b/filter.c index 80cf68956bc5291a74cbe029ebf449af625bedb0..0f3edb00e96eaca6464c3b212145f41825b05d02 100644 --- a/filter.c +++ b/filter.c @@ -13,15 +13,13 @@ #include#include <string.h> #include <stdlib.h> -int cgit_open_filter(struct cgit_filter *filter, ...) +static int open_exec_filter(struct cgit_filter *base, va_list ap) { + struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base; int i; - va_list ap; - va_start(ap, filter); for (i = 0; i < filter->extra_args; i++) filter->argv[i+1] = va_arg(ap, char *); - va_end(ap); filter->old_stdout = chk_positive(dup(STDOUT_FILENO), "Unable to duplicate STDOUT"); @@ -41,9 +39,9 @@ close(filter->pipe_fh[1]); return 0; } - -int cgit_close_filter(struct cgit_filter *filter) +static int close_exec_filter(struct cgit_filter *base) { + struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base; int i, exit_status; chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO), @@ -63,21 +61,50 @@ return 0; } -void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix) +static void fprintf_exec_filter(struct cgit_filter *base, FILE *f, const char *prefix) { + struct cgit_exec_filter *filter = (struct cgit_exec_filter *) base; fprintf(f, "%s%s\n", prefix, filter->cmd); } -struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) +int cgit_open_filter(struct cgit_filter *filter, ...) { - struct cgit_filter *f; - int args_size = 0; + int result; + va_list ap; + va_start(ap, filter); + result = filter->open(filter, ap); + va_end(ap); + return result; +} - if (!cmd || !cmd[0]) - return NULL; +int cgit_close_filter(struct cgit_filter *filter) +{ + return filter->close(filter); +} - f = xmalloc(sizeof(struct cgit_filter)); - memset(f, 0, sizeof(struct cgit_filter)); +void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix) +{ + filter->fprintf(filter, f, prefix); +} + +void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv) +{ + memset(filter, 0, sizeof(*filter)); + filter->base.open = open_exec_filter; + filter->base.close = close_exec_filter; + filter->base.fprintf = fprintf_exec_filter; + filter->cmd = cmd; + filter->argv = argv; +} + +static struct cgit_filter *new_exec_filter(const char *cmd, filter_type filtertype) +{ + struct cgit_exec_filter *f; + int args_size = 0; + + f = xmalloc(sizeof(*f)); + /* We leave argv for now and assign it below. */ + cgit_exec_filter_init(f, xstrdup(cmd), NULL); switch (filtertype) { case SOURCE: @@ -91,10 +118,17 @@ f->extra_args = 0; break; } - f->cmd = xstrdup(cmd); args_size = (2 + f->extra_args) * sizeof(char *); f->argv = xmalloc(args_size); memset(f->argv, 0, args_size); f->argv[0] = f->cmd; - return f; + return &f->base; +} + +struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) +{ + if (!cmd || !cmd[0]) + return NULL; + + return new_exec_filter(cmd, filtertype); } diff --git a/ui-snapshot.c b/ui-snapshot.c index 5136c49d84b8fb9307c592892f246fb605a89a69..7115ec44153f3dac4e6dd3c5df1880dfb7322c70 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c @@ -58,13 +58,12 @@ const char *prefix, char *filter_argv[]) { int rv; - struct cgit_filter f = { - .cmd = filter_argv[0], - .argv = filter_argv, - }; - cgit_open_filter(&f); + struct cgit_exec_filter f; + cgit_exec_filter_init(&f, filter_argv[0], filter_argv); + + cgit_open_filter(&f.base); rv = write_tar_archive(hex, prefix); - cgit_close_filter(&f); + cgit_close_filter(&f.base); return rv; }