Commit 6c9aa733 authored by Pádraig Ó Conbhuí's avatar Pádraig Ó Conbhuí
Browse files

Implemented find_includes.

parent f0f5262d
#ifndef MEGADEP_CONFIG_HPP
#define MEGADEP_CONFIG_HPP
#include <cstddef>
namespace megadep {
constexpr size_t filename_max = 4096;
} // namespace megadep
#endif // MEGADEP_CONFIG_HPP
#include <megadep/filesystem.hpp>
#include <megadep/common_types.hpp>
#include <megadep/config.hpp>
#include <megadep/filesystem.hpp>
#include <array>
#include <cerrno>
#include <cstring>
#include <vector>
#include <cstdio>
#include <dirent.h>
namespace megadep {
......@@ -10,10 +15,7 @@ namespace megadep {
std::vector<FileName> list_files(const DirectoryName &directory) {
std::vector<FileName> file_names;
DIR *dir_ptr;
dirent *entity_ptr;
dir_ptr = opendir(directory.c_str());
DIR *dir_ptr = opendir(directory.c_str());
// Directory is a file, return the directory name
if (dir_ptr == nullptr) {
......@@ -24,6 +26,7 @@ std::vector<FileName> list_files(const DirectoryName &directory) {
return {};
}
dirent *entity_ptr;
while ((entity_ptr = readdir(dir_ptr)) != nullptr) {
const char *entity_name = static_cast<const char *>(entity_ptr->d_name);
......@@ -48,9 +51,67 @@ std::vector<FileName> list_files(const DirectoryName &directory) {
return file_names;
}
// Wrap fopen and fclose in an RAII class.
class raii_fopen {
FILE *m_file_ptr = nullptr;
std::vector<std::string> read_includes(const std::string& file_name) {
return {};
public:
FILE *file_ptr() { return m_file_ptr; }
explicit raii_fopen(const char *file_name)
: m_file_ptr(fopen(file_name, "re")) {}
~raii_fopen() {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
fclose(m_file_ptr);
}
// Disable copy / move
raii_fopen(const raii_fopen &) = delete;
raii_fopen &operator=(const raii_fopen &) = delete;
raii_fopen(raii_fopen &&) = delete;
raii_fopen &operator=(raii_fopen &&) = delete;
};
std::vector<std::string> read_includes(const std::string &file_name) {
std::vector<std::string> includes;
raii_fopen file{file_name.c_str()};
auto file_ptr = file.file_ptr();
std::array<char, filename_max> buffer{};
while (fgets(buffer.data(), buffer.size(), file_ptr) != nullptr) {
std::string_view line{buffer.data(), strlen(buffer.data())};
constexpr std::string_view hash_include{"#include", 8};
if (line.compare(0, hash_include.size(), hash_include) != 0) {
continue;
}
// Strip '#include' and any surrounding spaces.
const size_t include_start = line.find_first_not_of(' ', 8);
line.remove_prefix(include_start);
const size_t include_end = ([&] {
switch (line[0]) {
case '<':
return line.find_last_not_of('>', std::string_view::npos);
case '\'':
return line.find_last_not_of('\'', std::string_view::npos);
case '"':
return line.find_last_not_of('"', std::string_view::npos);
}
return size_t(0);
}());
line.remove_suffix(line.size() - include_end);
// Add found include to includes.
includes.emplace_back(line);
}
return includes;
}
} // namespace megadep
......@@ -6,11 +6,13 @@
#include <string>
#include <vector>
#include <cstdio>
namespace megadep {
std::vector<FileName> list_files(const DirectoryName &directory);
std::vector<std::string> read_includes(const std::string& file_name);
std::vector<std::string> read_includes(const std::string &file_name);
} // namespace megadep
......
#include <iostream> // DELETE ME
#include <megadep/filesystem.hpp>
#include <megadep/config.hpp>
#include <catch2/catch.hpp>
#include <algorithm>
#include <array>
#include <stdio.h>
#include <cstdio>
#include <string>
#include <vector>
......@@ -22,19 +23,26 @@ TEST_CASE("megadep::list_files recursively lists files in a directory",
auto files = megadep::list_files("src");
// Make sure we got something!
REQUIRE(files.size() > 0);
REQUIRE(!files.empty());
// Run system find and get list of files
// Silence security warnings about popen, because this is just a test.
// NOLINTNEXTLINE(cert-env33-c)
FILE *find_fd = popen("find src -type f", "r");
std::vector<std::string> find_files;
std::array<char, 1024> line_buf;
while (fgets(line_buf.data(), line_buf.size(), find_fd) != NULL) {
std::string line = line_buf.data();
line.resize(line.size() - 1); // strip newline
find_files.push_back(line);
std::array<char, megadep::filename_max> line_buf{};
while (fgets(line_buf.data(), line_buf.size(), find_fd) != nullptr) {
std::string_view line{line_buf.data(), strlen(line_buf.data())};
line.remove_suffix(1); // strip newline
find_files.emplace_back(line);
}
pclose(find_fd);
// Also make sure we got something with find!
REQUIRE(!find_files.empty());
// Sort both lists so we can compare like-for-like
std::sort(files.begin(), files.end());
std::sort(find_files.begin(), find_files.end());
......@@ -62,15 +70,14 @@ TEST_CASE("megadep::read_includes reads all the #include statements",
auto includes = megadep::read_includes(this_file);
// includes copy/pasted from the top of this file!!
std::vector<std::string> expected_includes = {
"<megadep/filesystem.hpp>",
"<catch2/catch.hpp>",
"<algorithm>",
"<array>",
"<stdio.h>",
"<string>",
"<vector>"
};
std::vector<std::string> expected_includes = {"<megadep/filesystem.hpp>",
"<megadep/config.hpp>",
"<catch2/catch.hpp>",
"<algorithm>",
"<array>",
"<cstdio>",
"<string>",
"<vector>"};
std::sort(includes.begin(), includes.end());
std::sort(expected_includes.begin(), expected_includes.end());
......@@ -78,7 +85,7 @@ TEST_CASE("megadep::read_includes reads all the #include statements",
// Compare includes and expected_includes
REQUIRE(includes.size() == expected_includes.size());
for(size_t i=0; i<includes.size(); i++) {
for (size_t i = 0; i < includes.size(); i++) {
REQUIRE(includes[i] == expected_includes[i]);
}
}
......@@ -4,5 +4,6 @@ add_library(
)
target_link_libraries(catch2_runner PUBLIC Catch2::Catch2)
target_compile_features(catch2_runner PUBLIC cxx_std_17)
add_library(medagep::catch2_runner ALIAS catch2_runner)
......@@ -94,6 +94,9 @@ then
fi
fi
# Add clang-tidy dir to PATH for clang
export PATH=$(dirname "${CLANG_TIDY_EXECUTABLE}"):${PATH}
echo_verbose() {
if [[ -n "${VERBOSE}" ]]
then
......
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