חזור לתיקייה: גליון 4

FileSystem

חיפוש בתיקיה
Ctrl K
לחץ כאן או הקש Ctrl K כדי לחפש בכל התיקיה

    FileSystem

    02340124

    מבוא לתכנות מערכות

    רשימות הרצאה לקריאה בשבת

    FileSystem

    הופק מתוך תקיית התואר של שקד

    uni-folder.vercel.app

    filesystem.cpp

    הערה (קובץ קוד)

    קובץ זה הוא קובץ קוד מסוג CPP.

    #include "FileSystem.h"
    
    #include "Utilities.h"
    #include "Action.h"
    #include "HelpAction.h"
    #include "HistoryAction.h"
    #include "SymbolicLink.h"
    
    #include <iostream>
    #include <memory>
    #include <stdexcept>
    
    FileSystem::FileSystem()
                : history(), root(std::make_unique<Directory>("/", nullptr)) {
    }
    
    std::unique_ptr<Action> FileSystem::handleHelp(const std::vector<std::string>& args) const {
        checkAmountOfArgs(HELP, args.size());
        return std::make_unique<HelpAction>();
    }
    
    std::unique_ptr<Action> FileSystem::handleCreate(const std::vector<std::string>& args) const {
        const std::string& type = (args.size() > 1) ? args[1] : "";
        checkAmountOfArgs(CREATE, args.size(), type);
    
        std::vector<std::string> pathVector = Utilities::split(args[2]);
        Directory& directory = getDirectoryFromPath(pathVector, Utilities::FileNotFoundMsg());
    
        const std::string& name = args[3];
        const std::vector<std::string>& vector = type == "symlink" ?
                                Utilities::split(args[4]) : std::vector<std::string>();
        WriteRequest request = {name, type, vector};
        return directory.CreateCreateAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleDelete(const std::vector<std::string>& args) const {
        checkAmountOfArgs(DELETE, args.size());
    
        std::vector<std::string> pathVector = Utilities::split(args[1]);
        Directory& directory = getDirectoryFromPath(pathVector, Utilities::TypeErrorMsg());
        const std::string& name = args[2];
        WriteRequest request = {name, "", std::vector<std::string>()};
        return directory.CreateDeleteAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleList(const std::vector<std::string>& args) const {
        checkAmountOfArgs(LIST, args.size());
    
        std::vector<std::string> pathVector = Utilities::split(args[1]);
        Directory& directory = getDirectoryFromPath(pathVector, Utilities::TypeErrorMsg());
        ReadRequest request = {"", true};
    
        return directory.CreateReadAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleRead(const std::vector<std::string>& args) const {
        checkAmountOfArgs(READ, args.size());
    
        std::vector<std::string> pathVector = Utilities::split(args[1] + "/" + args[2]);
        File& file = (*root)[pathVector];
        ReadRequest request = {"", true};
    
        return file.CreateReadAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleWrite(const std::vector<std::string>& args) const {
        checkAmountOfArgs(WRITE, args.size());
    
        std::vector<std::string> pathVector = Utilities::split(args[1] + "/" + args[2]);
        TextFile& file = getTextFileFromPath(pathVector);
    
        std::vector<std::string> line;
        line.push_back(Utilities::joinArgs(args.cbegin() + 3, args.cend()));
    
        WriteRequest request = {"", "", line};
        return file.CreateWriteAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleSearch(const std::vector<std::string>& args) const {
        checkAmountOfArgs(SEARCH, args.size());
    
        std::string path = args[1] + "/" + args[2];
        std::vector<std::string> pathVector = Utilities::split(path);
        File& file = (*root)[pathVector];
        std::vector<std::string> temp;
        std::string searchTerm = Utilities::joinArgs(args.cbegin() + 3, args.cend());
    
        SearchRequest request = {searchTerm, false, temp, path};
        return file.CreateSearchAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleImport(const std::vector<std::string>& args) const {
        checkAmountOfArgs(IMPORT, args.size());
    
        std::vector<std::string> pathVector = Utilities::split(args[2] + "/" + args[3]);
        TextFile& file = getTextFileFromPath(pathVector);
    
        std::ifstream importFile(args[1]);
        if (!importFile.good())
        {
            throw std::runtime_error(Utilities::HostFileErrorMsg());
        }
    
        std::vector<std::string> importedLines = Utilities::readLinesFromStream(importFile);
        WriteRequest request = {"", "", importedLines};
        return file.CreateWriteAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleExport(const std::vector<std::string>& args) const {
        checkAmountOfArgs(EXPORT, args.size());
    
        std::vector<std::string> pathVector = Utilities::split(args[1] + "/" + args[2]);
        TextFile& file = getTextFileFromPath(pathVector);
    
        ReadRequest request = {args[3], false};
        return file.CreateReadAction(request);
    }
    
    std::unique_ptr<Action> FileSystem::handleHistory(const std::vector<std::string>& args) const
    {
        checkAmountOfArgs(HISTORY, args.size());
        return std::make_unique<HistoryAction>(history);
    }
    
    void FileSystem::checkAmountOfArgs(ActionType action, unsigned int num, const std::string& type) {
        bool flag = false;
        switch (action) {
            case HELP:
            case HISTORY:
                flag = (num == 1);
                break;
    
            case DELETE:
            case READ:
                flag = (num == 3);
                break;
    
            case LIST:
                flag = (num == 2);
                break;
    
            case IMPORT:
            case EXPORT:
                flag = (num == 4);
                break;
    
            case SEARCH: // "the word can contain spaces"
            case WRITE:
                flag = (num >= 4);
                break;
    
            case CREATE:
                flag = (type == "symlink") ? (num == 5) : (num == 4);
                break;
    
            default:
                flag = false;
                break;
        }
    
        if (!flag) {
            throw std::runtime_error(Utilities::commandErrorMsg());
        }
    }
    
    Directory& FileSystem::getDirectoryFromPath(const std::vector<std::string>& pathVector,
        const std::string& errorMessage) const {
        try {
            return dynamic_cast<Directory&>((*root)[pathVector]);
        } catch (const std::bad_cast&) {
            throw std::runtime_error(errorMessage);
        }
    }
    
    TextFile &FileSystem::getTextFileFromPath(const std::vector<std::string> &pathVector) const
    {
        try {
            return dynamic_cast<TextFile&>((*root)[pathVector]);
        } catch (const std::bad_cast&) {
            try {
                return dynamic_cast<SymbolicLink&>((*root)[pathVector]).getFile();
            } catch (const std::bad_cast&) {
                throw std::runtime_error(Utilities::TypeErrorMsg());
            }
        }
    }
    
    FileSystem& FileSystem::getInstance() {
        static FileSystem instance;
        return instance;
    }
    
    void FileSystem::run() {
        std::string line;
        while (true) {
            Utilities::printPrompt();
            if (!std::getline(std::cin, line)) break;
    
            auto args = Utilities::parseCommand(line);
            if (args.empty()) continue;
    
            const std::string& cmd = args[0];
    
            try {
                std::unique_ptr<Action> action;
    
                if (cmd == "exit") {
                    break;
                } else if (cmd == "help") {
                    action = handleHelp(args);
                } else if (cmd == "create") {
                    action = handleCreate(args);
                } else if (cmd == "delete") {
                    action = handleDelete(args);
                } else if (cmd == "list") {
                    action = handleList(args);
                } else if (cmd == "read") {
                    action = handleRead(args);
                } else if (cmd == "write") {
                    action = handleWrite(args);
                } else if (cmd == "search") {
                    action = handleSearch(args);
                } else if (cmd == "history") {
                    action = handleHistory(args);
                } else if (cmd == "import") {
                    action = handleImport(args);
                } else if (cmd == "export") {
                    action = handleExport(args);
                } else {
                    throw std::runtime_error(Utilities::commandErrorMsg());
                }
    
                if (action) {
                    action->execute();
                    Utilities::printActionExecuted(cmd);
                    if (cmd != "help" && cmd != "history") {
                        history.push_back(cmd);
                    }
                }
            } catch (const std::exception& e) {
                Utilities::printError(e.what());
            }
        }
    }