current commit
230531.11 · Moved headers inside a hypergrep namespace directory
#pragma once
#include <argparse/argparse.hpp>
#include <atomic>
#include <chrono>
#include <concurrentqueue/concurrentqueue.h>
#include <dirent.h>
#include <fcntl.h>
#include <filesystem>
#include <fmt/color.h>
#include <fmt/format.h>
#include <fstream>
#include <git2.h>
#include <hs/hs.h>
#include <hypergrep/compiler.hpp>
#include <hypergrep/constants.hpp>
#include <hypergrep/file_filter.hpp>
#include <hypergrep/file_search.hpp>
#include <hypergrep/git_index_search.hpp>
#include <hypergrep/is_binary.hpp>
#include <hypergrep/match_handler.hpp>
#include <hypergrep/search_options.hpp>
#include <hypergrep/size_to_bytes.hpp>
#include <limits>
#include <numeric>
#include <sys/mman.h>
#include <sys/stat.h>
#include <thread>
#include <unistd.h>
#include <vector>

class directory_search {
public:
  directory_search(std::string &pattern, const std::filesystem::path &path,
                   argparse::ArgumentParser &program);
  ~directory_search();
  void run(std::filesystem::path path);

private:
  bool process_file(std::string &&filename, hs_scratch_t *local_scratch,
                    char *buffer, std::string &lines);

  bool try_dequeue_and_process_path(moodycamel::ConsumerToken &ctok,
                                    hs_scratch_t *local_scratch, char *buffer,
                                    std::string &lines);

  void search_thread_function();

  void visit_directory_and_enqueue(moodycamel::ProducerToken &ptok,
                                   std::string directory,
                                   hs_scratch *local_file_filter_scratch);

private:
  std::filesystem::path search_path;

  // Directory traversal
  moodycamel::ConcurrentQueue<std::string> subdirectories;
  std::atomic<std::size_t> num_dirs_enqueued{0};

  moodycamel::ConcurrentQueue<std::string> queue;

  std::atomic<bool> running{true};
  std::atomic<std::size_t> num_files_enqueued{0};
  std::atomic<std::size_t> num_files_dequeued{0};

  hs_database_t *database = NULL;
  hs_scratch_t *scratch = NULL;
  hs_database_t *file_filter_database = NULL;
  hs_scratch_t *file_filter_scratch = NULL;
  // If the filter pattern starts with '!'
  // then negate the result of the filter
  bool negate_filter{false};

  search_options options;

  // Optimizations for large files
  struct large_file {
    std::string path;
    std::size_t size;
  };
  moodycamel::ConcurrentQueue<large_file> large_file_backlog;
  std::atomic<std::size_t> num_large_files_enqueued{0};

  // Optimizations for git repos
  moodycamel::ConcurrentQueue<std::string> git_repo_paths;
  std::atomic<std::size_t> num_git_repos_enqueued{0};
};