From dcd04bd6d9569aff386d438dcaa1194e9ce7d36e Mon Sep 17 00:00:00 2001 From: pixel Date: Tue, 10 Jul 2007 13:09:37 +0000 Subject: mpq-fs working. --- mpq-fs.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 2 deletions(-) (limited to 'mpq-fs.c') diff --git a/mpq-fs.c b/mpq-fs.c index acc2648..dac03b4 100644 --- a/mpq-fs.c +++ b/mpq-fs.c @@ -1,13 +1,173 @@ #include +#include +#include #include "mpq-fs.h" +#define MAX_FNAME 2048 + +typedef struct directory_list_t { + struct directory_list_t * child; + char * name; + struct mpq_archive_t * mpq_a; + int entry; + struct directory_list_t * next; +} directory_list; + +static directory_list root_dir = { + NULL, "", NULL, -1, NULL +}; + +static directory_list * root = &root_dir; + +static char * strtoupper(char * _str) { + char * str = _str; + while (*str) { + *str = toupper(*str); + str++; + } + return _str; +} + +static directory_list * new_directory_list(directory_list * parent, struct mpq_archive_t * mpq_a, const char * name) { + directory_list * r; + + for (r = parent->child; r; r = r->next) { + if (!strcasecmp(r->name, name)) + break; + } + + if (!r) { + r = (directory_list *) malloc(sizeof(directory_list)); + r->child = NULL; + r->next = parent->child; + parent->child = r; + r->name = strtoupper(strdup(name)); + r->mpq_a = mpq_a; + r->entry = -1; + } + + return r; +} + +static directory_list * add_file_r(directory_list * parent, struct mpq_archive_t * mpq_a, char * fname, int entry) { + char * bs; + directory_list * r; + int tail = 0; + + bs = strchr(fname, '\\'); + + if (bs) { + *bs = 0; + } else { + tail = 1; + } + if (!(r = new_directory_list(parent, mpq_a, fname))) + return NULL; + + if (tail) { + r->entry = entry; + return r; + } + + return add_file_r(r, mpq_a, bs + 1, entry); +} + +static directory_list * add_file(struct mpq_archive_t * mpq_a, char * fname) { + int entry; + + if ((entry = mpqlib_find_hash_entry_by_name(mpq_a, fname, 0, 0)) < 0) + return NULL; + + return add_file_r(root, mpq_a, fname, entry); +} + void mpqlib_fs_add_archive(struct mpq_archive_t * mpq_a) { + struct mpq_file_t * listfile; + char * buffer; + int s; + + if (!(listfile = mpqlib_open_filename(mpq_a, "(listfile)"))) + return; + + s = mpqlib_seek(listfile, 0, MPQLIB_SEEK_END); + mpqlib_seek(listfile, 0, MPQLIB_SEEK_SET); + + if (!(buffer = (char *) malloc(s + 1))) { + mpqlib_close(listfile); + return; + } + + buffer[s] = 0; + mpqlib_read(listfile, buffer, s); + mpqlib_fs_attach_listfile(mpq_a, buffer); + + free(buffer); + mpqlib_close(listfile); } void mpqlib_fs_attach_listfile(struct mpq_archive_t * mpq_a, const char * listfile) { - mpqlib_fs_add_archive(mpq_a); + char fname[MAX_FNAME]; + const char * p; + char * fnp; + + for (p = listfile, fnp = fname; *p; p++) { + switch (*p) { + case '\r': + case '\n': + case ';': + *fnp = 0; + if (fnp != fname) + add_file(mpq_a, fname); + fnp = fname; + break; + default: + *(fnp++) = *p; + break; + } + } } -struct mpq_file_t * mpqlib_fs_open(const char * fname) { +static directory_list * find_file_r(directory_list * parent, char * fname) { + char * bs; + directory_list * r; + int tail = 0; + + bs = strchr(fname, '\\'); + + if (bs) { + *bs = 0; + } else { + tail = 1; + } + + for (r = parent->child; r; r = r->next) { + if (!strcmp(fname, r->name)) { + if (tail) { + return r; + } else { + return find_file_r(r, bs + 1); + } + } + } + + return NULL; +} + +static directory_list * find_file(char * fname) { + return find_file_r(root, fname); +} + +struct mpq_file_t * mpqlib_fs_open(const char * _fname) { + char * fname = strtoupper(strdup(_fname)); + directory_list * entry; + + entry = find_file(fname); + + free(fname); + + if (entry) { + return mpqlib_open_file(entry->mpq_a, entry->entry); + } + return NULL; } -- cgit v1.2.3