#include "../include/cache_files.hpp" #include #include "../include/information.hpp" #include namespace fs = std::filesystem; gemini::CacheFiles::CacheFiles(const std::filesystem::path &folder, const Information &infos) : information(infos) { if (!fs::is_directory(folder)) { spdlog::error("Path {} is not a folder", folder.string()); throw std::runtime_error("Stopped in cache files constructor, see log."); } std::size_t global_cache = 0; for (const auto &iterator : fs::directory_iterator(folder, fs::directory_options::follow_directory_symlink)) { // Each time it finds a file, it is going to load it in memory and check if infos.cache_size is reached in terms of size. if (!iterator.is_regular_file()) continue; const std::size_t file_size = [&]() -> std::size_t { std::ifstream in(iterator.path()); const std::size_t begin = in.tellg(); in.seekg(0, std::ios::end); return static_cast(in.tellg()) - begin; }(); global_cache += file_size; if (global_cache > infos.cache_size) break; // I want to have the filename and not the whole path to be stored (less characters, less memory used). const std::string filename = [&]() -> std::string { const auto path = iterator.path().string(); const std::size_t pos = path.rfind('/'); return iterator.path().string().substr(pos != std::string::npos ? pos + 1 : pos); }(); if (files.insert(filename.empty() ? iterator.path().string() : filename).second) spdlog::warn("File {} could not be registered", iterator.path().string()); std::ifstream file{ iterator.path() }; if (!content.emplace(filename.empty() ? iterator.path().string() : filename, std::string{ std::istreambuf_iterator(file), std::istreambuf_iterator() }).second) spdlog::warn("File {} could not be loaded in cache", iterator.path().string()); } }