diff --git a/src/i_glob.c b/src/i_glob.c index f5284953..3aa6e5cd 100644 --- a/src/i_glob.c +++ b/src/i_glob.c @@ -72,7 +72,8 @@ static boolean IsDirectory(char *dir, struct dirent *de) struct glob_s { - char *glob; + char **globs; + int num_globs; int flags; DIR *dir; char *directory; @@ -83,9 +84,32 @@ struct glob_s int next_index; }; -glob_t *I_StartGlob(const char *directory, const char *glob, int flags) +glob_t *I_StartMultiGlob(const char *directory, int flags, + const char *glob, ...) { + char **globs; + int num_globs; glob_t *result; + va_list args; + + globs = malloc(sizeof(char *)); + globs[0] = M_StringDuplicate(glob); + num_globs = 1; + + va_start(args, glob); + for (;;) + { + const char *arg = va_arg(args, const char *); + if (arg == NULL) + { + break; + } + + globs = realloc(globs, sizeof(char *) * (num_globs + 1)); + globs[num_globs] = M_StringDuplicate(arg); + ++num_globs; + } + va_end(args); result = malloc(sizeof(glob_t)); if (result == NULL) @@ -101,7 +125,8 @@ glob_t *I_StartGlob(const char *directory, const char *glob, int flags) } result->directory = M_StringDuplicate(directory); - result->glob = M_StringDuplicate(glob); + result->globs = globs; + result->num_globs = num_globs; result->flags = flags; result->last_filename = NULL; result->filenames = NULL; @@ -110,6 +135,11 @@ glob_t *I_StartGlob(const char *directory, const char *glob, int flags) return result; } +glob_t *I_StartGlob(const char *directory, const char *glob, int flags) +{ + return I_StartMultiGlob(directory, flags, glob, NULL); +} + void I_EndGlob(glob_t *glob) { int i; @@ -119,15 +149,20 @@ void I_EndGlob(glob_t *glob) return; } + for (i = 0; i < glob->num_globs; ++i) + { + free(glob->globs[i]); + } + for (i = 0; i < glob->filenames_len; ++i) { free(glob->filenames[i]); } + free(glob->globs); free(glob->filenames); free(glob->directory); free(glob->last_filename); - free(glob->glob); (void) closedir(glob->dir); free(glob); } @@ -177,6 +212,20 @@ static boolean MatchesGlob(const char *name, const char *glob, int flags) return *name == '\0'; } +static boolean MatchesAnyGlob(const char *name, glob_t *glob) +{ + int i; + + for (i = 0; i < glob->num_globs; ++i) + { + if (MatchesGlob(name, glob->globs[i], glob->flags)) + { + return true; + } + } + return false; +} + static char *NextGlob(glob_t *glob) { struct dirent *de; @@ -189,7 +238,7 @@ static char *NextGlob(glob_t *glob) return NULL; } } while (IsDirectory(glob->directory, de) - || !MatchesGlob(de->d_name, glob->glob, glob->flags)); + || !MatchesAnyGlob(de->d_name, glob)); // Return the fully-qualified path, not just the bare filename. return M_StringJoin(glob->directory, DIR_SEPARATOR_S, de->d_name, NULL); diff --git a/src/i_glob.h b/src/i_glob.h index 12f2994b..f976db01 100644 --- a/src/i_glob.h +++ b/src/i_glob.h @@ -28,6 +28,11 @@ typedef struct glob_s glob_t; // the given glob pattern. I_EndGlob() must be called on completion. glob_t *I_StartGlob(const char *directory, const char *glob, int flags); +// Same as I_StartGlob but multiple glob patterns can be provided. The list +// of patterns must be terminated with NULL. +glob_t *I_StartMultiGlob(const char *directory, int flags, + const char *glob, ...); + // Finish reading file list. void I_EndGlob(glob_t *glob);