distinguish between files and directories

listfiles now optionally sorts the list and removes doubles
This commit is contained in:
ac-stef
2017-06-12 18:17:15 +02:00
parent 7a02ccd8b7
commit 661ee6eff2
8 changed files with 161 additions and 36 deletions
+134 -17
View File
@@ -261,17 +261,25 @@ const char *findfile(const char *filename, const char *mode)
return filename;
}
bool listdir(const char *dir, const char *ext, vector<char *> &files)
const char *stream_capabilities()
{
#if !defined(WIN32) && !defined(_DIRENT_HAVE_D_TYPE)
return "no support for d_type, listing directories may be slow";
#else
return "";
#endif
}
bool listsubdir(const char *dir, vector<char *> &subdirs)
{
int extsize = ext ? (int)strlen(ext)+1 : 0;
#if defined(WIN32)
defformatstring(pathname)("%s\\*.%s", dir, ext ? ext : "*");
defformatstring(pathname)("%s\\*", dir);
WIN32_FIND_DATA FindFileData;
HANDLE Find = FindFirstFile(path(pathname), &FindFileData);
if(Find != INVALID_HANDLE_VALUE)
{
do {
files.add(newstring(FindFileData.cFileName, (int)strlen(FindFileData.cFileName) - extsize));
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) subdirs.add(newstring(FindFileData.cFileName));
} while(FindNextFile(Find, &FindFileData));
FindClose(Find);
return true;
@@ -285,12 +293,90 @@ bool listdir(const char *dir, const char *ext, vector<char *> &files)
struct dirent *de, b;
while(!readdir_r(d, &b, &de) && de != NULL)
{
if(!ext) files.add(newstring(de->d_name));
else
#ifdef _DIRENT_HAVE_D_TYPE
if(de->d_type == DT_DIR) subdirs.add(newstring(de->d_name));
#else
struct stat s;
int dl = (int)strlen(pathname);
concatformatstring(pathname, "/%s", de->d_name);
if(!lstat(pathname, &s) && S_ISDIR(s.st_mode)) subdirs.add(newstring(de->d_name));
pathname[dl] = '\0';
#endif
}
closedir(d);
return true;
}
#endif
else return false;
}
void listsubdirs(const char *dir, vector<char *> &subdirs, int (__cdecl *sf)(const char **, const char **))
{
listsubdir(dir, subdirs);
string s;
if(homedir[0])
{
formatstring(s)("%s%s", homedir, dir);
listsubdir(s, subdirs);
}
loopv(packagedirs)
{
formatstring(s)("%s%s", packagedirs[i], dir);
listsubdir(s, subdirs);
}
#ifndef STANDALONE
listzipdirs(dir, subdirs);
#endif
subdirs.sort(sf);
for(int i = subdirs.length() - 1; i > 0; i--)
{ // remove doubles
if(!strcmp(subdirs[i], subdirs[i - 1])) delstring(subdirs.remove(i));
}
}
bool listdir(const char *dir, const char *ext, vector<char *> &files)
{
int extsize = ext ? (int)strlen(ext)+1 : 0;
#if defined(WIN32)
defformatstring(pathname)("%s\\*.%s", dir, ext ? ext : "*");
WIN32_FIND_DATA FindFileData;
HANDLE Find = FindFirstFile(path(pathname), &FindFileData);
if(Find != INVALID_HANDLE_VALUE)
{
do {
if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
files.add(newstring(FindFileData.cFileName, (int)strlen(FindFileData.cFileName) - extsize));
} while(FindNextFile(Find, &FindFileData));
FindClose(Find);
return true;
}
#else
string pathname;
copystring(pathname, dir);
DIR *d = opendir(path(pathname));
if(d)
{
struct dirent *de, b;
while(!readdir_r(d, &b, &de) && de != NULL)
{
#ifdef _DIRENT_HAVE_D_TYPE
if(de->d_type == DT_REG)
#else
struct stat s;
int dl = (int)strlen(pathname);
concatformatstring(pathname, "/%s", de->d_name);
bool isreg = !lstat(pathname, &s) && !S_ISDIR(s.st_mode);
pathname[dl] = '\0';
if(isreg)
#endif
{
int namelength = (int)strlen(de->d_name) - extsize;
if(namelength > 0 && de->d_name[namelength] == '.' && strncmp(de->d_name+namelength+1, ext, extsize-1)==0)
files.add(newstring(de->d_name, namelength));
if(!ext) files.add(newstring(de->d_name));
else
{
int namelength = (int)strlen(de->d_name) - extsize;
if(namelength > 0 && de->d_name[namelength] == '.' && strncmp(de->d_name+namelength+1, ext, extsize-1)==0)
files.add(newstring(de->d_name, namelength));
}
}
}
closedir(d);
@@ -300,7 +386,7 @@ bool listdir(const char *dir, const char *ext, vector<char *> &files)
else return false;
}
void listfiles(const char *dir, const char *ext, vector<char *> &files)
void listfiles(const char *dir, const char *ext, vector<char *> &files, int (__cdecl *sf)(const char **, const char **))
{
listdir(dir, ext, files);
string s;
@@ -317,25 +403,56 @@ void listfiles(const char *dir, const char *ext, vector<char *> &files)
#ifndef STANDALONE
listzipfiles(dir, ext, files);
#endif
if(sf)
{ // sort and remove doubles
files.sort(sf);
for(int i = files.length() - 1; i > 0; i--)
{
if(!strcmp(files[i], files[i - 1])) delstring(files.remove(i));
}
}
}
#ifndef STANDALONE
void listfilesrecursive(const char *dir, vector<char *> &files, int level)
{
if(level > 8) return; // 8 levels is insane enough...
vector<char *> thisdir;
vector<char *> dirs, thisdir;
listsubdirs(dir, dirs, stringsort);
loopv(dirs)
{
if(dirs[i][0] != '.') // ignore "." and ".." (and also other directories starting with '.', like it is unix-convention - and doesn't hurt on windows)
{
defformatstring(name)("%s/%s", dir, dirs[i]);
listfilesrecursive(name, files, level + 1);
}
delstring(dirs[i]);
}
listfiles(dir, NULL, thisdir);
loopv(thisdir)
{
if(thisdir[i][0] != '.') // ignore "." and ".." (and also other directories starting with '.', like it is unix-convention - and doesn't hurt on windows)
{
defformatstring(name)("%s/%s", dir, thisdir[i]);
files.add(newstring(name));
listfilesrecursive(name, files, level + 1);
}
defformatstring(name)("%s/%s", dir, thisdir[i]);
files.add(newstring(name));
delstring(thisdir[i]);
}
}
void listdirsrecursive(const char *dir, vector<char *> &subdirs, int level)
{
if(level > 8) return; // 8 levels is insane enough...
vector<char *> dirs;
listsubdirs(dir, dirs, stringsort);
loopv(dirs)
{
if(dirs[i][0] != '.') // ignore "." and ".." (and also other directories starting with '.', like it is unix-convention - and doesn't hurt on windows)
{
defformatstring(name)("%s/%s", dir, dirs[i]);
subdirs.add(newstring(name));
listdirsrecursive(name, subdirs, level + 1);
}
delstring(dirs[i]);
}
}
#endif
bool delfile(const char *path)