From 31fa6e96bb35f23491cc21abc1980ed22361b975 Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Wed, 27 Mar 2024 17:06:46 +0300 Subject: [PATCH] tmp --- CMakeLists.txt | 9 ++++--- app/main.cpp | 26 ++++++++++++++++++++ inc/FileSystem.hpp | 8 +++--- inc/Interpreter.hpp | 24 ++++++++++++++++++ inc/Path.hpp | 2 +- src/FileSystem.cpp | 50 +++++++++++++++++++++++++------------ src/Interpreter.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++++ src/Path.cpp | 2 +- test/Tests.cpp | 43 +++++++------------------------- 9 files changed, 166 insertions(+), 58 deletions(-) create mode 100644 app/main.cpp create mode 100644 inc/Interpreter.hpp create mode 100644 src/Interpreter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ccf471..4d348db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,11 +4,14 @@ project(FileSystemEmulator) set(CMAKE_CXX_STANDARD 20) -file(GLOB SOURCES "./src/*.cpp") -file(GLOB HEADERS "./inc/*.hpp") +file(GLOB SOURCES "src/*.cpp") +file(GLOB HEADERS "inc/*.hpp") add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) -target_include_directories(${PROJECT_NAME} PUBLIC ./inc/) +target_include_directories(${PROJECT_NAME} PUBLIC inc/) + +add_executable(fse "app/main.cpp") +target_link_libraries(fse ${PROJECT_NAME}) file(GLOB TEST_SOURCES "./test/*.cpp") add_executable(Test${PROJECT_NAME} ${TEST_SOURCES}) diff --git a/app/main.cpp b/app/main.cpp new file mode 100644 index 0000000..519aae5 --- /dev/null +++ b/app/main.cpp @@ -0,0 +1,26 @@ +#include "Interpreter.hpp" + +#include +#include + +int main() { + Interpreter interpreter; + std::string line; + + std::cout << "File System emulator.\n"; + + while (true) { + std::cout << ">> "; + std::getline(std::cin, line); + + if (line == "stop") { + break; + } + + // Process the line here + // + interpreter.interpret(line); + } + + return 0; +} \ No newline at end of file diff --git a/inc/FileSystem.hpp b/inc/FileSystem.hpp index c9dfec2..b859600 100644 --- a/inc/FileSystem.hpp +++ b/inc/FileSystem.hpp @@ -40,7 +40,7 @@ struct Directory : public Node { Directory(); bool attachNode(const std::vector& directoryPath, const Key& newKey, Node* newNode); - Node* findNode(const std::vector& path, ui32 currentDepth); + Node* findNode(const std::vector& path, ui32 currentDepth = 0); void detachNode(Node* node); template @@ -79,10 +79,12 @@ public: FileSystem(); ~FileSystem(); - void makeDirectory(const Path& path); - void changeCurrent(const Path& path); + bool makeDirectory(const Path& path); + bool changeCurrent(const Path& path); void log() const; + const std::string& getLastError(); + private: void logNode(std::stringstream& ss, const Node* node, int depth, std::vector& indents) const; void indent(std::stringstream & ss, int depth, std::vector& indents) const; diff --git a/inc/Interpreter.hpp b/inc/Interpreter.hpp new file mode 100644 index 0000000..4108b3b --- /dev/null +++ b/inc/Interpreter.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "FileSystem.hpp" +#include + +class Interpreter { + struct Command { + ui32 numArguments = 0; + bool(*callback)(FileSystem&, const std::vector&) = nullptr; + }; + +public: + Interpreter(); + + void interpret(const std::string& command); + +private: + static void reportError(const std::string& string); + +private: + std::map mCommands; + FileSystem mFileSystem; + std::string mError; +}; \ No newline at end of file diff --git a/inc/Path.hpp b/inc/Path.hpp index f0085e0..9f1a5e8 100644 --- a/inc/Path.hpp +++ b/inc/Path.hpp @@ -9,7 +9,7 @@ void initializeTransitions(); class Path { public: Path() = default; - Path(const char* path); + Path(const std::string& path); void set(const std::string& path); const std::string& operator[](int idx) const; diff --git a/src/FileSystem.cpp b/src/FileSystem.cpp index ddf8ea7..4bc85a0 100644 --- a/src/FileSystem.cpp +++ b/src/FileSystem.cpp @@ -1,5 +1,8 @@ #include "FileSystem.hpp" #include +#include + +static std::string gError; void Node::updateTreeCache() { // TODO update cache @@ -20,12 +23,12 @@ Directory::Directory() { bool Directory::attachNode(const std::vector& directoryPath, const Key& newKey, Node* newNode) { Node* node = findNode(directoryPath, 0); if (!node) { - // TODO : update error status - invalid path + gError = "Invalid path"; return false; } if (node->type != DIRECTORY) { - // TODO : update error status - given path is not a directory + gError = "given path is not a directory"; return false; } @@ -34,7 +37,7 @@ bool Directory::attachNode(const std::vector& directoryPath, const Key& new Node* existingNode = directory->treeSearch(newKey); if (existingNode) { if (existingNode->type == newNode->type) return false; // exit silently - // TODO : report error cant add node + gError = "Cant add node"; return false; } @@ -233,7 +236,7 @@ void Directory::getMaxDepthUtil(ui32 depth, ui32& maxDepth) const { ui32 Directory::getMaxDepth() const { ui32 maxDepth = 0; - getMaxDepthUtil(0, maxDepth); + getMaxDepthUtil(1, maxDepth); return maxDepth; } @@ -249,31 +252,41 @@ FileSystem::~FileSystem() { delete root; } -void FileSystem::makeDirectory(const Path& path) { +bool FileSystem::makeDirectory(const Path& path) { if (path.getDepth() < 1 || path.isInvalid()) { - // TODO : update error - invalid path - return; + gError = "Invalid path"; + return false; } Directory* parentDirectory = path.isAbsolute() ? root : currentDirectory; - auto newDirectory = new Directory(); - if (!parentDirectory->attachNode(path.getParentChain(), path.getFilename(), newDirectory)) { - delete newDirectory; + + auto existingNode = parentDirectory->findNode(path.getChain()); + if (existingNode) { + if (existingNode->type == Node::DIRECTORY) return true; + gError = "Cant create directory, such node exists"; + return false; } + + auto newDirectory = new Directory(); + assert(parentDirectory->attachNode(path.getParentChain(), path.getFilename(), newDirectory)); + + return true; } -void FileSystem::changeCurrent(const Path& path) { +bool FileSystem::changeCurrent(const Path& path) { if (path.isInvalid()) { - // TODO : update error - invalid path - return; + gError = "Invalid path"; + return false; } auto node = path.isAbsolute() ? root->findNode(path.getChain(), 0) : currentDirectory->findNode(path.getChain(), 0); if (node->type != Node::DIRECTORY) { - // TODO : update error status - no such directory - return; + gError = "No such directory"; + return false; } + currentDirectory = (Directory*) node; + return true; } void FileSystem::log() const { @@ -281,7 +294,7 @@ void FileSystem::log() const { std::vector indents; indents.resize(root->getMaxDepth()); logNode(ss, root, 0, indents); - std::cout << ss.str(); + std::cout << ss.str() << "\n"; } @@ -305,6 +318,7 @@ void FileSystem::indent(std::stringstream & ss, int depth, std::vector& in } void FileSystem::logDirectory(std::stringstream & ss, const Directory* node, int depth, std::vector& indents) const { + ss << (node == currentDirectory ? "* " : " "); indent(ss, depth, indents); ss << node->key << "\n"; indents[depth] = true; @@ -325,3 +339,7 @@ void FileSystem::logLink(std::stringstream & ss, const Link* node, int depth, st indent(ss, depth, indents); ss << "link [" << node->key << "] \n"; } + +const std::string& FileSystem::getLastError() { + return gError; +} diff --git a/src/Interpreter.cpp b/src/Interpreter.cpp new file mode 100644 index 0000000..02b6fb9 --- /dev/null +++ b/src/Interpreter.cpp @@ -0,0 +1,60 @@ +#include "Interpreter.hpp" +#include +#include +#include + +void getWords(const std::string& in, std::vector& out) { + std::stringstream ss(in); + std::string word; + while (ss >> word) out.push_back(word); +} + +Interpreter::Interpreter() { + mCommands["cd"] = { 1, [](FileSystem& filesystem, const std::vector& args){ + return filesystem.changeCurrent(args[1]); + }}; + + mCommands["md"] = { 1, [](FileSystem& filesystem, const std::vector& args){ + return filesystem.makeDirectory(args[1]); + }}; +} + +void Interpreter::reportError(const std::string& description) { + std::cout << "ERROR : " << description << std::endl; +} + +void Interpreter::interpret(const std::string& command) { + std::cout << "\"" << command << "\"\n"; + + std::vector words; + getWords(command, words); + + if (words.empty()) { + reportError("Empty command"); + return; + } + + std::string& commandName = words.front(); + std::transform(commandName.begin(), commandName.end(), commandName.begin(), [](unsigned char c) { return std::tolower(c); }); + + auto iter = mCommands.find(commandName); + + if (iter == mCommands.end()) { + reportError("Command not found"); + return; + } + + if (iter->second.numArguments != words.size() - 1) { + reportError("invalid number of arguments given"); + return; + } + + bool success = iter->second.callback(mFileSystem, words); + + if (!success) { + reportError(mFileSystem.getLastError()); + return; + } + + mFileSystem.log(); +} \ No newline at end of file diff --git a/src/Path.cpp b/src/Path.cpp index c2f0829..0edaec2 100644 --- a/src/Path.cpp +++ b/src/Path.cpp @@ -13,7 +13,7 @@ void initializeTransitions() { transitions['.'] = '.'; } -Path::Path(const char* path) { +Path::Path(const std::string& path) { set(path); } diff --git a/test/Tests.cpp b/test/Tests.cpp index f3dca9a..a5a29a1 100644 --- a/test/Tests.cpp +++ b/test/Tests.cpp @@ -1,42 +1,17 @@ -#include "FileSystem.hpp" +#include "Interpreter.hpp" int main() { - FileSystem fse; + Interpreter interpreter; - fse.makeDirectory("/a"); - fse.makeDirectory("/a/b"); - fse.makeDirectory("/a/b/k"); - fse.makeDirectory("/a/c"); - fse.makeDirectory("/a/c/k"); + interpreter.interpret(""); + interpreter.interpret("m"); + interpreter.interpret("mD a"); + interpreter.interpret("mD /"); + interpreter.interpret("MD /A123"); + interpreter.interpret("cd /A123"); + interpreter.interpret("md asd"); - fse.makeDirectory("/d"); - fse.makeDirectory("/d/b"); - fse.makeDirectory("/d/b/k"); - fse.makeDirectory("/d/c"); - fse.makeDirectory("/d/c/k"); - - fse.makeDirectory("d"); - - fse.changeCurrent("/d/c/k"); - - fse.makeDirectory("/a"); - fse.makeDirectory("/a/b"); - fse.makeDirectory("/a/b/k"); - fse.makeDirectory("/a/c"); - fse.makeDirectory("/a/c/k"); - - fse.makeDirectory("ggad"); - fse.makeDirectory("gad"); - fse.makeDirectory("rwed"); - fse.makeDirectory("e"); - fse.makeDirectory("d"); - fse.makeDirectory("d/b"); - fse.makeDirectory("d/b/k"); - fse.makeDirectory("d/c"); - fse.makeDirectory("d/c/k"); - - fse.log(); return 0; } \ No newline at end of file