ref: f5da1a45b1d34e40b4687a6add3b8a2b3685f525
parent: 5705be4c622af4a4027a711c5dbbb42d9ce0ea8a
author: Simon Howard <fraggle@soulsphere.org>
date: Sat Nov 3 09:11:55 EDT 2018
glob: Add multi-pattern matching. Sometimes we want to glob for more than one type of file at once.
--- a/src/i_glob.c
+++ b/src/i_glob.c
@@ -72,7 +72,8 @@
struct glob_s
{
- char *glob;
+ char **globs;
+ int num_globs;
int flags;
DIR *dir;
char *directory;
@@ -83,10 +84,33 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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);
--- a/src/i_glob.h
+++ b/src/i_glob.h
@@ -28,6 +28,11 @@
// 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);