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)
14 return 1; // end of pattern
15 case '?': // match any single character
16 if (*in == 0 || *in == '/' || *in == '\\' || *in == ':')
21 case '*': // match anything until following string
27 if (*in == '/' || *in == '\\' || *in == ':')
29 // see if pattern matches at this offset
30 if (matchpattern(in, pattern, caseinsensitive))
32 // nope, advance to next offset
42 if (c1 >= 'A' && c1 <= 'Z')
45 if (c2 >= 'A' && c2 <= 'Z')
56 return 0; // reached end of pattern but not end of input
60 // a little chained strings system
61 stringlist_t *stringlistappend(stringlist_t *current, char *text)
63 stringlist_t *newitem;
66 textlen = strlen(text) + 1;
67 newitem = (stringlist_t *)Z_Malloc(textlen + sizeof(stringlist_t));
69 newitem->text = (char *)(newitem + 1);
70 memcpy(newitem->text, text, textlen);
72 current->next = newitem;
76 void stringlistfree(stringlist_t *current)
87 stringlist_t *stringlistsort(stringlist_t *start)
90 stringlist_t *current, *previous, *temp2, *temp3, *temp4;
91 // exit early if there's nothing to sort
92 if (start == NULL || start->next == NULL)
100 while (current && current->next)
102 if (strcmp(current->text, current->next->text) > 0)
104 // current is greater than next
106 temp2 = current->next;
108 temp4 = current->next->next;
110 previous->next = temp2;
118 current = current->next;
124 // operating system specific code
127 stringlist_t *listdirectory(const char *path)
129 char pattern[4096], *c;
130 struct _finddata_t n_file;
132 stringlist_t *start, *current;
133 strlcpy (pattern, path, sizeof (pattern));
134 strlcat (pattern, "*", sizeof (pattern));
135 // ask for the directory listing handle
136 hFile = _findfirst(pattern, &n_file);
139 // start a new chain with the the first name
140 start = current = stringlistappend(NULL, n_file.name);
141 // iterate through the directory
142 while (_findnext(hFile, &n_file) == 0)
143 current = stringlistappend(current, n_file.name);
146 // convert names to lowercase because windows does not care, but pattern matching code often does
147 for (current = start;current;current = current->next)
148 for (c = current->text;*c;c++)
149 if (*c >= 'A' && *c <= 'Z')
152 // sort the list alphanumerically
153 return stringlistsort(start);
157 stringlist_t *listdirectory(const char *path)
161 stringlist_t *start, *current;
165 start = current = NULL;
166 while ((ent = readdir(dir)))
168 if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
170 current = stringlistappend(current, ent->d_name);
176 // sort the list alphanumerically
177 return stringlistsort(start);
181 void freedirectory(stringlist_t *list)
183 stringlistfree(list);