Rewrite directory scanner to use linked lists
authorparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Tue, 16 Nov 2010 22:00:37 +0000 (22:00 +0000)
committerparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Tue, 16 Nov 2010 22:00:37 +0000 (22:00 +0000)
git-svn-id: https://s.snth.net/svn/neverball/trunk@3363 78b8d119-cf0a-0410-b17c-f493084dd1d7

share/dir.c
share/dir.h
share/fs_physfs.c

index aaeb03a..345fdab 100644 (file)
 #include "dir.h"
 #include "common.h"
 
-static char **get_dir_list(const char *path)
+/*
+ * HACK: MinGW provides numerous POSIX extensions to MSVCRT, including
+ * dirent.h, so parasti ever so lazily has not bothered to port the
+ * code below to FindFirstFile et al.
+ */
+
+List dir_list_files(const char *path)
 {
     DIR *dir;
-    char **files = NULL;
-    int count = 0;
-
-    /*
-     * HACK: MinGW provides numerous POSIX extensions to MSVCRT,
-     * including dirent.h, so parasti ever so lazily has not bothered
-     * to port the code below to FindFirstFile et al.
-     */
+    List files = NULL;
 
     if ((dir = opendir(path)))
     {
         struct dirent *ent;
 
-        files = malloc(sizeof (char *));
-
         while ((ent = readdir(dir)))
         {
             if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
                 continue;
 
-            files[count++] = strdup(ent->d_name);
-            files = realloc(files, (count + 1) * sizeof (char *));
+            files = list_cons(strdup(ent->d_name), files);
         }
 
-        files[count] = NULL;
-
         closedir(dir);
     }
 
     return files;
 }
 
-static void free_dir_list(void *files)
+void dir_list_free(List files)
 {
-    if (files)
+    while (files)
     {
-        char **file;
-
-        /* Free file names. */
-        for (file = files; *file; free(*file++));
-
-        /* Free trailing NULL. */
-        free(*file);
-
-        /* Free pointer list. */
-        free(files);
+        free(files->data);
+        files = list_rest(files);
     }
 }
 
@@ -94,40 +80,33 @@ static void del_item(Array items)
 }
 
 Array dir_scan(const char *path,
-               int    (*filter)   (struct dir_item *),
-               char **(*get_list) (const char *),
-               void   (*free_list)(void *))
+               int  (*filter)    (struct dir_item *),
+               List (*list_files)(const char *),
+               void (*free_files)(List))
 {
-    char **list;
+    List files, file;
     Array items = NULL;
 
-    assert((get_list && free_list) || (!get_list && !free_list));
+    assert((list_files && free_files) || (!list_files || !free_files));
 
-    if (!get_list)
-        get_list = get_dir_list;
+    if (!list_files) list_files = dir_list_files;
+    if (!free_files) free_files = dir_list_free;
 
-    if (!free_list)
-        free_list = free_dir_list;
-
-    if ((list = get_list(path)))
+    if ((files = list_files(path)))
     {
-        char **file = list;
-
         items = array_new(sizeof (struct dir_item));
 
-        while (*file)
+        for (file = files; file; file = file->next)
         {
             struct dir_item *item;
 
-            item = add_item(items, path, *file);
+            item = add_item(items, path, file->data);
 
             if (filter && !filter(item))
                 del_item(items);
-
-            file++;
         }
 
-        free_list(list);
+        free_files(files);
     }
 
     return items;
index 1a3548f..7e3bc08 100644 (file)
@@ -2,6 +2,7 @@
 #define DIR_H
 
 #include "array.h"
+#include "list.h"
 
 struct dir_item
 {
@@ -17,9 +18,12 @@ struct dir_item
 #define DIR_ITEM_GET(a, i) ((struct dir_item *) array_get((a), (i)))
 
 Array dir_scan(const char *,
-               int    (*filter)   (struct dir_item *),
-               char **(*get_list) (const char *),
-               void   (*free_list)(void *));
+               int  (*filter)    (struct dir_item *),
+               List (*list_files)(const char *),
+               void (*free_files)(List));
 void  dir_free(Array);
 
+List dir_list_files(const char *);
+void dir_list_free (List);
+
 #endif
index b0e50f5..c920b63 100644 (file)
@@ -20,6 +20,7 @@
 #include "fs.h"
 #include "dir.h"
 #include "array.h"
+#include "common.h"
 
 /*
  * This file implements the low-level virtual file system routines
@@ -78,9 +79,34 @@ const char *fs_get_write_dir(void)
 
 /*---------------------------------------------------------------------------*/
 
+static List list_files(const char *path)
+{
+    List list = NULL;
+    char **files, **file;
+
+    if ((files = PHYSFS_enumerateFiles(path)))
+    {
+        for (file = files; *file; file++)
+            list = list_cons(strdup(*file), list);
+
+        PHYSFS_freeList(files);
+    }
+
+    return list;
+}
+
+static void free_files(List list)
+{
+    while (list)
+    {
+        free(list->data);
+        list = list_rest(list);
+    }
+}
+
 Array fs_dir_scan(const char *path, int (*filter)(struct dir_item *))
 {
-    return dir_scan(path, filter, PHYSFS_enumerateFiles, PHYSFS_freeList);
+    return dir_scan(path, filter, list_files, free_files);
 }
 
 void fs_dir_free(Array items)