Add system-specific globbing API.

Part of #1051.
This commit is contained in:
Simon Howard 2018-10-27 17:50:14 -04:00
parent 7f03c58cbf
commit 419776fc72
4 changed files with 186 additions and 1 deletions

View file

@ -77,7 +77,7 @@ CFLAGS="$CFLAGS $SDL_CFLAGS ${SAMPLERATE_CFLAGS:-} ${PNG_CFLAGS:-}"
LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-} ${PNG_LIBS:-}"
AC_CHECK_LIB(m, log)
AC_CHECK_HEADERS([linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
AC_CHECK_HEADERS([dirent.h linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
AC_CHECK_FUNCS(mmap ioperm)
AC_CHECK_DECLS([strcasecmp, strncasecmp], [], [], [[#include <strings.h>]])

View file

@ -65,6 +65,7 @@ deh_str.c deh_str.h \
gusconf.c gusconf.h \
i_cdmus.c i_cdmus.h \
i_endoom.c i_endoom.h \
i_glob.c i_glob.h \
i_input.c i_input.h \
i_joystick.c i_joystick.h \
i_swap.h \

148
src/i_glob.c Normal file
View file

@ -0,0 +1,148 @@
//
// Copyright(C) 2018 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// File globbing API. This allows the contents of the filesystem
// to be interrogated.
//
// TODO: Merge win_opendir.[ch] into this file for MSVC implementation.
#include <stdlib.h>
#include "i_glob.h"
#include "m_misc.h"
#include "config.h"
#ifdef HAVE_DIRENT_H
#include "dirent.h"
struct glob_s
{
char *glob;
DIR *dir;
char *directory;
char *last_filename;
};
glob_t *I_StartGlob(const char *directory, const char *glob)
{
glob_t *result;
result = malloc(sizeof(glob_t));
if (result == NULL)
{
return NULL;
}
result->dir = opendir(directory);
if (result->dir == NULL)
{
free(result);
return NULL;
}
result->directory = M_StringDuplicate(directory);
result->glob = M_StringDuplicate(glob);
result->last_filename = NULL;
return result;
}
void I_EndGlob(glob_t *glob)
{
if (glob == NULL)
{
return;
}
free(glob->directory);
free(glob->last_filename);
free(glob->glob);
(void) closedir(glob->dir);
free(glob);
}
static boolean MatchesGlob(const char *name, const char *glob)
{
while (*glob != '\0')
{
if (*glob == '*')
{
// To handle *-matching we skip past the * and recurse
// to check each subsequent character in turn. If none
// match then the whole match is a failure.
while (*name != '\0')
{
if (MatchesGlob(name, glob + 1))
{
return true;
}
++name;
}
return false;
}
else if (*glob != '?' && *name != *glob)
{
// For normal characters the name must match the glob,
// but for ? we don't care what the character is.
return false;
}
++name;
++glob;
}
// Match successful when glob and name end at the same time.
return *name == '\0';
}
const char *I_NextGlob(glob_t *glob)
{
struct dirent *de;
do
{
de = readdir(glob->dir);
if (de == NULL)
{
return NULL;
}
} while (de->d_type != DT_REG || !MatchesGlob(de->d_name, glob->glob));
// Return the fully-qualified path, not just the bare filename.
free(glob->last_filename);
glob->last_filename = M_StringJoin(glob->directory, DIR_SEPARATOR_S,
de->d_name, NULL);
return glob->last_filename;
}
#else /* #ifndef HAVE_DIRENT_H */
#warning No native implementation of file globbing.
glob_t *I_StartGlob(const char *directory, const char *glob)
{
return NULL;
}
void I_EndGlob(glob_t *glob)
{
}
const char *I_NextGlob(glob_t *glob)
{
return "";
}
#endif /* #ifndef HAVE_DIRENT_H */

36
src/i_glob.h Normal file
View file

@ -0,0 +1,36 @@
//
// Copyright(C) 2018 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// System specific file globbing interface.
//
#ifndef __I_GLOB__
#define __I_GLOB__
typedef struct glob_s glob_t;
// Start reading a list of file paths from the given directory which match
// the given glob pattern. I_EndGlob() must be called on completion.
glob_t *I_StartGlob(const char *directory, const char *glob);
// Finish reading file list.
void I_EndGlob(glob_t *glob);
// Read the name of the next globbed filename. NULL is returned if there
// are no more found.
const char *I_NextGlob(glob_t *glob);
#endif