Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Swap out the horrible hacks for something more elegant.

  • Loading branch information...
commit b5095003217bde915bdc7679a0ce0731e20b13f7 1 parent 041d4e5
@Deiz Deiz authored
View
85 src/ndata.c
@@ -89,7 +89,7 @@ static int ndata_isndata( const char *path, ... );
static void ndata_notfound (void);
static char** ndata_listBackend( const char* path, uint32_t* nfiles, int dirs );
static char** filterList( const char** list, int nlist,
- const char* path, uint32_t* nfiles, int dirs );
+ const char* path, uint32_t* nfiles, int recursive );
/**
@@ -686,15 +686,14 @@ SDL_RWops *ndata_rwops( const char* filename )
* @param list List to filter.
* @param nlist Members in list.
* @param path Path to filter.
- * @param dirs Whether directories should be included.
+ * @param recursive Whether all children at any depth should be listed.
* @param[out] nfiles Files that match.
*/
static char** filterList( const char** list, int nlist,
- const char* path, uint32_t* nfiles, int dirs )
+ const char* path, uint32_t* nfiles, int recursive )
{
- char **filtered, *tmp;
- int i, j, k, sl;
- int len;
+ char **filtered;
+ int i, j, k, len;
/* Maximum size by default. */
filtered = malloc(sizeof(char*) * nlist);
@@ -709,21 +708,18 @@ static char** filterList( const char** list, int nlist,
/* Make sure there are no stray '/'. */
for (k=len; list[i][k] != '\0'; k++)
- if (list[i][k] == '/') {
- if (dirs) {
- sl = k-len + 2;
- tmp = malloc( sl*sizeof(char) );
- nsnprintf( tmp, sl, "%s", &list[i][len] );
- filtered[j++] = strdup(tmp);
- free(tmp);
- }
- break;
- }
+ if (list[i][k] == '/')
+ if (!recursive)
+ break;
+
if (list[i][k] != '\0')
continue;
/* Copy the file name without the path. */
- filtered[j++] = strdup(&list[i][len]);
+ if (!recursive)
+ filtered[j++] = strdup(&list[i][len]);
+ else /* Recursive needs paths. */
+ filtered[j++] = strdup(list[i]);
}
/* Return results. */
@@ -741,22 +737,28 @@ static char** filterList( const char** list, int nlist,
* @param nfiles Number of files found.
* @return List of files found.
*/
-static char** ndata_listBackend( const char* path, uint32_t* nfiles, int dirs )
+static char** ndata_listBackend( const char* path, uint32_t* nfiles, int recursive )
{
(void) path;
char **files, buf[PATH_MAX], *tmp;
int n;
+ char** (*nfile_readFunc) ( int* nfiles, const char* path, ... ) = NULL;
+
+ if (recursive)
+ nfile_readFunc = nfile_readDirRecursive;
+ else
+ nfile_readFunc = nfile_readDir;
/* Already loaded the list. */
if (ndata_fileList != NULL)
- return filterList( ndata_fileList, ndata_fileNList, path, nfiles, dirs );
+ return filterList( ndata_fileList, ndata_fileNList, path, nfiles, recursive );
/* See if can load from local directory. */
if (ndata_cache == NULL) {
/* Local search. */
if (ndata_source <= NDATA_SRC_LAIDOUT) {
- files = nfile_readDir( &n, path );
+ files = nfile_readFunc( &n, path );
if (files != NULL) {
*nfiles = n;
return files;
@@ -767,7 +769,7 @@ static char** ndata_listBackend( const char* path, uint32_t* nfiles, int dirs )
if ((ndata_filename == NULL) && (ndata_dirname != NULL) &&
(ndata_source <= NDATA_SRC_NDATADEF)) {
nsnprintf( buf, sizeof(buf), "%s/%s", ndata_dirname, path );
- files = nfile_readDir( &n, buf );
+ files = nfile_readFunc( &n, buf );
if (files != NULL) {
*nfiles = n;
return files;
@@ -779,7 +781,7 @@ static char** ndata_listBackend( const char* path, uint32_t* nfiles, int dirs )
tmp = strdup( NDATA_DEF );
nsnprintf( buf, sizeof(buf), "%s/%s", nfile_dirname(tmp), path );
free(tmp);
- files = nfile_readDir( &n, buf );
+ files = nfile_readFunc( &n, buf );
if (files != NULL) {
*nfiles = n;
return files;
@@ -791,7 +793,7 @@ static char** ndata_listBackend( const char* path, uint32_t* nfiles, int dirs )
tmp = strdup( naev_binary() );
nsnprintf( buf, sizeof(buf), "%s/%s", nfile_dirname(tmp), path );
free(tmp);
- files = nfile_readDir( &n, buf );
+ files = nfile_readFunc( &n, buf );
if (files != NULL) {
*nfiles = n;
return files;
@@ -811,11 +813,11 @@ static char** ndata_listBackend( const char* path, uint32_t* nfiles, int dirs )
/* Load list. */
ndata_fileList = pack_listfilesCached( ndata_cache, &ndata_fileNList );
- return filterList( ndata_fileList, ndata_fileNList, path, nfiles, dirs );
+ return filterList( ndata_fileList, ndata_fileNList, path, nfiles, recursive );
}
/**
- * @brief Gets a list of files in the ndata, excluding directories.
+ * @brief Gets a list of files in the ndata that are direct children of a path.
*
* @sa ndata_listBackend
*/
@@ -826,40 +828,13 @@ char** ndata_list( const char* path, uint32_t* nfiles )
/**
- * @brief Gets a list of files in the ndata, including directories.
+ * @brief Gets a list of files in the ndata below a certain path.
*
* @sa ndata_listBackend
*/
-char** ndata_listDirs( const char* path, uint32_t* nfiles )
+char** ndata_listRecursive( const char* path, uint32_t* nfiles )
{
- char **tmpout, **output;
- uint32_t tmp;
- int i, j, nout, have;
-
- tmpout = ndata_listBackend( path, &tmp, 1 );
-
- nout = 0;
- output = malloc( sizeof(char*) * tmp );
-
- /* Duplicate directories must be removed. */
- if (tmp)
- output[nout++] = tmpout[0];
- for (i=0; i<(int)tmp; i++) {
- have = 0;
- for (j=0; j<nout; j++) {
- /* We have this one already. */
- if (strcmp(tmpout[i],output[j])==0) {
- have = 1;
- break;
- }
- }
- /* Add new file or directory to output. */
- if (!have)
- output[nout++] = tmpout[i];
- }
-
- *nfiles = nout;
- return output;
+ return ndata_listBackend( path, nfiles, 1 );
}
View
2  src/ndata.h
@@ -73,7 +73,7 @@ const char* ndata_name (void);
*/
void* ndata_read( const char* filename, uint32_t *filesize );
char** ndata_list( const char *path, uint32_t* nfiles );
-char** ndata_listDirs( const char *path, uint32_t* nfiles );
+char** ndata_listRecursive( const char *path, uint32_t* nfiles );
void ndata_sortName( char **files, uint32_t nfiles );
View
60 src/nfile.c
@@ -530,6 +530,66 @@ char** nfile_readDir( int* nfiles, const char* path, ... )
/**
+ * @brief Lists all the visible files in a directory, at any depth.
+ *
+ * Should also sort by last modified but that's up to the OS in question.
+ * Paths are relative to base directory.
+ *
+ * @param[out] nfiles Returns how many files there are.
+ * @param path Directory to read.
+ */
+char** nfile_readDirRecursive( int* nfiles, const char* path, ... )
+{
+ char **tfiles, **out, **cfiles, *buf, base[PATH_MAX];
+ int i, j, ls, mfiles, tmp, cn;
+ va_list ap;
+
+ va_start(ap, path);
+ vsnprintf( base, PATH_MAX, path, ap );
+ va_end(ap);
+
+ mfiles = 128;
+ out = malloc(sizeof(char*)*mfiles);
+ tfiles = nfile_readDir( &tmp, base );
+ *nfiles = 0;
+
+ for (i=0; i<tmp; i++) {
+ ls = strlen(base) + strlen(tfiles[i]) + 1;
+ buf = malloc(ls * sizeof(char));
+ nsnprintf( buf, ls, "%s%s", path, tfiles[i] );
+ if (nfile_dirExists(buf)) {
+ /* Append slash if necessary. */
+ if (strcmp(&buf[ls-1],"/")!=0) {
+ buf = realloc( buf, (ls+1) * sizeof(char) );
+ nsnprintf( buf, ls+1, "%s%s/", path, tfiles[i] );
+ }
+
+ /* Iterate over children. */
+ cfiles = nfile_readDirRecursive( &cn, buf );
+ for (j=0; j<cn; j++) {
+ if ((*nfiles+1) > mfiles) {
+ mfiles *= 2;
+ out = realloc( out, sizeof(char*)*mfiles );
+ }
+ out[(*nfiles)++] = strdup( cfiles[j] );
+ }
+ free(cfiles);
+ }
+ else {
+ if ((*nfiles+1) > mfiles) {
+ mfiles *= 2;
+ out = realloc( out, sizeof(char*)*mfiles );
+ }
+ out[(*nfiles)++] = strdup( buf );
+ }
+ free(buf);
+ }
+
+ free(tfiles);
+ return out;
+}
+
+/**
* @brief Tries to read a file.
*
* @param filesize Stores the size of the file.
View
1  src/nfile.h
@@ -16,6 +16,7 @@ int nfile_dirExists( const char* path, ... ); /* Returns 1 on exists. */
int nfile_fileExists( const char* path, ... ); /* Returns 1 on exists */
int nfile_backupIfExists( const char* path, ... );
char** nfile_readDir( int* nfiles, const char* path, ... );
+char** nfile_readDirRecursive( int* nfiles, const char* path, ... );
char* nfile_readFile( int* filesize, const char* path, ... );
int nfile_touch( const char* path, ... );
int nfile_writeFile( const char* data, int len, const char* path, ... );
View
43 src/outfit.c
@@ -2026,47 +2026,20 @@ if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define
/**
* @brief Loads all the files in a directory.
+ *
+ * @param dir Directory to load files from.
+ * @return 0 on success.
*/
static int outfit_loadDir( char *dir )
{
- uint32_t nfiles, isfile;
+ uint32_t nfiles;
char **outfit_files;
- char *file, *buf, *ndata;
- int i, len, sl;
-
- outfit_files = ndata_listDirs( dir, &nfiles );
- for (i=0; i<(int)nfiles; i++) {
- sl = (strlen(outfit_files[i]) + strlen(dir) + 1);
- buf = malloc( sl * sizeof(char) );
- nsnprintf( buf, sl, "%s%s", dir, outfit_files[i] );
-
- ndata = (char*)ndata_getPath();
- if (ndata != NULL) {
- /* Horrible hack. Returns 1 for single files and 0 for directories. */
- ndata_list( buf, &isfile );
- free( buf );
- }
+ int i;
- file = malloc( sl*sizeof(char) );
- nsnprintf( file, sl, "%s%s", dir, outfit_files[i] );
- if (((ndata != NULL) && (isfile != 1)) || nfile_dirExists(file) ) {
- len = strlen(file);
- if (strcmp(&file[len-1],"/")==0)
- outfit_loadDir( file );
- /* Directories must always have trailing slashes. */
- else {
- sl = strlen(file)+2;
- buf = malloc( sl*sizeof(char) );
- nsnprintf( buf, sl, "%s/", file );
- outfit_loadDir( buf );
- free( buf );
- }
- }
- else
- outfit_parse( &array_grow(&outfit_stack), file );
+ outfit_files = ndata_listRecursive( dir, &nfiles );
+ for (i=0; i<(int)nfiles; i++)
+ outfit_parse( &array_grow(&outfit_stack), outfit_files[i] );
- free( file );
- }
array_shrink( &outfit_stack );
return 0;
Please sign in to comment.
Something went wrong with that request. Please try again.