tmp
This commit is contained in:
parent
2053bf474b
commit
31fa6e96bb
9 changed files with 166 additions and 58 deletions
|
|
@ -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})
|
||||
|
|
|
|||
26
app/main.cpp
Normal file
26
app/main.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include "Interpreter.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ struct Directory : public Node {
|
|||
Directory();
|
||||
|
||||
bool attachNode(const std::vector<Key>& directoryPath, const Key& newKey, Node* newNode);
|
||||
Node* findNode(const std::vector<Key>& path, ui32 currentDepth);
|
||||
Node* findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
|
||||
void detachNode(Node* node);
|
||||
|
||||
template<typename tFunctor>
|
||||
|
|
@ -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<bool>& indents) const;
|
||||
void indent(std::stringstream & ss, int depth, std::vector<bool>& indents) const;
|
||||
|
|
|
|||
24
inc/Interpreter.hpp
Normal file
24
inc/Interpreter.hpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "FileSystem.hpp"
|
||||
#include <map>
|
||||
|
||||
class Interpreter {
|
||||
struct Command {
|
||||
ui32 numArguments = 0;
|
||||
bool(*callback)(FileSystem&, const std::vector<std::string>&) = nullptr;
|
||||
};
|
||||
|
||||
public:
|
||||
Interpreter();
|
||||
|
||||
void interpret(const std::string& command);
|
||||
|
||||
private:
|
||||
static void reportError(const std::string& string);
|
||||
|
||||
private:
|
||||
std::map<std::string, Command> mCommands;
|
||||
FileSystem mFileSystem;
|
||||
std::string mError;
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "FileSystem.hpp"
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
static std::string gError;
|
||||
|
||||
void Node::updateTreeCache() {
|
||||
// TODO update cache
|
||||
|
|
@ -20,12 +23,12 @@ Directory::Directory() {
|
|||
bool Directory::attachNode(const std::vector<Key>& 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<Key>& 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<bool> 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<bool>& in
|
|||
}
|
||||
|
||||
void FileSystem::logDirectory(std::stringstream & ss, const Directory* node, int depth, std::vector<bool>& 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;
|
||||
}
|
||||
|
|
|
|||
60
src/Interpreter.cpp
Normal file
60
src/Interpreter.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include "Interpreter.hpp"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
void getWords(const std::string& in, std::vector<std::string>& 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<std::string>& args){
|
||||
return filesystem.changeCurrent(args[1]);
|
||||
}};
|
||||
|
||||
mCommands["md"] = { 1, [](FileSystem& filesystem, const std::vector<std::string>& 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<std::string> 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();
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ void initializeTransitions() {
|
|||
transitions['.'] = '.';
|
||||
}
|
||||
|
||||
Path::Path(const char* path) {
|
||||
Path::Path(const std::string& path) {
|
||||
set(path);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue