diff --git a/tree_structurer/cpp/bindings.cpp b/tree_structurer/cpp/bindings.cpp new file mode 100644 index 0000000..6aa031a --- /dev/null +++ b/tree_structurer/cpp/bindings.cpp @@ -0,0 +1,72 @@ +#define PY_SSIZE_T_CLEAN +#include +#include "tree_structurer.hpp" + +static PyObject* TreeStructurerError; +static TreeStructurer* g_tree_structurer = nullptr; + +static PyObject* create_tree_structurer(PyObject* self, PyObject* args) { + if (g_tree_structurer != nullptr) { + delete g_tree_structurer; + } + g_tree_structurer = new TreeStructurer(); + Py_RETURN_NONE; +} + +static PyObject* get_structure(PyObject* self, PyObject* args) { + const char* path = nullptr; + if (!PyArg_ParseTuple(args, "|s", &path)) { + return NULL; + } + + if (g_tree_structurer == nullptr) { + PyErr_SetString(TreeStructurerError, "TreeStructurer not initialized"); + return NULL; + } + + try { + std::string path_str = path ? path : ""; + std::vector structure = g_tree_structurer->get_directory_structure(path_str); + PyObject* list = PyList_New(structure.size()); + for (size_t i = 0; i < structure.size(); i++) { + PyList_SET_ITEM(list, i, PyUnicode_FromString(structure[i].c_str())); + } + return list; + } catch (const std::exception& e) { + PyErr_SetString(TreeStructurerError, e.what()); + return NULL; + } +} + +static PyMethodDef TreeStructurerMethods[] = { + {"create_tree_structurer", create_tree_structurer, METH_NOARGS, + "Create a new TreeStructurer instance"}, + {"get_structure", get_structure, METH_VARARGS, + "Get the directory structure for the given path"}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef tree_structurer_module = { + PyModuleDef_HEAD_INIT, + "_tree_structurer", // Changed module name to match Python import + "Module for analyzing directory structures", + -1, + TreeStructurerMethods +}; + +PyMODINIT_FUNC PyInit__tree_structurer(void) { // Changed function name to match module name + PyObject* m = PyModule_Create(&tree_structurer_module); + if (m == NULL) + return NULL; + + TreeStructurerError = PyErr_NewException("tree_structurer.error", NULL, NULL); + Py_XINCREF(TreeStructurerError); + if (PyModule_AddObject(m, "error", TreeStructurerError) < 0) { + Py_XDECREF(TreeStructurerError); + Py_CLEAR(TreeStructurerError); + Py_DECREF(m); + return NULL; + } + + return m; +} \ No newline at end of file diff --git a/tree_structurer/cpp/tree_structurer.cpp b/tree_structurer/cpp/tree_structurer.cpp new file mode 100644 index 0000000..219455f --- /dev/null +++ b/tree_structurer/cpp/tree_structurer.cpp @@ -0,0 +1,60 @@ +#include "tree_structurer.hpp" +#include +#include + +namespace fs = std::filesystem; + +bool TreeStructurer::should_ignore_dir(const std::string& dirname) { + return dirname[0] == '.' || + dirname.find("build") != std::string::npos || + dirname == "venv" || + dirname == "myenv"; +} + +bool TreeStructurer::should_ignore_file(const std::string& filename) { + return filename[0] == '.' || + filename.find("build") != std::string::npos; +} + +std::string TreeStructurer::create_indent(int level) { + return std::string(4 * level, ' '); +} + +std::string TreeStructurer::get_relative_path(const fs::path& path, const fs::path& base) { + const fs::path rel = fs::relative(path, base); + return rel.string(); +} + +std::vector TreeStructurer::get_directory_structure(const std::string& startpath) { + std::vector result; + fs::path start = startpath.empty() ? fs::current_path() : fs::path(startpath); + + try { + std::vector paths; + for(const auto& entry : fs::recursive_directory_iterator(start)) { + paths.push_back(entry.path()); + } + + // Sort paths for consistent output + std::sort(paths.begin(), paths.end()); + + for(const auto& path : paths) { + std::string rel_path = get_relative_path(path, start); + int level = std::count(rel_path.begin(), rel_path.end(), fs::path::preferred_separator); + + if(fs::is_directory(path)) { + if(!should_ignore_dir(path.filename().string())) { + result.push_back(create_indent(level) + path.filename().string() + "/"); + } + } else { + if(!should_ignore_file(path.filename().string())) { + result.push_back(create_indent(level) + path.filename().string()); + } + } + } + } catch (const fs::filesystem_error& e) { + throw std::runtime_error("Failed to access directory: " + std::string(e.what())); + } + + return result; +} \ No newline at end of file diff --git a/tree_structurer/cpp/tree_structurer.hpp b/tree_structurer/cpp/tree_structurer.hpp new file mode 100644 index 0000000..102bf26 --- /dev/null +++ b/tree_structurer/cpp/tree_structurer.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include +#include + +class TreeStructurer { +public: + TreeStructurer() = default; + std::vector get_directory_structure(const std::string& startpath = std::filesystem::current_path().string()); + +private: + bool should_ignore_dir(const std::string& dirname); + bool should_ignore_file(const std::string& filename); + std::string create_indent(int level); + std::string get_relative_path(const std::filesystem::path& path, const std::filesystem::path& base); +}; \ No newline at end of file