4657: Reduce system API calls when listing directory contents r=heinrich5991 a=Robyt3

Optimize `fs_listdir` and `fs_listdir_fileinfo` by reducing nested calls to `fs_is_dir` (and subsequent additional system API calls).
- Windows: check file attributes in `WIN32_FIND_DATAW finddata` instead of calling WinAPI again.
- Others: check file type of `struct dirent *entry` instead of calling `stat`. The file type may not be available on all filesystems, so a call to `fs_is_dir` is used as fallback.

Tested on Windows and Ubuntu.

See #4652. This reduces additional overhead.

## Checklist

- [X] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Robert Müller <robert.mueller@uni-siegen.de>
This commit is contained in:
bors[bot] 2022-02-04 17:16:57 +00:00 committed by GitHub
commit 37fc74ccba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -2151,7 +2151,7 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
{
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, sizeof(buffer2), NULL, NULL);
str_copy(buffer + length, buffer2, (int)sizeof(buffer) - length);
if(cb(buffer2, fs_is_dir(buffer), type, user))
if(cb(buffer2, (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0, type, user))
break;
} while(FindNextFileW(handle, &finddata));
@ -2171,7 +2171,7 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
while((entry = readdir(d)) != NULL)
{
str_copy(buffer + length, entry->d_name, (int)sizeof(buffer) - length);
if(cb(entry->d_name, fs_is_dir(buffer), type, user))
if(cb(entry->d_name, entry->d_type == DT_UNKNOWN ? fs_is_dir(buffer) : entry->d_type == DT_DIR, type, user))
break;
}
@ -2211,7 +2211,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
info.m_TimeCreated = filetime_to_unixtime(&finddata.ftCreationTime);
info.m_TimeModified = filetime_to_unixtime(&finddata.ftLastWriteTime);
if(cb(&info, fs_is_dir(buffer), type, user))
if(cb(&info, (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0, type, user))
break;
} while(FindNextFileW(handle, &finddata));
@ -2240,7 +2240,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
info.m_TimeCreated = created;
info.m_TimeModified = modified;
if(cb(&info, fs_is_dir(buffer), type, user))
if(cb(&info, entry->d_type == DT_UNKNOWN ? fs_is_dir(buffer) : entry->d_type == DT_DIR, type, user))
break;
}