В файловой системе памяти в C ++ - PullRequest
0 голосов
/ 16 марта 2020

Я реализовал файловую систему в памяти на c ++, которая должна поддерживать команды basi c Linux, такие как cd, mkdir, mkfile ...

Мое решение дано ниже, но так как я младший разработчик, меня интересует, как это будет реализовано с точки зрения старшего разработчика. Обзор кода также очень приветствуется.

#include <iostream>
#include <chrono>
#include <ctime>

#include <vector>
#include <algorithm>
#include <memory>
#include <fstream>
#include <sstream>

class Directory;

enum class EntryType
{
    FILE,
    DIRECTORY,
    ANY_TYPE
};

class Entry {
private:
    const std::string m_name;
    const std::time_t m_created;
    const EntryType   m_entryType;

    Directory *m_parentDirectory;

protected:
    Entry(const std::string &name, EntryType entryType, Directory *parentDirectory) : m_name {name},
                                                                 m_created {std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())},
                                                                 m_entryType {entryType},
                                                                 m_parentDirectory {parentDirectory}
    {
    }

    virtual ~Entry()
    {
    }

public:
    const std::string& getName() const {return m_name;}
    const std::time_t& getTimeCreated() const {return m_created;}
    const EntryType& getEntryType() const {return m_entryType;}

    Directory* getParentDirectory() {return m_parentDirectory;}
};

class File : public Entry {
public:
    File(const std::string &name, Directory *parentDirectory) : Entry(name, EntryType::FILE, parentDirectory)
    {
    }
};

class Directory : public Entry {
private:
    std::vector<std::shared_ptr<Entry>> entries;

public:
    Directory(const std::string &name, Directory *parentDirectory) : Entry(name, EntryType::DIRECTORY, parentDirectory)
    {
    }

    ~Directory()
    {
    }

private:
    void list(EntryType type)
    {
        for (auto &entry : entries) {
            if (entry->getEntryType() == type)
                std::cout << getCreatedTime(entry.get()) << "\t\t" << entry->getName() << "\n";
        }
    }

    int countEntries(EntryType type)
    {
        auto count {static_cast<int>(std::count_if(entries.begin(), entries.end(), [&type](std::shared_ptr<Entry> entry){
                                            return entry->getEntryType() == type;
                                        }))};

        return count;
    }

    bool checkEntry(const std::string &name)
    {
        auto findEntry {std::find_if(entries.begin(), entries.end(), [&name](std::shared_ptr<Entry> entry){
                return entry->getName() == name;
            })};

        if (findEntry != entries.end())
            return true;

        return false;
    }

    const std::string getCreatedTime (Entry *entry) const
    {
        std::string timeCreated {std::ctime(&entry->getTimeCreated())};
        timeCreated[timeCreated.length() - 1] = '\0';

        return timeCreated;
    }

public:
    void listEntries()
    {
        std::cout << getCreatedTime(this) << "\t\t" << ".\n";

        int numDir {1};

        if (this->getParentDirectory() != nullptr) {
            std::cout << getCreatedTime(this->getParentDirectory()) << "\t\t" << "..\n";
            ++numDir;
        }

        list(EntryType::DIRECTORY);
        list(EntryType::FILE);

        std::cout << "\n";

        std::cout << countEntries(EntryType::DIRECTORY) + numDir << "\t\t" << "Dir(s)\n";
        std::cout << countEntries(EntryType::FILE) << "\t\t" << "File(s)\n";

        std::cout << "\n";
        std::cout << "--------------------------------------------------\n";
    }

    void makeDirectory(const std::string &name)
    {
        if (checkEntry(name))
            return;

        entries.push_back(std::make_shared<Directory>(name, this));
    }

    void makeFile(const std::string &name)
    {
        if (checkEntry(name))
            return;

        entries.push_back(std::make_shared<File>(name, this));
    }

    Directory* changeDirectory(const std::string &name)
    {
        if (name == ".") {
            return this;
        } else if (name == "..") {
            if (this->getParentDirectory() == nullptr) {
                return this;
            } else
                return this->getParentDirectory();
        }

        for (auto &entry : entries) {
            if (entry->getEntryType() == EntryType::DIRECTORY && entry->getName() == name)
                return static_cast<Directory *>(entry.get());
        }

        std::cout << "Directory: " << name << " does not exist\n";
        return this;
    }

    void deleteEntry(const std::string &name, EntryType type)
    {
        auto findEntry {std::find_if(entries.begin(), entries.end(), [&name](std::shared_ptr<Entry> entry){
                return entry->getName() == name;
            })};

        if (findEntry != entries.end()) {
            if (type == EntryType::ANY_TYPE || type == findEntry->get()->getEntryType()) {
                entries.erase(findEntry);
                return;
            }
        }
    }
};



class FileSystem {
private:
    Directory m_root;
    Directory *m_currentDirectory;

public:
    FileSystem() : m_root(Directory {".", nullptr})
    {
        m_currentDirectory = &m_root;
    }

    ~FileSystem()
    {
    }

private:
    void ls() const
    {
        m_currentDirectory->listEntries();
    }

    void mkdir(const std::string &name) const
    {
        m_currentDirectory->makeDirectory(name);
    }

    void mkfile(const std::string &name) const
    {
        m_currentDirectory->makeFile(name);
    }

    void dir() const
    {
        ls();
    }

    void cd(const std::string &name)
    {
        m_currentDirectory = m_currentDirectory->changeDirectory(name);
    }

    void del(const std::string &name, EntryType type = EntryType::ANY_TYPE) const
    {
        m_currentDirectory->deleteEntry(name, type);
    }

    void rmdir(const std::string &name) const
    {
        del(name, EntryType::DIRECTORY);
    }

    void processCommand(const std::string &command, const std::string &option)
    {
        if (command == "ls")
            return ls();
        else if (command == "dir")
            return dir();
        else if (command == "mkdir")
            return mkdir(option);
        else if (command == "mkfile")
            return mkfile(option);
        else if (command == "cd")
            return cd(option);
        else if (command == "rmdir")
            return rmdir(option);
        else if (command == "del")
            return del(option);
    }

public:
    void readInput(const std::string &fileName)
    {
        std::ifstream infile {fileName};

        std::string line;
        while (std::getline(infile, line)) {
            std::istringstream iss(line);

            std::string command;
            std::string option;

            iss >> command;
            iss >> option;

            std::cout << command << " " << option << "\n";
            processCommand(command, option);
        }
    }
};




int main() {
    FileSystem filesystem;

    filesystem.readInput("path to the input file");

    return 0;
}
...