Fix redundant glTexEnv calls
[neverball] / share / dir.c
1 /*
2  * Copyright (C) 2003-2010 Neverball authors
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <dirent.h>
16
17 #include <string.h>
18 #include <stdlib.h>
19 #include <assert.h>
20
21 #include "dir.h"
22 #include "common.h"
23
24 /*
25  * HACK: MinGW provides numerous POSIX extensions to MSVCRT, including
26  * dirent.h, so parasti ever so lazily has not bothered to port the
27  * code below to FindFirstFile et al.
28  */
29
30 List dir_list_files(const char *path)
31 {
32     DIR *dir;
33     List files = NULL;
34
35     if ((dir = opendir(path)))
36     {
37         struct dirent *ent;
38
39         while ((ent = readdir(dir)))
40         {
41             if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
42                 continue;
43
44             files = list_cons(strdup(ent->d_name), files);
45         }
46
47         closedir(dir);
48     }
49
50     return files;
51 }
52
53 void dir_list_free(List files)
54 {
55     while (files)
56     {
57         free(files->data);
58         files = list_rest(files);
59     }
60 }
61
62 static struct dir_item *add_item(Array items, const char *dir, const char *name)
63 {
64     struct dir_item *item = array_add(items);
65
66     item->path = path_join(dir, name);
67     item->data = NULL;
68
69     return item;
70 }
71
72 static void del_item(Array items)
73 {
74     struct dir_item *item = array_get(items, array_len(items) - 1);
75
76     free((void *) item->path);
77     assert(!item->data);
78
79     array_del(items);
80 }
81
82 Array dir_scan(const char *path,
83                int  (*filter)    (struct dir_item *),
84                List (*list_files)(const char *),
85                void (*free_files)(List))
86 {
87     List files, file;
88     Array items = NULL;
89
90     assert((list_files && free_files) || (!list_files || !free_files));
91
92     if (!list_files) list_files = dir_list_files;
93     if (!free_files) free_files = dir_list_free;
94
95     items = array_new(sizeof (struct dir_item));
96
97     if ((files = list_files(path)))
98     {
99         for (file = files; file; file = file->next)
100         {
101             struct dir_item *item;
102
103             item = add_item(items, path, file->data);
104
105             if (filter && !filter(item))
106                 del_item(items);
107         }
108
109         free_files(files);
110     }
111
112     return items;
113 }
114
115 void dir_free(Array items)
116 {
117     while (array_len(items))
118         del_item(items);
119
120     array_free(items);
121 }
122
123 int dir_exists(const char *path)
124 {
125     DIR *dir;
126
127     if ((dir = opendir(path)))
128     {
129         closedir(dir);
130         return 1;
131     }
132     return 0;
133 }