mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-22 00:19:28 +00:00
Convert GetFilesInFolderHelper to use BFS (#268)
This function has a huge stack frame (> 8k, thanks to tinydir), and is called recursively. I have seen this function causing some stack overflows. So convert it to BFS to avoid that.
This commit is contained in:
parent
0ef5aec3fc
commit
b644b54614
74
src/utils.cc
74
src/utils.cc
@ -140,49 +140,53 @@ static void GetFilesInFolderHelper(
|
|||||||
bool recursive,
|
bool recursive,
|
||||||
std::string output_prefix,
|
std::string output_prefix,
|
||||||
const std::function<void(const std::string&)>& handler) {
|
const std::function<void(const std::string&)>& handler) {
|
||||||
tinydir_dir dir;
|
std::queue<std::pair<std::string, std::string>> q;
|
||||||
if (tinydir_open(&dir, folder.c_str()) == -1) {
|
q.push(make_pair(folder, output_prefix));
|
||||||
LOG_S(WARNING) << "Unable to open directory " << folder;
|
while(!q.empty()) {
|
||||||
goto bail;
|
tinydir_dir dir;
|
||||||
}
|
if (tinydir_open(&dir, q.front().first.c_str()) == -1) {
|
||||||
|
LOG_S(WARNING) << "Unable to open directory " << folder;
|
||||||
while (dir.has_next) {
|
|
||||||
tinydir_file file;
|
|
||||||
if (tinydir_readfile(&dir, &file) == -1) {
|
|
||||||
LOG_S(WARNING) << "Unable to read file " << file.name
|
|
||||||
<< " when reading directory " << folder;
|
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip all dot files.
|
while (dir.has_next) {
|
||||||
//
|
tinydir_file file;
|
||||||
// The nested ifs are intentional, branching order is subtle here.
|
if (tinydir_readfile(&dir, &file) == -1) {
|
||||||
//
|
LOG_S(WARNING) << "Unable to read file " << file.name
|
||||||
// Note that in the future if we do support dot directories/files, we must
|
<< " when reading directory " << folder;
|
||||||
// always ignore the '.' and '..' directories otherwise this will loop
|
goto bail;
|
||||||
// infinitely.
|
}
|
||||||
if (file.name[0] != '.') {
|
|
||||||
if (file.is_dir) {
|
// Skip all dot files.
|
||||||
if (recursive) {
|
//
|
||||||
std::string child_dir = output_prefix + file.name + "/";
|
// The nested ifs are intentional, branching order is subtle here.
|
||||||
if (!IsSymLink(child_dir))
|
//
|
||||||
GetFilesInFolderHelper(file.path, true /*recursive*/, child_dir,
|
// Note that in the future if we do support dot directories/files, we must
|
||||||
handler);
|
// always ignore the '.' and '..' directories otherwise this will loop
|
||||||
|
// infinitely.
|
||||||
|
if (file.name[0] != '.') {
|
||||||
|
if (file.is_dir) {
|
||||||
|
if (recursive) {
|
||||||
|
std::string child_dir = output_prefix + file.name + "/";
|
||||||
|
if (!IsSymLink(child_dir))
|
||||||
|
q.push(make_pair(file.path, child_dir));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handler(q.front().second + file.name);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
handler(output_prefix + file.name);
|
|
||||||
|
if (tinydir_next(&dir) == -1) {
|
||||||
|
LOG_S(WARNING) << "Unable to fetch next file when reading directory "
|
||||||
|
<< folder;
|
||||||
|
goto bail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tinydir_next(&dir) == -1) {
|
bail:
|
||||||
LOG_S(WARNING) << "Unable to fetch next file when reading directory "
|
tinydir_close(&dir);
|
||||||
<< folder;
|
q.pop();
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bail:
|
|
||||||
tinydir_close(&dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetFilesInFolder(std::string folder,
|
std::vector<std::string> GetFilesInFolder(std::string folder,
|
||||||
|
Loading…
Reference in New Issue
Block a user