Commit 7a1370d0 authored by Pádraig Ó Conbhuí's avatar Pádraig Ó Conbhuí
Browse files

filesystem.cpp: Use reused path buffer for directory recursion. Use...

filesystem.cpp: Use reused path buffer for directory recursion. Use std::string_view for input directory name type, and std::string for returned filename type. Remove common_types.hpp.
parent b4ab3e49
---
Checks: '*,
-llvm-header-guard,
-fuchsia-default-arguments,
-fuchsia-trailing-return,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-fuchsia-default-arguments,
-fuchsia-trailing-return,
-google-runtime-references,
-hicpp-no-array-decay'
# -cppcoreguidelines-pro-bounds-array-to-pointer-decay
......
#ifndef MEGADEP_COMMON_TYPES_HPP
#define MEGADEP_COMMON_TYPES_HPP
#include <cstdint>
#include <string>
namespace megadep {
using FileName = std::string;
using DirectoryName = std::string;
using FileHash = uint32_t;
} // namespace megadep
#endif // MEGADEP_COMMON_TYPES_HPP
#include <megadep/common_types.hpp>
#include <megadep/config.hpp>
#include <megadep/filesystem.hpp>
......@@ -14,23 +13,45 @@
namespace megadep {
std::vector<FileName> list_files(const DirectoryName &directory) {
std::vector<FileName> file_names;
static void list_files_impl(char *path_begin, char *path_end,
std::vector<std::string> &file_names);
DIR *dir_ptr = opendir(directory.c_str());
std::vector<std::string> list_files(std::string_view directory) {
std::vector<std::string> file_names;
std::array<char, filename_max> path_buffer{};
directory.copy(path_buffer.begin(), path_buffer.size());
list_files_impl(path_buffer.begin(), path_buffer.begin() + directory.size(),
file_names);
return file_names;
}
// This implimentation takes advantage of recursing into directories only
// needing to append values to the current directory path.
// The function only ever reads the region [path_begin, path_end], and
// edits the region [path_end, path_max) for recursive calls, bumping the
// `path_end` pointer along to recursive calls.
static void list_files_impl(char *path_begin, char *path_end,
std::vector<std::string> &file_names) {
*path_end = '\0';
DIR *dir_ptr = opendir(path_begin);
// Directory is a file, return the directory name
if (dir_ptr == nullptr) {
if (errno == ENOTDIR || errno == ENOENT) {
return {directory};
file_names.emplace_back(path_begin);
return;
}
return {};
return;
}
dirent *entity_ptr;
while ((entity_ptr = readdir(dir_ptr)) != nullptr) {
const char *entity_name = static_cast<const char *>(entity_ptr->d_name);
const size_t entity_name_size = strlen(entity_name);
// Skip . and ..
if (strcmp(entity_name, ".") == 0) {
......@@ -40,17 +61,20 @@ std::vector<FileName> list_files(const DirectoryName &directory) {
continue;
}
// Try recursing
auto sub_files = list_files(directory + '/' + entity_name);
// Copy the entity to the end of the current path and recurse.
assert(path_end - path_begin + entity_name_size + 2 < filename_max &&
"Filename is too big for filename buffer!");
for (auto &sub_file : sub_files) {
file_names.emplace_back(std::move(sub_file));
}
*path_end = '/';
auto new_entity_start = std::next(path_end);
std::copy_n(entity_name, entity_name_size, new_entity_start);
auto new_entity_end = std::next(new_entity_start, entity_name_size);
list_files_impl(path_begin, new_entity_end, file_names);
}
closedir(dir_ptr);
return file_names;
}
namespace {
......
#ifndef MEGADEP_FILESYSTEM_HPP
#define MEGADEP_FILESYSTEM_HPP
#include <megadep/common_types.hpp>
#include <string>
#include <string_view>
#include <vector>
......@@ -11,7 +9,7 @@
namespace megadep {
std::vector<FileName> list_files(const DirectoryName &directory);
std::vector<std::string> list_files(std::string_view directory);
std::vector<std::string> read_includes(std::string_view file_name);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment