glob: Add multi-pattern matching.
Sometimes we want to glob for more than one type of file at once.
This commit is contained in:
parent
5705be4c62
commit
f5da1a45b1
2 changed files with 59 additions and 5 deletions
59
src/i_glob.c
59
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue