This commit is contained in:
IlyaShurupov 2024-03-27 23:50:05 +03:00
parent 492ab9d13d
commit fae5a39053
3 changed files with 85 additions and 88 deletions

View file

@ -9,6 +9,32 @@
extern std::string gError;
typedef std::string Key;
class Node {
public:
enum Type : ui32 { NONE, DIRECTORY, FILE, LINK } ;
public:
virtual ~Node();
public:
Type mType = NONE;
};
class File : public Node {
public:
File();
};
class Link : public Node {
public:
Link();
[[nodiscard]] Node* getLink() const;
private:
Node* mLink = nullptr;
bool mIsHard = false;
};
struct DirectoryKey {
DirectoryKey() = default;
explicit DirectoryKey(Key val) : val(std::move(val)) {}
@ -33,40 +59,15 @@ public:
ui32 incomingLinksDynamic = 0;
};
class Node {
public:
enum Type : ui32 { NONE, DIRECTORY, FILE, LINK } ;
public:
virtual void dump(const Node* node, const Key& key) const = 0;
virtual ~Node();
public:
Type mType = NONE;
};
class File : public Node {
public:
File();
};
class Link : public Node {
public:
Link();
[[nodiscard]] Node* getLink() const;
private:
Node* mLink = nullptr;
bool mIsHard = false;
};
class Directory : public Node {
typedef AvlTree<DirectoryKey, Node*> DirectoryTree;
typedef AvlTree<DirectoryKey, class Node*> DirectoryTree;
public:
Directory();
~Directory() override;
void dump(std::stringstream& ss);
bool attachNode(const std::vector<Key>& directoryPath, const Key& newKey, Node* newNode);
Node* findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
void detachNode(Node* node);
@ -81,6 +82,7 @@ public:
private:
void updateTreeLinkCount(Node* node);
void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const;
void dumpUtil(std::stringstream& ss, ui32 currentDepth, std::vector<bool>& indents);
public:
DirectoryTree mMembers;

View file

@ -1,6 +1,8 @@
#include "DirectoryTree.hpp"
#include <sstream>
std::string gError;
Node::~Node() = default;
@ -37,9 +39,9 @@ bool Directory::attachNode(const std::vector<Key>& directoryPath, const Key& new
auto directory = ((Directory*) node);
Node* existingNode = directory->mMembers.find(DirectoryKey(newKey))->data;
if (existingNode) {
if (existingNode->mType == newNode->mType) return false; // exit silently
DirectoryTree::Node* iterNode = directory->mMembers.find(DirectoryKey(newKey));
if (iterNode) {
if (iterNode->data->mType == newNode->mType) return false; // exit silently
gError = "Cant add node";
return false;
}
@ -56,12 +58,14 @@ Node* Directory::findNode(const std::vector<Key>& path, ui32 currentDepth) {
}
const Key& key = path[currentDepth];
Node* node = mMembers.find(DirectoryKey(key))->data;
DirectoryTree::Node* iterNode = mMembers.find(DirectoryKey(key));
if (!node) {
if (!iterNode) {
return nullptr;
}
Node* node = iterNode->data;
// link on link is not allowed
while (true) {
switch (node->mType) {
@ -95,7 +99,7 @@ void Directory::getMaxDepthUtil(ui32 depth, ui32& maxDepth) const {
maxDepth = std::max(depth, maxDepth);
mMembers.traverseInorder(mMembers.getRoot(), [&](const DirectoryTree::Node* node){
if (node->data->mType == DIRECTORY) {
((Directory*)node)->getMaxDepthUtil(++depth, maxDepth);
((Directory*)node->data)->getMaxDepthUtil(++depth, maxDepth);
}
});
}
@ -104,4 +108,44 @@ ui32 Directory::getMaxDepth() const {
ui32 maxDepth = 1;
getMaxDepthUtil(1, maxDepth);
return maxDepth;
}
void Directory::dump(std::stringstream& ss) {
std::vector<bool> indents;
indents.resize(getMaxDepth());
dumpUtil(ss, 0, indents);
ss << "\n";
}
static void indent(std::stringstream & ss, ui32 depth, std::vector<bool>& indents) {
if (!depth) return;
for (auto i = 0; i < depth - 1; i++) {
ss << (indents[i] ? " |" : " ");
}
ss << " |_";
}
void Directory::dumpUtil(std::stringstream& ss, ui32 currentDepth, std::vector<bool>& indents) {
indents[currentDepth] = true;
currentDepth++;
auto lastNode = mMembers.maxNode(mMembers.getRoot());
traverseInorder([&](const DirectoryTree::Node* node){
if (lastNode == node) indents[currentDepth - 1] = false;
indent(ss, currentDepth, indents);
ss << node->key.val << "\n";
switch (node->data->mType) {
case Node::DIRECTORY:
((Directory*) node->data)->dumpUtil(ss, currentDepth, indents);
return;
default:
// do nothing for now
return;
}
});
}

View file

@ -23,7 +23,7 @@ bool FileSystem::makeDirectory(const Path& path) {
auto existingNode = parentDirectory->findNode(path.getChain());
if (existingNode) {
if (existingNode->type == Node::DIRECTORY) return true;
if (existingNode->mType == Node::DIRECTORY) return true;
gError = "Cant create directory, such node exists";
return false;
}
@ -45,7 +45,7 @@ bool FileSystem::changeCurrent(const Path& path) {
}
auto node = path.isAbsolute() ? root->findNode(path.getChain(), 0) : currentDirectory->findNode(path.getChain(), 0);
if (!node || node->type != Node::DIRECTORY) {
if (!node || node->mType != Node::DIRECTORY) {
gError = "No such directory";
return false;
}
@ -56,58 +56,9 @@ bool FileSystem::changeCurrent(const Path& path) {
void FileSystem::log() const {
std::stringstream ss;
std::vector<bool> indents;
indents.resize(root->getMaxDepth());
logNode(ss, root, 0, indents);
std::cout << ss.str() << "\n";
}
void FileSystem::logNode(std::stringstream& ss, const Node* node, const Key& key, int depth, std::vector<bool>& indents) const {
indent(ss, depth, indents);
ss << key << "\n";
switch (node->type) {
case Node::DIRECTORY:
return logDirectory(ss, (Directory*) node, depth, indents);
case Node::FILE:
return logFile(ss, (File*) node, depth, indents);
case Node::LINK:
return logLink(ss, (Link*) node, depth, indents);
}
}
void FileSystem::indent(std::stringstream & ss, int depth, std::vector<bool>& indents) const {
if (!depth) return;
for (auto i = 0; i < depth - 1; i++) {
ss << (indents[i] ? " |" : " ");
}
ss << " |_";
}
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;
depth++;
/*
auto lastNode = node->maxNode();
node->traverseInorder([&](const Node* iterNode){
if (lastNode == iterNode) indents[depth - 1] = false;
logNode(ss, iterNode, depth, indents);
});
*/
}
void FileSystem::logFile(std::stringstream& ss, const File* node, int depth, std::vector<bool>& indents) const {
indent(ss, depth, indents);
// ss << node->key << "\n";
}
void FileSystem::logLink(std::stringstream & ss, const Link* node, int depth, std::vector<bool>& indents) const {
indent(ss, depth, indents);
// ss << "link [" << node->key << "] \n";
ss << " *\n";
root->dump(ss);
std::cout << ss.str();
}
const std::string& FileSystem::getLastError() {