4 // LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such...
6 int matchpattern(const char *in, const char *pattern, int caseinsensitive)
8 return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false);
11 // wildcard_least_one: if true * matches 1 or more characters
12 // if false * matches 0 or more characters
13 int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one)
21 return 1; // end of pattern
22 case '?': // match any single character
23 if (*in == 0 || strchr(separators, *in))
28 case '*': // match anything until following string
29 if(wildcard_least_one)
31 if (*in == 0 || strchr(separators, *in))
38 if (strchr(separators, *in))
40 // see if pattern matches at this offset
41 if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one))
43 // nope, advance to next offset
53 if (c1 >= 'A' && c1 <= 'Z')
56 if (c2 >= 'A' && c2 <= 'Z')
67 return 0; // reached end of pattern but not end of input
71 // a little strings system
72 void stringlistinit(stringlist_t *list)
74 memset(list, 0, sizeof(*list));
77 void stringlistfreecontents(stringlist_t *list)
80 for (i = 0;i < list->numstrings;i++)
83 Z_Free(list->strings[i]);
84 list->strings[i] = NULL;
89 Z_Free(list->strings);
93 void stringlistappend(stringlist_t *list, const char *text)
98 if (list->numstrings >= list->maxstrings)
100 oldstrings = list->strings;
101 list->maxstrings += 4096;
102 list->strings = (char **) Z_Malloc(list->maxstrings * sizeof(*list->strings));
103 if (list->numstrings)
104 memcpy(list->strings, oldstrings, list->numstrings * sizeof(*list->strings));
108 textlen = strlen(text) + 1;
109 list->strings[list->numstrings] = (char *) Z_Malloc(textlen);
110 memcpy(list->strings[list->numstrings], text, textlen);
114 void stringlistsort(stringlist_t *list)
118 // this is a selection sort (finds the best entry for each slot)
119 for (i = 0;i < list->numstrings - 1;i++)
121 for (j = i + 1;j < list->numstrings;j++)
123 if (strcasecmp(list->strings[i], list->strings[j]) > 0)
125 temp = list->strings[i];
126 list->strings[i] = list->strings[j];
127 list->strings[j] = temp;
133 // operating system specific code
134 static void adddirentry(stringlist_t *list, const char *path, const char *name)
136 if (strcmp(name, ".") && strcmp(name, ".."))
138 char temp[MAX_OSPATH];
139 dpsnprintf( temp, sizeof( temp ), "%s%s", path, name );
140 stringlistappend(list, temp);
145 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
148 char pattern[4096], *c;
149 WIN32_FIND_DATA n_file;
151 strlcpy (pattern, basepath, sizeof(pattern));
152 strlcat (pattern, path, sizeof (pattern));
153 strlcat (pattern, "*", sizeof (pattern));
154 // ask for the directory listing handle
155 hFile = FindFirstFile(pattern, &n_file);
156 if(hFile == INVALID_HANDLE_VALUE)
159 adddirentry(list, path, n_file.cFileName);
160 } while (FindNextFile(hFile, &n_file) != 0);
163 // convert names to lowercase because windows does not care, but pattern matching code often does
164 for (i = 0;i < list->numstrings;i++)
165 for (c = list->strings[i];*c;c++)
166 if (*c >= 'A' && *c <= 'Z')
171 void listdirectory(stringlist_t *list, const char *basepath, const char *path)
173 char fullpath[MAX_OSPATH];
176 dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, *path ? path : "./");
177 dir = opendir(fullpath);
180 while ((ent = readdir(dir)))
181 adddirentry(list, path, ent->d_name);