waycast/lib/files.hpp
2025-08-28 17:03:32 -04:00

109 lines
3.3 KiB
C++

#pragma once
#include <filesystem>
#include <string>
#include <vector>
#include <unordered_set>
#include <system_error>
#include <iostream>
#include <sstream>
#include <fstream>
#include <functional>
namespace files
{
namespace fs = std::filesystem;
inline std::vector<fs::path> findFilesWithExtension(const std::string path, const std::string ext)
{
std::vector<fs::path> out;
std::unordered_set<std::string> seen; // canonicalized paths to dedupe
std::error_code ec;
fs::path p(path);
if (!fs::exists(p, ec) || !fs::is_directory(p, ec))
return out;
for (const auto &entry : fs::directory_iterator(p, ec))
{
if (ec)
{
ec.clear();
continue;
}
const auto &filePath = entry.path();
if (filePath.extension() == ext && fs::is_regular_file(filePath, ec))
{
out.push_back(filePath);
}
}
return out;
}
inline std::vector<fs::path> findAllFiles(const std::string& path, int max_depth = -1)
{
std::vector<fs::path> out;
std::error_code ec;
fs::path p(path);
if (!fs::exists(p, ec) || !fs::is_directory(p, ec))
return out;
// Use recursive_directory_iterator with depth control
auto options = fs::directory_options::skip_permission_denied;
try {
if (max_depth < 0) {
// No depth limit - use unlimited recursion
for (const auto& entry : fs::recursive_directory_iterator(p, options, ec)) {
if (ec) {
ec.clear();
continue;
}
if (entry.is_regular_file(ec) && !ec) {
out.push_back(entry.path());
}
ec.clear();
}
} else {
// Limited depth recursion
std::function<void(const fs::path&, int)> recurse = [&](const fs::path& dir_path, int current_depth) {
if (current_depth > max_depth) return;
for (const auto& entry : fs::directory_iterator(dir_path, options, ec)) {
if (ec) {
ec.clear();
continue;
}
if (entry.is_regular_file(ec) && !ec) {
out.push_back(entry.path());
} else if (entry.is_directory(ec) && !ec && current_depth < max_depth) {
recurse(entry.path(), current_depth + 1);
}
ec.clear();
}
};
recurse(p, 0);
}
} catch (const fs::filesystem_error&) {
// Handle any remaining filesystem errors silently
}
return out;
}
inline std::string readFile(const std::string &filename)
{
std::ifstream in(filename);
if (!in)
throw std::runtime_error("Could not open file");
std::ostringstream ss;
ss << in.rdbuf(); // dump entire buffer into string
return ss.str();
}
}