tmp
This commit is contained in:
parent
a68d77894b
commit
6d1c37db0a
5 changed files with 158 additions and 88 deletions
|
|
@ -1,5 +1,9 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(FileSystemEmulator)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC FileSystemEmulator.cpp FileSystemEmulator.hpp)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC .)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
static void f() {}
|
||||
|
|
@ -25,53 +25,72 @@
|
|||
// base node class has all the cache data. use it directly in the tree
|
||||
// dynamic links ? -> yet another cache variable in each node?
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Path.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <map>
|
||||
#include <filesystem>
|
||||
|
||||
typedef std::filesystem::path Path;
|
||||
typedef std::string Key;
|
||||
typedef std::map<Key, struct Node*> Tree;
|
||||
|
||||
struct Node {
|
||||
Key key;
|
||||
|
||||
Node* left = nullptr;
|
||||
Node* right = nullptr;
|
||||
Node* parent = nullptr;
|
||||
unsigned int height = 0;
|
||||
|
||||
unsigned int inLinks = 0;
|
||||
unsigned int outLinks = 0;
|
||||
|
||||
enum Type : unsigned int { NONE, DIRECTORY, FILE, LINK } type = NONE;
|
||||
};
|
||||
|
||||
struct File : Node {
|
||||
File() {
|
||||
type = FILE;
|
||||
class Node {
|
||||
public:
|
||||
Node() {
|
||||
type = NONE;
|
||||
}
|
||||
|
||||
virtual void log(std::stringstream& ss, const Key& key, int depth) {
|
||||
ss << "ss";
|
||||
}
|
||||
|
||||
virtual ~Node() = default;
|
||||
|
||||
protected:
|
||||
enum Type : unsigned int { NONE, DIRECTORY, FILE, LINK };
|
||||
Type type;
|
||||
};
|
||||
|
||||
struct Link : Node {
|
||||
Node* link = nullptr;
|
||||
bool hard = false;
|
||||
class File : public Node {
|
||||
public:
|
||||
File() {
|
||||
type = Type::FILE;
|
||||
}
|
||||
|
||||
void log(std::stringstream& ss, const Key& key, int depth) override {
|
||||
ss << std::setw(depth * 2) << key << "\n";
|
||||
}
|
||||
|
||||
~File() override = default;
|
||||
};
|
||||
|
||||
class Link : public Node {
|
||||
public:
|
||||
|
||||
Link() {
|
||||
type = LINK;
|
||||
}
|
||||
|
||||
void log(std::stringstream & ss, const Key& key, int depth) override {
|
||||
ss << std::setw(depth * 2) << "link [" << key << "] \n";
|
||||
}
|
||||
|
||||
~Link() override = default;
|
||||
|
||||
private:
|
||||
Node* link = nullptr;
|
||||
bool hard = false;
|
||||
};
|
||||
|
||||
struct Directory : Node {
|
||||
Node subNodes;
|
||||
|
||||
class Directory : public Node {
|
||||
public:
|
||||
Directory() {
|
||||
type = DIRECTORY;
|
||||
}
|
||||
|
||||
~Directory() override = default;
|
||||
|
||||
void detachNode(Node* node) {
|
||||
// TODO : remove util from avl tree
|
||||
|
|
@ -86,16 +105,16 @@ struct Directory : Node {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (node->type != DIRECTORY) {
|
||||
// if (node->type != DIRECTORY) {
|
||||
// TODO : update error status - given path is not a directory
|
||||
return false;
|
||||
}
|
||||
// return false;
|
||||
//}
|
||||
|
||||
if (!((Directory*) node)->insertUtil(newKey, newNode)) return false;
|
||||
|
||||
if (newNode->type == LINK) {
|
||||
// if (newNode->type == LINK) {
|
||||
// TODO : update all caches (due to the new link update)
|
||||
}
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -116,7 +135,7 @@ struct Directory : Node {
|
|||
}
|
||||
|
||||
const Key& key = {}; // path.getCurrentKey();
|
||||
node = findUtil(key, &subNodes);
|
||||
node = subNodes.find(key)->second;
|
||||
|
||||
if (!node) {
|
||||
return nullptr;
|
||||
|
|
@ -124,6 +143,7 @@ struct Directory : Node {
|
|||
|
||||
// TODO : dont allow cyclic links (with length one?)?
|
||||
while (true) {
|
||||
/*
|
||||
switch (node->type) {
|
||||
case Node::DIRECTORY:
|
||||
return ((Directory*)node)->findNode(path);
|
||||
|
|
@ -135,22 +155,19 @@ struct Directory : Node {
|
|||
default:
|
||||
return nullptr;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
Node* findUtil(const Key& key, Node* node) {
|
||||
Node* iter = node;
|
||||
while (true) {
|
||||
if (!iter) return nullptr;
|
||||
if (iter->key == key) return iter;
|
||||
if (key > iter->key) {
|
||||
iter = iter->left;
|
||||
} else {
|
||||
iter = iter->right;
|
||||
}
|
||||
void log(std::stringstream & ss, const Key& key, int depth) override {
|
||||
ss << std::setw(depth * 2) << key;
|
||||
for (auto & node : subNodes) {
|
||||
node.second->log(ss, node.first, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Tree subNodes;
|
||||
};
|
||||
|
||||
class FileSystem {
|
||||
|
|
@ -160,6 +177,7 @@ class FileSystem {
|
|||
public:
|
||||
FileSystem() {
|
||||
root = new Directory();
|
||||
initializeTransitions();
|
||||
}
|
||||
|
||||
~FileSystem() {
|
||||
|
|
@ -167,60 +185,27 @@ public:
|
|||
}
|
||||
|
||||
void makeDirectory(const Path& path) {
|
||||
Directory* parentDirectory = path.is_relative() ? currentDirectory : root;
|
||||
Directory* parentDirectory = path.isAbsolute() ? root : currentDirectory;
|
||||
auto newDirectory = new Directory();
|
||||
/*
|
||||
if (!parentDirectory->attachNode(path.parent_path(), path.filename(), newDirectory)) {
|
||||
delete newDirectory;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void changeCurrent(const char* directoryString) {
|
||||
auto path = Path(directoryString);
|
||||
auto node = path.is_relative() ? root->findNode(path) : currentDirectory->findNode(path);
|
||||
if (node->type != Node::DIRECTORY) {
|
||||
void changeCurrent(const Path& path) {
|
||||
auto node = path.isAbsolute() ? root->findNode(path) : currentDirectory->findNode(path);
|
||||
// if (node->type != Node::DIRECTORY) {
|
||||
// TODO : update error status - no such directory
|
||||
return;
|
||||
}
|
||||
// return;
|
||||
// }
|
||||
currentDirectory = (Directory*) node;
|
||||
}
|
||||
|
||||
void log() {
|
||||
std::stringstream ss;
|
||||
logNode(ss, root, 0);
|
||||
root->log(ss, "/", 0);
|
||||
std::cout << ss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
void logUtil(std::stringstream& ss, const Node* node, int depth) {
|
||||
if (!node) return;
|
||||
logUtil(ss, node->left, depth);
|
||||
logNode(ss, node, depth);
|
||||
logUtil(ss, node->right, depth);
|
||||
}
|
||||
|
||||
void logNode(std::stringstream& ss, const Node* node, int depth) {
|
||||
switch (node->type) {
|
||||
case Node::DIRECTORY:
|
||||
return logDirectory(ss, (Directory*) node, depth);
|
||||
case Node::FILE:
|
||||
return logFile(ss, (File*) node, depth);
|
||||
case Node::LINK:
|
||||
return logLink(ss, (Link*) node, depth);
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void logDirectory(std::stringstream& ss, const Directory* dir, int depth) {
|
||||
ss << std::setw(depth * 2) << dir->key;
|
||||
logUtil(ss, &dir->subNodes, depth + 1);
|
||||
}
|
||||
|
||||
void logFile(std::stringstream& ss, const File* file, int depth) {
|
||||
ss << std::setw(depth * 2) << file->key << "\n";
|
||||
}
|
||||
|
||||
void logLink(std::stringstream& ss, const Link* link, int depth) {
|
||||
ss << std::setw(depth * 2) << "link [" << link->key << "] \n";
|
||||
}
|
||||
};
|
||||
67
Path.hpp
Normal file
67
Path.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
std::vector<char> transitions;
|
||||
|
||||
void initializeTransitions() {
|
||||
transitions.resize(256);
|
||||
std::fill(transitions.begin(), transitions.end(), 1);
|
||||
for (char i = 'a'; i <= 'z'; i++) transitions[i] = i;
|
||||
for (char i = '0'; i <= '9'; i++) transitions[i] = i;
|
||||
for (char i = 'A'; i <= 'Z'; i++) transitions[i] = i + ('a' - 'A');
|
||||
transitions['/'] = '/';
|
||||
}
|
||||
|
||||
char getChar(char in) {
|
||||
return transitions[in];
|
||||
}
|
||||
|
||||
class Path {
|
||||
public:
|
||||
Path() = default;
|
||||
|
||||
Path(const char* path) {
|
||||
set(path);
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
return mIsValid;
|
||||
}
|
||||
|
||||
bool isAbsolute() const {
|
||||
return mAbsolute;
|
||||
}
|
||||
|
||||
int getDepth() const {
|
||||
return mDepth;
|
||||
}
|
||||
|
||||
void set(const std::string& path) {
|
||||
if (path.empty()) {
|
||||
mIsValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mIsValid = true;
|
||||
mPath = path;
|
||||
|
||||
mDepth = std::count(path.begin(), path.end(), '/') + 1;
|
||||
mDepth -= (mPath.back() == '/') + (path.front() == '/');
|
||||
|
||||
mAbsolute = path.front() == '/';
|
||||
|
||||
for (auto & character : mPath) {
|
||||
character = getChar(character);
|
||||
if (character == 1) mIsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mPath = "";
|
||||
int mDepth = 0;
|
||||
bool mAbsolute = false;
|
||||
bool mIsValid = false;
|
||||
};
|
||||
18
Tests.cpp
18
Tests.cpp
|
|
@ -1,9 +1,25 @@
|
|||
|
||||
#include "FileSystemEmulator.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
int main() {
|
||||
FileSystem fse;
|
||||
|
||||
fse.makeDirectory("/newDir");
|
||||
Path path;
|
||||
|
||||
path.set("/");
|
||||
path.set("/dir");
|
||||
path.set("/dir/");
|
||||
path.set("dir/");
|
||||
|
||||
path.set("");
|
||||
path.set("asd");
|
||||
path.set("asdASD");
|
||||
path.set("asdASD123");
|
||||
path.set("asdASD123");
|
||||
|
||||
fse.makeDirectory("/dir");
|
||||
fse.log();
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue