Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
2.3 kB
4
Indexable
Never
std::optional<FSNodes> Folder::get_contents_recursively(const std::atomic<bool>& stop_token /= false/) const
{
	FSNodes nodes;

	FSNodes local_folders;

	FSNodes local_files;

	auto formatPath = [](std::wstring_view file_name, std::wstring directory) -> std::wstring
	{
		if (directory.back() != '\\') // \ 
			directory.append(1, '\\');
		directory.append(file_name);

		return directory;
	};

	WIN32_FIND_DATA findFileData;

	std::queue<std::wstring> tasks_pool; 

	tasks_pool.push(m_path_);

	while (!tasks_pool.empty() and !stop_token)
	{
		HANDLE hFind = FindFirstFile(std::wstring(tasks_pool.front().data() + std::wstring(L"\\*")).c_str(), &findFileData);

		if (hFind != INVALID_HANDLE_VALUE)
		{
			do
			{	
				if (std::wstring fileName = findFileData.cFileName; fileName != L"." && fileName != L".." && fileName != L"")
				{
					std::wstring formattedPath = formatPath(fileName, tasks_pool.front());

					if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
					{
						tasks_pool.emplace(formattedPath);

						local_folders.emplace_back(std::make_unique<Folder>(std::move(formattedPath)));
						continue;
					}
					local_files.emplace_back(std::make_unique<File>(std::move(formattedPath)));
				}
			} while (FindNextFile(hFind, &findFileData));
		}
		FindClose(hFind);
		tasks_pool.pop();
	}	

	auto fix_path =  [&](auto& elem) { // just to erase the leftover *
		auto& acquired_path = elem->get_modifiable_path();
		std::erase(acquired_path, L'*');
	};

	auto visit_vector = [&](auto& variant, auto& vector)
	{
		std::visit([&](auto policy){
			std::for_each(policy, vector.begin(), vector.end(), fix_path);
		}, variant);
	};

	bool high_elem_count = (local_folders.size() + local_files.size()) > 100'000;
	
	std::variant<std::execution::sequenced_policy, std::execution::parallel_policy> exec_policy;

	if (high_elem_count)
		exec_policy = std::execution::par;
	else
		exec_policy = std::execution::seq;
	
	visit_vector(exec_policy, local_folders);
	visit_vector(exec_policy, local_files);

	nodes.reserve(local_files.size() + local_folders.size());
	nodes.insert(nodes.end(), std::make_move_iterator(local_folders.begin()), std::make_move_iterator(local_folders.end()));
	nodes.insert(nodes.end(), std::make_move_iterator(local_files.begin()), std::make_move_iterator(local_files.end()));
	
	return nodes;
}