commit 3e04dc09b619fdad56e07fd9fe03d30b3ca687ec
parent f4a2c59b7cf12d727e11f12d98ccb0688c3070f0
Author: Chris Bracken <chris@bracken.jp>
Date: Fri, 20 Feb 2026 19:01:18 +0900
writer: extract ops vtable
Diffstat:
2 files changed, 98 insertions(+), 185 deletions(-)
diff --git a/src/writer/index_writer.c b/src/writer/index_writer.c
@@ -8,36 +8,49 @@
#include "writer/gopher/index_writer.h"
#include "writer/html/index_writer.h"
-typedef void (*IndexWriterVoidFunc)(void* impl);
-typedef void (*IndexWriterStringFunc)(void* impl, const char* url);
-typedef void (*IndexWriterRepoInfoFunc)(void* impl, const GitRepo* repo);
+typedef struct IndexWriterOps {
+ void (*set_me_url)(void* impl, const char* url);
+ void (*begin)(void* impl);
+ void (*add_repo)(void* impl, const GitRepo* repo);
+ void (*end)(void* impl);
+ void (*free)(void* impl);
+} IndexWriterOps;
struct IndexWriter {
- /* Writer implementation. */
- IndexWriterType type;
+ const IndexWriterOps* ops;
void* impl;
-
- /* Writer operations. */
- IndexWriterStringFunc set_me_url;
- IndexWriterVoidFunc begin;
- IndexWriterRepoInfoFunc add_repo;
- IndexWriterVoidFunc end;
};
-static IndexWriter* htmlindexwriter_create(FILE* out);
-static void htmlindexwriter_free(IndexWriter* writer);
+static const IndexWriterOps kHtmlIndexWriterOps = {
+ .set_me_url = (void (*)(void*, const char*))html_indexwriter_set_me_url,
+ .begin = (void (*)(void*))html_indexwriter_begin,
+ .add_repo = (void (*)(void*, const GitRepo*))html_indexwriter_add_repo,
+ .end = (void (*)(void*))html_indexwriter_end,
+ .free = (void (*)(void*))html_indexwriter_free,
+};
-static IndexWriter* gopherindexwriter_create(FILE* out);
-static void gopherindexwriter_free(IndexWriter* writer);
+static const IndexWriterOps kGopherIndexWriterOps = {
+ .set_me_url = NULL,
+ .begin = (void (*)(void*))gopher_indexwriter_begin,
+ .add_repo = (void (*)(void*, const GitRepo*))gopher_indexwriter_add_repo,
+ .end = (void (*)(void*))gopher_indexwriter_end,
+ .free = (void (*)(void*))gopher_indexwriter_free,
+};
IndexWriter* indexwriter_create(IndexWriterType type, FILE* out) {
assert(out != NULL);
+ IndexWriter* writer = ecalloc(1, sizeof(IndexWriter));
switch (type) {
case kIndexWriterTypeHtml:
- return htmlindexwriter_create(out);
+ writer->ops = &kHtmlIndexWriterOps;
+ writer->impl = html_indexwriter_create(out);
+ return writer;
case kIndexWriterTypeGopher:
- return gopherindexwriter_create(out);
+ writer->ops = &kGopherIndexWriterOps;
+ writer->impl = gopher_indexwriter_create(out);
+ return writer;
}
+ free(writer);
errx(1, "unknown IndexWriterType %d", type);
}
@@ -45,83 +58,31 @@ void indexwriter_free(IndexWriter* writer) {
if (!writer) {
return;
}
- switch (writer->type) {
- case kIndexWriterTypeHtml:
- htmlindexwriter_free(writer);
- return;
- case kIndexWriterTypeGopher:
- gopherindexwriter_free(writer);
- return;
- }
- errx(1, "unknown IndexWriterType %d", writer->type);
+ writer->ops->free(writer->impl);
+ writer->impl = NULL;
+ free(writer);
}
void indexwriter_set_me_url(IndexWriter* writer, const char* url) {
assert(writer != NULL);
assert(url != NULL);
- if (writer->set_me_url) {
- writer->set_me_url(writer->impl, url);
+ if (writer->ops->set_me_url) {
+ writer->ops->set_me_url(writer->impl, url);
}
}
void indexwriter_begin(IndexWriter* writer) {
assert(writer != NULL);
- writer->begin(writer->impl);
+ writer->ops->begin(writer->impl);
}
void indexwriter_add_repo(IndexWriter* writer, const GitRepo* repo) {
assert(writer != NULL);
assert(repo != NULL);
- writer->add_repo(writer->impl, repo);
+ writer->ops->add_repo(writer->impl, repo);
}
void indexwriter_end(IndexWriter* writer) {
assert(writer != NULL);
- writer->end(writer->impl);
-}
-
-/* HtmlIndexWriter setup/teardown. */
-
-static IndexWriter* htmlindexwriter_create(FILE* out) {
- IndexWriter* writer = ecalloc(1, sizeof(IndexWriter));
- HtmlIndexWriter* html_writer = html_indexwriter_create(out);
- writer->type = kIndexWriterTypeHtml;
- writer->impl = html_writer;
- writer->set_me_url = (IndexWriterStringFunc)html_indexwriter_set_me_url;
- writer->begin = (IndexWriterVoidFunc)html_indexwriter_begin;
- writer->add_repo = (IndexWriterRepoInfoFunc)html_indexwriter_add_repo;
- writer->end = (IndexWriterVoidFunc)html_indexwriter_end;
- return writer;
-}
-
-static void htmlindexwriter_free(IndexWriter* writer) {
- if (!writer) {
- return;
- }
- html_indexwriter_free(writer->impl);
- writer->impl = NULL;
- free(writer);
-}
-
-/* GopherIndexWriter setup/teardown. */
-
-static IndexWriter* gopherindexwriter_create(FILE* out) {
- IndexWriter* writer = ecalloc(1, sizeof(IndexWriter));
- GopherIndexWriter* gopher_writer = gopher_indexwriter_create(out);
- writer->type = kIndexWriterTypeGopher;
- writer->impl = gopher_writer;
- writer->set_me_url = NULL;
- writer->begin = (IndexWriterVoidFunc)gopher_indexwriter_begin;
- writer->add_repo = (IndexWriterRepoInfoFunc)gopher_indexwriter_add_repo;
- writer->end = (IndexWriterVoidFunc)gopher_indexwriter_end;
- return writer;
-}
-
-static void gopherindexwriter_free(IndexWriter* writer) {
- if (!writer) {
- return;
- }
- gopher_indexwriter_free(writer->impl);
- writer->impl = NULL;
- free(writer);
+ writer->ops->end(writer->impl);
}
diff --git a/src/writer/repo_writer.c b/src/writer/repo_writer.c
@@ -8,51 +8,71 @@
#include "writer/gopher/repo_writer.h"
#include "writer/html/repo_writer.h"
-typedef void (*RepoWriterSetLogCachefile)(void* writer, const char* cachefile);
-typedef void (*RepoWriterSetLogCommitLimit)(void* writer, size_t count);
-typedef void (*RepoWriterSetBaseurl)(void* writer, const char* baseurl);
-typedef void (*RepoWriterBegin)(void* writer);
-typedef void (*RepoWriterAddCommit)(void* writer, const GitCommit* commit);
-typedef void (*RepoWriterAddReference)(void* writer, const GitReference* ref);
-typedef void (*RepoWriterAddFile)(void* writer, const GitFile* file);
-typedef void (*RepoWriterEnd)(void* writer);
+typedef struct RepoWriterOps {
+ void (*set_log_cachefile)(void* writer, const char* cachefile);
+ void (*set_log_commit_limit)(void* writer, size_t count);
+ void (*set_baseurl)(void* writer, const char* baseurl);
+ void (*begin)(void* writer);
+ void (*add_commit)(void* writer, const GitCommit* commit);
+ void (*add_reference)(void* writer, const GitReference* ref);
+ void (*add_file)(void* writer, const GitFile* file);
+ void (*end)(void* writer);
+ void (*free)(void* writer);
+} RepoWriterOps;
struct RepoWriter {
- /* Writer implementation. */
- RepoWriterType type;
+ const RepoWriterOps* ops;
void* impl;
- const FileSystem* fs;
-
- /* Writer configuration. */
- RepoWriterSetLogCachefile set_log_cachefile;
- RepoWriterSetLogCommitLimit set_log_commit_limit;
- RepoWriterSetBaseurl set_baseurl;
-
- /* Writer operations. */
- RepoWriterBegin begin;
- RepoWriterAddCommit add_commit;
- RepoWriterAddReference add_reference;
- RepoWriterAddFile add_file;
- RepoWriterEnd end;
};
-static RepoWriter* htmlrepowriter_create(GitRepo* repo, const FileSystem* fs);
-static void htmlrepowriter_free(RepoWriter* writer);
+static const RepoWriterOps kHtmlRepoWriterOps = {
+ .set_log_cachefile =
+ (void (*)(void*, const char*))html_repowriter_set_log_cachefile,
+ .set_log_commit_limit =
+ (void (*)(void*, size_t))html_repowriter_set_log_commit_limit,
+ .set_baseurl = (void (*)(void*, const char*))html_repowriter_set_baseurl,
+ .begin = (void (*)(void*))html_repowriter_begin,
+ .add_commit = (void (*)(void*, const GitCommit*))html_repowriter_add_commit,
+ .add_reference =
+ (void (*)(void*, const GitReference*))html_repowriter_add_reference,
+ .add_file = (void (*)(void*, const GitFile*))html_repowriter_add_file,
+ .end = (void (*)(void*))html_repowriter_end,
+ .free = (void (*)(void*))html_repowriter_free,
+};
-static RepoWriter* gopherrepowriter_create(GitRepo* repo, const FileSystem* fs);
-static void gopherrepowriter_free(RepoWriter* writer);
+static const RepoWriterOps kGopherRepoWriterOps = {
+ .set_log_cachefile =
+ (void (*)(void*, const char*))gopher_repowriter_set_log_cachefile,
+ .set_log_commit_limit =
+ (void (*)(void*, size_t))gopher_repowriter_set_log_commit_limit,
+ .set_baseurl = (void (*)(void*, const char*))gopher_repowriter_set_baseurl,
+ .begin = (void (*)(void*))gopher_repowriter_begin,
+ .add_commit =
+ (void (*)(void*, const GitCommit*))gopher_repowriter_add_commit,
+ .add_reference =
+ (void (*)(void*, const GitReference*))gopher_repowriter_add_reference,
+ .add_file = (void (*)(void*, const GitFile*))gopher_repowriter_add_file,
+ .end = (void (*)(void*))gopher_repowriter_end,
+ .free = (void (*)(void*))gopher_repowriter_free,
+};
RepoWriter* repowriter_create(RepoWriterType type,
GitRepo* repo,
const FileSystem* fs) {
assert(repo != NULL);
assert(fs != NULL);
+ RepoWriter* writer = ecalloc(1, sizeof(RepoWriter));
switch (type) {
case kRepoWriterTypeHtml:
- return htmlrepowriter_create(repo, fs);
+ writer->ops = &kHtmlRepoWriterOps;
+ writer->impl = html_repowriter_create(repo, fs);
+ return writer;
case kRepoWriterTypeGopher:
- return gopherrepowriter_create(repo, fs);
+ writer->ops = &kGopherRepoWriterOps;
+ writer->impl = gopher_repowriter_create(repo, fs);
+ return writer;
}
+ free(writer);
errx(1, "unknown RepoWriterType %d", type);
}
@@ -60,120 +80,52 @@ void repowriter_free(RepoWriter* writer) {
if (!writer) {
return;
}
- switch (writer->type) {
- case kRepoWriterTypeHtml:
- htmlrepowriter_free(writer);
- return;
- case kRepoWriterTypeGopher:
- gopherrepowriter_free(writer);
- return;
- }
- errx(1, "unknown RepoWriterType %d", writer->type);
+ writer->ops->free(writer->impl);
+ writer->impl = NULL;
+ free(writer);
}
void repowriter_set_log_cachefile(RepoWriter* writer, const char* cachefile) {
assert(writer != NULL);
assert(cachefile != NULL);
- writer->set_log_cachefile(writer->impl, cachefile);
+ writer->ops->set_log_cachefile(writer->impl, cachefile);
}
void repowriter_set_log_commit_limit(RepoWriter* writer, size_t count) {
assert(writer != NULL);
- writer->set_log_commit_limit(writer->impl, count);
+ writer->ops->set_log_commit_limit(writer->impl, count);
}
void repowriter_set_baseurl(RepoWriter* writer, const char* baseurl) {
assert(writer != NULL);
assert(baseurl != NULL);
- writer->set_baseurl(writer->impl, baseurl);
+ writer->ops->set_baseurl(writer->impl, baseurl);
}
void repowriter_begin(RepoWriter* writer) {
assert(writer != NULL);
- writer->begin(writer->impl);
+ writer->ops->begin(writer->impl);
}
void repowriter_add_commit(RepoWriter* writer, const GitCommit* commit) {
assert(writer != NULL);
assert(commit != NULL);
- writer->add_commit(writer->impl, commit);
+ writer->ops->add_commit(writer->impl, commit);
}
void repowriter_add_reference(RepoWriter* writer, const GitReference* ref) {
assert(writer != NULL);
assert(ref != NULL);
- writer->add_reference(writer->impl, ref);
+ writer->ops->add_reference(writer->impl, ref);
}
void repowriter_add_file(RepoWriter* writer, const GitFile* file) {
assert(writer != NULL);
assert(file != NULL);
- writer->add_file(writer->impl, file);
+ writer->ops->add_file(writer->impl, file);
}
void repowriter_end(RepoWriter* writer) {
assert(writer != NULL);
- writer->end(writer->impl);
-}
-
-/* HtmlRepoWriter setup/teardown. */
-
-static RepoWriter* htmlrepowriter_create(GitRepo* repo, const FileSystem* fs) {
- RepoWriter* writer = ecalloc(1, sizeof(RepoWriter));
- HtmlRepoWriter* html_writer = html_repowriter_create(repo, fs);
- writer->type = kRepoWriterTypeHtml;
- writer->impl = html_writer;
- writer->fs = fs;
- writer->set_log_cachefile =
- (RepoWriterSetLogCachefile)html_repowriter_set_log_cachefile;
- writer->set_log_commit_limit =
- (RepoWriterSetLogCommitLimit)html_repowriter_set_log_commit_limit;
- writer->set_baseurl = (RepoWriterSetBaseurl)html_repowriter_set_baseurl;
- writer->begin = (RepoWriterBegin)html_repowriter_begin;
- writer->add_commit = (RepoWriterAddCommit)html_repowriter_add_commit;
- writer->add_reference = (RepoWriterAddReference)html_repowriter_add_reference;
- writer->add_file = (RepoWriterAddFile)html_repowriter_add_file;
- writer->end = (RepoWriterEnd)html_repowriter_end;
- return writer;
-}
-
-static void htmlrepowriter_free(RepoWriter* writer) {
- if (!writer) {
- return;
- }
- html_repowriter_free(writer->impl);
- writer->impl = NULL;
- free(writer);
-}
-
-/* GopherRepoWriter setup/teardown. */
-
-static RepoWriter* gopherrepowriter_create(GitRepo* repo,
- const FileSystem* fs) {
- RepoWriter* writer = ecalloc(1, sizeof(RepoWriter));
- GopherRepoWriter* gopher_writer = gopher_repowriter_create(repo, fs);
- writer->type = kRepoWriterTypeGopher;
- writer->impl = gopher_writer;
- writer->fs = fs;
- writer->set_log_cachefile =
- (RepoWriterSetLogCachefile)gopher_repowriter_set_log_cachefile;
- writer->set_log_commit_limit =
- (RepoWriterSetLogCommitLimit)gopher_repowriter_set_log_commit_limit;
- writer->set_baseurl = (RepoWriterSetBaseurl)gopher_repowriter_set_baseurl;
- writer->begin = (RepoWriterBegin)gopher_repowriter_begin;
- writer->add_commit = (RepoWriterAddCommit)gopher_repowriter_add_commit;
- writer->add_reference =
- (RepoWriterAddReference)gopher_repowriter_add_reference;
- writer->add_file = (RepoWriterAddFile)gopher_repowriter_add_file;
- writer->end = (RepoWriterEnd)gopher_repowriter_end;
- return writer;
-}
-
-static void gopherrepowriter_free(RepoWriter* writer) {
- if (!writer) {
- return;
- }
- gopher_repowriter_free(writer->impl);
- writer->impl = NULL;
- free(writer);
+ writer->ops->end(writer->impl);
}