X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=filematch.c;h=e06439614c2174927168128adf5b1fcbe8fa268d;hp=0755f14aaa2ea61641504feda50560710c6b6ee3;hb=8507719df58bf767983c92ecfa32a70090bf501e;hpb=27ad2d336694ea2dc50035130bae321316e3936f diff --git a/filematch.c b/filematch.c index 0755f14a..e0643961 100644 --- a/filematch.c +++ b/filematch.c @@ -1,14 +1,22 @@ -#include "quakedef.h" +#ifdef WIN32 +#include +#else +#include +#endif -// LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such... +#include "darkplaces.h" + +// LadyHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such... int matchpattern(const char *in, const char *pattern, int caseinsensitive) { return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false); } -int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one) +// wildcard_least_one: if true * matches 1 or more characters +// if false * matches 0 or more characters +int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qbool wildcard_least_one) { int c1, c2; while (*pattern) @@ -25,17 +33,18 @@ int matchpattern_with_separator(const char *in, const char *pattern, int caseins break; case '*': // match anything until following string if(wildcard_least_one) + { if (*in == 0 || strchr(separators, *in)) return 0; // no match - if (!*in) - return 1; // match + in++; + } pattern++; while (*in) { if (strchr(separators, *in)) break; // see if pattern matches at this offset - if (matchpattern(in, pattern, caseinsensitive)) + if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one)) return 1; // nope, advance to next offset in++; @@ -108,22 +117,37 @@ void stringlistappend(stringlist_t *list, const char *text) list->numstrings++; } -void stringlistsort(stringlist_t *list) +static int stringlistsort_cmp(const void *a, const void *b) +{ + return strcasecmp(*(const char **)a, *(const char **)b); +} + +void stringlistsort(stringlist_t *list, qbool uniq) { int i, j; - char *temp; - // this is a selection sort (finds the best entry for each slot) - for (i = 0;i < list->numstrings - 1;i++) + if(list->numstrings < 1) + return; + qsort(&list->strings[0], list->numstrings, sizeof(list->strings[0]), stringlistsort_cmp); + if(uniq) { - for (j = i + 1;j < list->numstrings;j++) + // i: the item to read + // j: the item last written + for (i = 1, j = 0; i < list->numstrings; ++i) { - if (strcasecmp(list->strings[i], list->strings[j]) > 0) - { - temp = list->strings[i]; - list->strings[i] = list->strings[j]; - list->strings[j] = temp; - } + char *save; + if(!strcasecmp(list->strings[i], list->strings[j])) + continue; + ++j; + save = list->strings[j]; + list->strings[j] = list->strings[i]; + list->strings[i] = save; } + for(i = j+1; i < list->numstrings; ++i) + { + if (list->strings[i]) + Z_Free(list->strings[i]); + } + list->numstrings = j+1; } } @@ -138,42 +162,59 @@ static void adddirentry(stringlist_t *list, const char *path, const char *name) } } #ifdef WIN32 -#include void listdirectory(stringlist_t *list, const char *basepath, const char *path) { - int i; - char pattern[4096], *c; - struct _finddata_t n_file; - long hFile; + char pattern[4096]; + WIN32_FIND_DATA n_file; + HANDLE hFile; strlcpy (pattern, basepath, sizeof(pattern)); strlcat (pattern, path, sizeof (pattern)); strlcat (pattern, "*", sizeof (pattern)); // ask for the directory listing handle - hFile = _findfirst(pattern, &n_file); - if(hFile == -1) + hFile = FindFirstFile(pattern, &n_file); + if(hFile == INVALID_HANDLE_VALUE) return; do { - adddirentry(list, path, n_file.name ); - } while (_findnext(hFile, &n_file) == 0); - _findclose(hFile); - - // convert names to lowercase because windows does not care, but pattern matching code often does - for (i = 0;i < list->numstrings;i++) - for (c = list->strings[i];*c;c++) - if (*c >= 'A' && *c <= 'Z') - *c += 'a' - 'A'; + adddirentry(list, path, n_file.cFileName); + } while (FindNextFile(hFile, &n_file) != 0); + FindClose(hFile); } #else -#include void listdirectory(stringlist_t *list, const char *basepath, const char *path) { char fullpath[MAX_OSPATH]; DIR *dir; struct dirent *ent; - dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, *path ? path : "./"); + dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, path); +#ifdef __ANDROID__ + // SDL currently does not support listing assets, so we have to emulate + // it. We're using relative paths for assets, so that will do. + if (basepath[0] != '/') + { + char listpath[MAX_OSPATH]; + qfile_t *listfile; + dpsnprintf(listpath, sizeof(listpath), "%sls.txt", fullpath); + char *buf = (char *) FS_SysLoadFile(listpath, tempmempool, true, NULL); + if (!buf) + return; + char *p = buf; + for (;;) + { + char *q = strchr(p, '\n'); + if (q == NULL) + break; + *q = 0; + adddirentry(list, path, p); + p = q + 1; + } + Mem_Free(buf); + return; + } +#endif dir = opendir(fullpath); if (!dir) return; + while ((ent = readdir(dir))) adddirentry(list, path, ent->d_name); closedir(dir);