added assfile
[raydungeon] / libs / assfile / mod_path.c
diff --git a/libs/assfile/mod_path.c b/libs/assfile/mod_path.c
new file mode 100644 (file)
index 0000000..dbad402
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+assfile - library for accessing assets with an fopen/fread-like interface
+Copyright (C) 2018  John Tsiombikas <nuclear@member.fsf.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#ifdef __MSVCRT__
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+
+#include "assfile_impl.h"
+
+
+static void *fop_open(const char *fname, void *udata);
+static void fop_close(void *fp, void *udata);
+static long fop_seek(void *fp, long offs, int whence, void *udata);
+static long fop_read(void *fp, void *buf, long size, void *udata);
+
+
+struct ass_fileops *ass_alloc_path(const char *path)
+{
+       char *p;
+       struct ass_fileops *fop;
+
+       if(!(fop = malloc(sizeof *fop))) {
+               return 0;
+       }
+       if(!(p = malloc(strlen(path) + 1))) {
+               free(fop);
+               return 0;
+       }
+       fop->udata = p;
+
+       while(*path) {
+               *p++ = *path++;
+       }
+       while(p > (char*)fop->udata && (p[-1] == '/' || isspace(p[-1]))) p--;
+       *p = 0;
+
+       fop->open = fop_open;
+       fop->close = fop_close;
+       fop->seek = fop_seek;
+       fop->read = fop_read;
+       return fop;
+}
+
+void ass_free_path(struct ass_fileops *fop)
+{
+       free(fop->udata);
+}
+
+static void *fop_open(const char *fname, void *udata)
+{
+       const char *asspath = (char*)udata;
+       char *path;
+       FILE *fp;
+
+       path = alloca(strlen(asspath) + strlen(fname) + 2);
+       sprintf(path, "%s/%s", asspath, fname);
+
+       if(!(fp = fopen(path, "rb"))) {
+               ass_errno = errno;
+               return 0;
+       }
+       return fp;
+}
+
+static void fop_close(void *fp, void *udata)
+{
+       fclose(fp);
+}
+
+static long fop_seek(void *fp, long offs, int whence, void *udata)
+{
+       fseek(fp, offs, whence);
+       return ftell(fp);
+}
+
+static long fop_read(void *fp, void *buf, long size, void *udata)
+{
+       return fread(buf, 1, size, fp);
+}