From 7655a7f5f06956d6453793babddfca6cc019bf4c Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Fri, 29 Mar 2024 09:23:34 +0300 Subject: [PATCH] remove tree cache (fallback to O(n) move operation). Use std::map --- inc/DirectoryTree.hpp | 87 ++-------- inc/FileSystem.hpp | 18 +- inc/Tree.hpp | 391 ------------------------------------------ src/DirectoryTree.cpp | 152 ++++++++-------- src/FileSystem.cpp | 24 +-- src/Interpreter.cpp | 6 +- test/TestTree.cpp | 137 --------------- 7 files changed, 122 insertions(+), 693 deletions(-) delete mode 100644 inc/Tree.hpp delete mode 100644 test/TestTree.cpp diff --git a/inc/DirectoryTree.hpp b/inc/DirectoryTree.hpp index 4383c83..d245945 100644 --- a/inc/DirectoryTree.hpp +++ b/inc/DirectoryTree.hpp @@ -1,42 +1,21 @@ #pragma once -#include "Tree.hpp" +typedef unsigned long long ui64; +typedef unsigned long ui32; +typedef long long i64; +typedef long i32; -#include +#include #include #include +#include + +class Link; extern std::string gError; typedef std::string Key; -struct DirectoryKey { - DirectoryKey() = default; - explicit DirectoryKey(Key val) : val(std::move(val)) {} - - [[nodiscard]] inline bool descentRight(const DirectoryKey& in) const { return in.val > val; } - [[nodiscard]] inline bool descentLeft(const DirectoryKey& in) const { return in.val < val; } - [[nodiscard]] inline bool exactNode(const DirectoryKey& in) const { return in.val == val; } - - [[nodiscard]] inline const DirectoryKey& getFindKey() const { return *this; } - static inline const DirectoryKey& keyInRightSubtree(const DirectoryKey& in) { return in; } - static inline const DirectoryKey& keyInLeftSubtree(const DirectoryKey& in) { return in; } - - template - inline void updateTreeCacheCallBack(NodeType& treeNode); - -public: - Key val; - - ui32 incomingLinksHard = 0; - ui32 incomingLinksDynamic = 0; -}; - -typedef AvlTree DirectoryTree; - class Node { -public: - enum Type : ui32 { NONE, DIRECTORY, FILE, LINK } ; - public: Node() = default; Node(const Node& node); @@ -45,14 +24,17 @@ public: [[nodiscard]] virtual Node* clone() const; public: - Type mType = NONE; - Node* mParent = nullptr; - DirectoryTree::Node* mTreeNode = nullptr; + enum Type : ui32 { NONE, DIRECTORY, FILE, LINK } ; + Type mType = NONE; // TODO : remove - std::vector mIncomingHardLinks; - std::vector mIncomingDynamicLinks; + class Directory* mParent = nullptr; + + std::vector mIncomingHardLinks; + std::vector mIncomingDynamicLinks; }; +typedef std::map DirectoryTree; + class File : public Node { public: File(); @@ -99,46 +81,13 @@ public: [[nodiscard]] ui32 getMaxDepth() const; - template - void traverseInorder(tFunctor functor) const { - mMembers.traverseInorder(mMembers.getRoot(), functor); - } - - void getNodePath(Node* node, std::vector& path) const; + void getNodeStraightPath(Node* node, std::vector& path) const; [[nodiscard]] ui64 size() const; - static void updateTreeLinkCount(Node* node); - private: void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const; void dumpUtil(std::stringstream& ss, ui32 currentDepth, std::vector& indents); public: DirectoryTree mMembers; -}; - - -template -inline void DirectoryKey::updateTreeCacheCallBack(NodeType& treeNode) { - treeNode.data->mTreeNode = &treeNode; - - incomingLinksHard = 0; - if (treeNode.mLeft) incomingLinksHard += treeNode.mLeft->key.incomingLinksHard; - if (treeNode.mRight) incomingLinksHard += treeNode.mRight->key.incomingLinksHard; - - incomingLinksDynamic = 0; - if (treeNode.mLeft) incomingLinksDynamic += treeNode.mLeft->key.incomingLinksDynamic; - if (treeNode.mRight) incomingLinksDynamic += treeNode.mRight->key.incomingLinksDynamic; - - incomingLinksHard += treeNode.data->mIncomingHardLinks.size(); - incomingLinksDynamic += treeNode.data->mIncomingDynamicLinks.size(); - - if (treeNode.data->mType == Node::DIRECTORY) { - auto directory = (Directory*)treeNode.data; - if (directory->mMembers.size()) { - const auto& rootKey = directory->mMembers.getRoot()->key; - incomingLinksDynamic += rootKey.incomingLinksDynamic; - incomingLinksHard += rootKey.incomingLinksHard; - } - } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/inc/FileSystem.hpp b/inc/FileSystem.hpp index df5f508..9f5b5c4 100644 --- a/inc/FileSystem.hpp +++ b/inc/FileSystem.hpp @@ -5,10 +5,21 @@ #include +// FIX MEMORY VIOLATIONS WITH LINKS + + +// DONT STORE CACHE +// DO O(N) deletion and moving +// in-tree node links will report false to those operations and hard nodes deletion +// use in node 'is_delete' flag and travers all nodes with link checks +// remove mParent mTreeNode links + +// Key (is copied on each tree access) !!! + // Functionality: -// - print links and link counts -// - update link counts -// - add link creation commands +// deleting directory - mark all nodes as deleted +// traverse and check for links +// unlink if those links are outgoing // Refactor // - remove code duplication @@ -17,6 +28,7 @@ // - introduce smart pointers // - reconsider switch statements + class FileSystem { public: FileSystem(); diff --git a/inc/Tree.hpp b/inc/Tree.hpp deleted file mode 100644 index 7898a42..0000000 --- a/inc/Tree.hpp +++ /dev/null @@ -1,391 +0,0 @@ -#pragma once - -#include -#include - -typedef unsigned long long ui64; -typedef unsigned long ui32; -typedef long long i64; -typedef long i32; - -template -struct SelectValueOrReference { - using type = typename std::conditional::value, T, const T&>::type; -}; - -template -struct AvlNumericKey { - - NumericType val; - - AvlNumericKey() = default; - AvlNumericKey(NumericType val) : - val(val) {} - - inline bool descentRight(AvlNumericKey in) const { return in.val > val; } - inline bool descentLeft(AvlNumericKey in) const { return in.val < val; } - inline bool exactNode(AvlNumericKey in) const { return in.val == val; } - - inline const AvlNumericKey& getFindKey(/**/) const { return *this; } - inline const AvlNumericKey& keyInRightSubtree(const AvlNumericKey& in) const { return in; } - inline const AvlNumericKey& keyInLeftSubtree(const AvlNumericKey& in) const { return in; } - - template - inline void updateTreeCacheCallBack(const NodeType&) {} -}; - -template -class AvlTree { - typedef SelectValueOrReference::type KeyArg; - typedef SelectValueOrReference::type DataArg; - -public: - class Node { - friend AvlTree; - - private: - Node(KeyArg aKey, DataArg aData) : - key(aKey), - data(aData) {} - - public: - Data data; - Key key; - - public: - Node* mLeft = nullptr; - Node* mRight = nullptr; - Node* mParent = nullptr; - ui64 mHeight = 0; - - private: - inline bool descentRight(KeyArg aKey) const { return key.descentRight(aKey); } - inline bool descentLeft(KeyArg aKey) const { return key.descentLeft(aKey); } - inline bool exactNode(KeyArg aKey) const { return key.exactNode(aKey); } - - inline KeyArg getFindKey(const Node* node = nullptr) const { return key.getFindKey(/*node*/); } - inline KeyArg keyInRightSubtree(KeyArg aKey) const { return key.keyInRightSubtree(aKey); } - inline KeyArg keyInLeftSubtree(KeyArg aKey) const { return key.keyInLeftSubtree(aKey); } - - inline void updateTreeCacheCallBack() { key.updateTreeCacheCallBack(*this); } - }; - -public: - AvlTree() = default; - ~AvlTree() { removeAll(); } - - [[nodiscard]] ui64 size() const { return mSize; } - - Node* getRoot() const { return this->mRoot; } - - void insert(KeyArg key, DataArg data) { - mRoot = insertUtil(mRoot, key, data); - mRoot->mParent = nullptr; - } - - void remove(KeyArg key) { - mRoot = removeUtil(mRoot, key); - if (mRoot) mRoot->mParent = nullptr; - } - - Node* maxNode(Node* head) const { - if (!head) return nullptr; - while (head->mRight != nullptr) { - head = head->mRight; - } - return head; - } - - Node* minNode(Node* head) const { - if (!head) return nullptr; - while (head->mLeft != nullptr) { - head = head->mLeft; - } - return head; - } - - Node* find(KeyArg key) const { - Node* iter = mRoot; - while (true) { - if (!iter) return nullptr; - if (iter->exactNode(key)) return iter; - if (iter->descentLeft(key)) { - // key = iter->keyInLeftSubtree(key); - iter = iter->mLeft; - } else { - // key = iter->keyInRightSubtree(key); - iter = iter->mRight; - } - } - } - - Node* findLessOrEq(KeyArg key) const { - Node* iter = mRoot; - while (true) { - if (!iter) return nullptr; - if (iter->exactNode(key)) return iter; - if (iter->descentLeft(key)) { - if (iter->mLeft) { - key = iter->keyInLeftSubtree(key); - iter = iter->mLeft; - } else { - return iter; - } - } else { - if (iter->mRight) { - key = iter->keyInRightSubtree(key); - iter = iter->mRight; - } else { - return iter; - } - } - } - } - - // returns first invalid node - const Node* findInvalidNode(const Node* head) const { - if (head == nullptr) return nullptr; - - if (head->mLeft) { - // TODO: incomplete test - if (!head->descentLeft(head->mLeft->getFindKey(head))) return head; - if (head->mLeft->mParent != head) return head; - if (!head->mRight && head->mLeft->mHeight != head->mHeight - 1) return head; - } - - if (head->mRight) { - if (!head->descentRight(head->mRight->getFindKey(head))) return head; - if (head->mRight->mParent != head) return head; - if (!head->mLeft && head->mRight->mHeight != head->mHeight - 1) return head; - } - - if (head->mLeft && head->mRight) { - if (std::max(head->mLeft->mHeight, head->mRight->mHeight) != head->mHeight - 1) return head; - } - - int balance = getNodeHeight(head->mRight) - getNodeHeight(head->mLeft); - - if (balance > 1 || balance < -1) return head; - - const Node* ret = findInvalidNode(head->mRight); - - if (ret) return ret; - - return findInvalidNode(head->mLeft); - } - - bool isValid() { return findInvalidNode(getRoot()) == nullptr; } - - template - void traverseInorder(Node* node, tFunctor functor) { - if (!node) return; - traverseInorder(node->mLeft, functor); - functor(node); - traverseInorder(node->mRight, functor); - } - - template - void traverseInorder(const Node* node, tFunctor functor) const { - if (!node) return; - traverseInorder(node->mLeft, functor); - functor(node); - traverseInorder(node->mRight, functor); - } - - void removeAll() { - if (!mRoot) return; - removeUtil(mRoot); - mRoot = nullptr; - mSize = 0; - } - - void removeUtil(Node* node) { - if (node->mLeft) removeUtil(node->mLeft); - if (node->mRight) removeUtil(node->mRight); - deleteNode(node); - } - -private: - inline void deleteNode(Node* node) { - delete node; - } - - inline Node* newNode(KeyArg key, DataArg data) { - auto out = new Node(key, data); - return out; - } - - inline void injectNodeInstead(Node* target, Node* from) { - std::swap(target->data, from->data); - target->key = from->key; - target->updateTreeCacheCallBack(); - from->updateTreeCacheCallBack(); - } - - inline i64 getNodeHeight(const Node* node) const { return node ? node->mHeight : -1; } - - // returns new head - Node* rotateLeft(Node* pivot) { - assert(pivot); - - Node* const head = pivot; - Node* const right = pivot->mRight; - Node* const right_left = right->mLeft; - Node* const parent = pivot->mParent; - - // parents - if (right_left) right_left->mParent = head; - head->mParent = right; - right->mParent = parent; - - // children - head->mRight = right_left; - right->mLeft = head; - - // heights - head->mHeight = 1 + std::max(getNodeHeight(head->mLeft), getNodeHeight(head->mRight)); - right->mHeight = 1 + std::max(getNodeHeight(right->mLeft), getNodeHeight(right->mRight)); - - // cache - head->updateTreeCacheCallBack(); - right->updateTreeCacheCallBack(); - - return right; - } - - Node* rotateRight(Node* pivot) { - assert(pivot); - - Node* const head = pivot; - Node* const left = pivot->mLeft; - Node* const left_right = left->mRight; - Node* const parent = pivot->mParent; - - // parents - if (left_right) left_right->mParent = head; - head->mParent = left; - left->mParent = parent; - - // children - head->mLeft = left_right; - left->mRight = head; - - // heights - head->mHeight = 1 + std::max(getNodeHeight(head->mLeft), getNodeHeight(head->mRight)); - left->mHeight = 1 + std::max(getNodeHeight(left->mLeft), getNodeHeight(left->mRight)); - - // cache - head->updateTreeCacheCallBack(); - left->updateTreeCacheCallBack(); - - return left; - } - - // recursively returns valid isLeft or isRight child or root - Node* insertUtil(Node* head, KeyArg key, DataArg data) { - - Node* insertedNode; - - if (head == nullptr) { - mSize++; - Node* out = newNode(key, data); - out->updateTreeCacheCallBack(); - return out; - } else if (head->exactNode(key)) { - return head; - } else if (head->descentRight(key)) { - insertedNode = insertUtil(head->mRight, head->keyInRightSubtree(key), data); - head->mRight = insertedNode; - insertedNode->mParent = head; - } else { - insertedNode = insertUtil(head->mLeft, head->keyInLeftSubtree(key), data); - head->mLeft = insertedNode; - insertedNode->mParent = head; - } - - // update height - head->mHeight = 1 + std::max(getNodeHeight(head->mRight), getNodeHeight(head->mLeft)); - - i64 balance = i64(getNodeHeight(head->mRight) - getNodeHeight(head->mLeft)); - - if (balance > 1) { - if (head->mRight->descentRight(head->keyInRightSubtree(key))) { - return rotateLeft(head); - } else { - head->mRight = rotateRight(head->mRight); - return rotateLeft(head); - } - } else if (balance < -1) { - if (head->mLeft->descentLeft(head->keyInLeftSubtree(key))) { - return rotateRight(head); - } else { - head->mLeft = rotateLeft(head->mLeft); - return rotateRight(head); - } - } - - head->updateTreeCacheCallBack(); - - return head; - } - - Node* removeUtil(Node* head, KeyArg key) { - if (head == nullptr) return head; - - if (head->exactNode(key)) { - if (head->mRight && head->mLeft) { - Node* min = minNode(head->mRight); - auto const& newKey = min->getFindKey(head->mRight); - injectNodeInstead(head, min); - head->mRight = removeUtil(head->mRight, newKey); - } else if (head->mRight) { - injectNodeInstead(head, head->mRight); - deleteNode(head->mRight); - head->mRight = nullptr; - mSize--; - } else if (head->mLeft) { - injectNodeInstead(head, head->mLeft); - deleteNode(head->mLeft); - head->mLeft = nullptr; - mSize--; - } else { - deleteNode(head); - mSize--; - head = nullptr; - } - } else if (head->descentRight(key)) { - head->mRight = removeUtil(head->mRight, head->keyInRightSubtree(key)); - } else if (head->descentLeft(key)) { - head->mLeft = removeUtil(head->mLeft, head->keyInLeftSubtree(key)); - } - - if (head == nullptr) return head; - - head->mHeight = 1 + std::max(getNodeHeight(head->mRight), getNodeHeight(head->mLeft)); - i64 balance = getNodeHeight(head->mRight) - getNodeHeight(head->mLeft); - - if (balance < -1) { - if (getNodeHeight(head->mLeft->mLeft) >= getNodeHeight(head->mLeft->mRight)) { - return rotateRight(head); - } else { - head->mLeft = rotateLeft(head->mLeft); - return rotateRight(head); - } - } else if (balance > 1) { - if (getNodeHeight(head->mRight->mRight) >= getNodeHeight(head->mRight->mLeft)) { - return rotateLeft(head); - } else { - head->mRight = rotateRight(head->mRight); - return rotateLeft(head); - } - } - - head->updateTreeCacheCallBack(); - - return head; - } - -private: - Node* mRoot = nullptr; - ui64 mSize = 0; -}; diff --git a/src/DirectoryTree.cpp b/src/DirectoryTree.cpp index 865784f..e084556 100644 --- a/src/DirectoryTree.cpp +++ b/src/DirectoryTree.cpp @@ -2,11 +2,19 @@ #include "DirectoryTree.hpp" #include +#include +#include std::string gError; bool gDebug = true; -Node::~Node() = default; +Node::~Node() { + // assert(mIncomingHardLinks.empty()); + // for (auto dynamicLink : mIncomingDynamicLinks) { + // dynamicLink->mParent->detachNode(dynamicLink->mTreeNode->key.val); + // delete dynamicLink; + // +} Node::Node(const Node &node) { mType = node.mType; @@ -65,23 +73,17 @@ Link *Link::clone() const { } Link::~Link() { - assert(mLink); - auto& links = mIsHard ? mLink->mIncomingHardLinks : mLink->mIncomingDynamicLinks; - links.erase(std::remove(links.begin(), links.end(), this), links.end()); - Directory::updateTreeLinkCount(mLink); - mLink = nullptr; + // assert(mLink); + // auto& links = mIsHard ? mLink->mIncomingHardLinks : mLink->mIncomingDynamicLinks; + // links.erase(std::remove(links.begin(), links.end(), this), links.end()); + // Directory::updateTreeLinkCount(mLink); + // mLink = nullptr; } Directory::Directory() { mType = DIRECTORY; } -Directory::~Directory() { - mMembers.traverseInorder(mMembers.getRoot(), [](DirectoryTree::Node* node){ - delete node->data; - }); -} - bool Directory::attachNode(const std::vector& directoryPath, const Key& newKey, Node* newNode) { Node* node = findNode(directoryPath, 0); @@ -96,17 +98,16 @@ bool Directory::attachNode(const std::vector& directoryPath, const Key& new } bool Directory::attachNode(const Key &newKey, Node *newNode) { - DirectoryTree::Node* iterNode = mMembers.find(DirectoryKey(newKey)); - if (iterNode) { - if (iterNode->data->mType == newNode->mType) return false; // exit silently + auto iterNode = mMembers.find(newKey); + if (iterNode != mMembers.end()) { + if (iterNode->second->mType == newNode->mType) return false; // exit silently gError = "Can not add node"; return false; } - mMembers.insert(DirectoryKey(newKey), newNode); + mMembers.insert({ newKey, newNode }); newNode->mParent = this; - updateTreeLinkCount(this); return true; } @@ -121,27 +122,25 @@ bool Directory::detachNode(const std::vector& directoryPath, const Key& key } bool Directory::detachNode(const Key& key) { - DirectoryTree::Node* removeNode = mMembers.find(DirectoryKey(key)); - if (!removeNode) { + auto removeNode = mMembers.find(key); + if (removeNode == mMembers.end()) { gError = "Invalid path"; return false; } - if (removeNode->key.incomingLinksHard || removeNode->key.incomingLinksDynamic) { - gError = "Cannot modify node with incoming hard links"; - return false; - } + //if (removeNode->key.incomingLinksHard || removeNode->key.incomingLinksDynamic) { + // gError = "Cannot modify node with incoming hard links"; + // return false; + //} - removeNode->mParent = nullptr; - mMembers.remove(DirectoryKey(key)); - - updateTreeLinkCount(this); + removeNode->second->mParent = nullptr; + mMembers.erase(key); return true; } Node* Directory::findNode(const Key& key) { - DirectoryTree::Node* iterNode = mMembers.find(DirectoryKey(key)); - return iterNode ? iterNode->data : nullptr; + auto iterNode = mMembers.find(key); + return iterNode != mMembers.end() ? iterNode->second : nullptr; } Node* Directory::findNode(const std::vector& path, ui32 currentDepth) { @@ -150,13 +149,13 @@ Node* Directory::findNode(const std::vector& path, ui32 currentDepth) { } const Key& key = path[currentDepth]; - DirectoryTree::Node* iterNode = mMembers.find(DirectoryKey(key)); + auto iterNode = mMembers.find(key); - if (!iterNode) { + if (iterNode == mMembers.end()) { return nullptr; } - Node* node = iterNode->data; + Node* node = iterNode->second; // link on link is not allowed while (true) { @@ -179,26 +178,14 @@ Node* Directory::findNode(const std::vector& path, ui32 currentDepth) { } } -void Directory::updateTreeLinkCount(Node* node) { - if (!node || !node->mTreeNode) return; - - node->mTreeNode->key.updateTreeCacheCallBack(*node->mTreeNode); - - if (node->mTreeNode->mParent) { - updateTreeLinkCount(node->mTreeNode->mParent->data); - } else { - updateTreeLinkCount(node->mParent); - } -} - void Directory::getMaxDepthUtil(ui32 depth, ui32& maxDepth) const { - if (!mMembers.getRoot()) return; + if (mMembers.empty()) return; maxDepth = std::max(depth, maxDepth); - mMembers.traverseInorder(mMembers.getRoot(), [&](const DirectoryTree::Node* node){ - if (node->data->mType == DIRECTORY) { - ((Directory*)node->data)->getMaxDepthUtil(++depth, maxDepth); + for (auto& node : mMembers) { + if (node.second->mType == DIRECTORY) { + ((Directory*)node.second)->getMaxDepthUtil(++depth, maxDepth); } - }); + } } ui32 Directory::getMaxDepth() const { @@ -223,51 +210,57 @@ static void indent(std::stringstream & ss, ui32 depth, std::vector& indent } void Directory::dumpUtil(std::stringstream& ss, ui32 currentDepth, std::vector& indents) { + if (mMembers.empty()) + return; + indents[currentDepth] = true; currentDepth++; - auto lastNode = mMembers.maxNode(mMembers.getRoot()); - traverseInorder([&](const DirectoryTree::Node* node){ - if (lastNode == node) indents[currentDepth - 1] = false; + const auto& lastNode = mMembers.rbegin()->first; + + for (auto & member : mMembers) { + if (lastNode == member.first) + indents[currentDepth - 1] = false; indent(ss, currentDepth, indents); - switch (node->data->mType) { + switch (member.second->mType) { case Node::DIRECTORY: - ss << node->key.val; - if (gDebug) ss << " [" << node->key.incomingLinksHard << ":" << node->key.incomingLinksDynamic << "]"; + ss << member.first; + if (gDebug) ss << " [" << member.second->mIncomingHardLinks.size() << ":" << member.second->mIncomingDynamicLinks.size() << "]"; ss << "\n"; - ((Directory*) node->data)->dumpUtil(ss, currentDepth, indents); - return; + ((Directory*) member.second)->dumpUtil(ss, currentDepth, indents); + break; case Node::LINK: { - auto linkNode = ((Link*)node->data); - ss << node->key.val << (linkNode->isHard() ? " hlink[/" : " dlink[/"); - std::vector path; - getNodePath(linkNode->getLink(), path); + auto linkNode = ((Link*)member.second); + ss << member.first << (linkNode->isHard() ? " hlink[/" : " dlink[/"); + std::vector path; + getNodeStraightPath(linkNode->getLink(), path); std::reverse(path.begin(), path.end()); - for (auto key : path) ss << *key << "/"; + for (auto key : path) + ss << "X" << "/"; ss << "]\n"; - return; + break; } case Node::FILE: - ss << node->key.val; + ss << member.first; if (gDebug) ss << " [file]"; ss << "\n"; - return; + break; default: ss << " ERROR \n"; - return; + break; } - }); + } } -void Directory::getNodePath(Node* node, std::vector& path) const { - if (!node || !node->mTreeNode) return; - path.push_back(&node->mTreeNode->key.val); - getNodePath(node->mParent, path); +void Directory::getNodeStraightPath(Node* node, std::vector& path) const { + if (!node) return; + path.push_back(node); + getNodeStraightPath(node->mParent, path); } ui64 Directory::size() const { @@ -275,16 +268,17 @@ ui64 Directory::size() const { } Directory::Directory(const Directory &node) : Node(node) { - node.traverseInorder([&](const DirectoryTree::Node* node){ - auto newNode = node->data->clone(); - mMembers.insert(node->key, newNode); + for (auto & member : node.mMembers) { + auto newNode = member.second->clone(); + mMembers.insert({ member.first, newNode }); newNode->mParent = this; - if (newNode->mType == LINK) { - updateTreeLinkCount(((Link*)newNode)->getLink()); - } - }); + } +} - updateTreeLinkCount(this); +Directory::~Directory() { + for (auto node : mMembers) { + delete node.second; + } } Directory *Directory::clone() const { diff --git a/src/FileSystem.cpp b/src/FileSystem.cpp index 14afcc6..089ce37 100644 --- a/src/FileSystem.cpp +++ b/src/FileSystem.cpp @@ -2,6 +2,8 @@ #include "FileSystem.hpp" #include +#include +#include FileSystem::FileSystem() { root = new Directory(); @@ -122,7 +124,7 @@ bool FileSystem::copyNode(const Path& source, const Path& target) { auto targetDirectory = (Directory*)targetNode; - Key key = sourceNode->mTreeNode->key.val; + Key key = source.getFilename(); if (targetDirectory->findNode(key)) { // gError = "Node with such name already exists in the target directory"; @@ -163,7 +165,7 @@ bool FileSystem::moveNode(const Path &source, const Path &target) { auto sourceParentDirectory = (Directory*)sourceParentNode; auto targetDirectory = (Directory*)targetNode; - Key key = sourceNode->mTreeNode->key.val; + Key key = source.getFilename(); if (targetDirectory->findNode(key)) { gError = "Node with such name already exists in the target directory"; @@ -206,7 +208,7 @@ bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic return false; } - const Key& key = sourceNode->mTreeNode->key.val; + const Key& key = source.getFilename(); auto targetDirectory = (Directory*)targetNode; if (targetDirectory->findNode(key)) { @@ -218,8 +220,6 @@ bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic assert(targetDirectory->attachNode(key, newLink)); - Directory::updateTreeLinkCount(sourceNode); - return true; } @@ -267,13 +267,13 @@ bool FileSystem::changeCurrent(const Path& path) { void FileSystem::log() const { std::stringstream ss; - std::vector currentPath; - root->getNodePath(currentDirectory, currentPath); + std::vector currentPath; + root->getNodeStraightPath(currentDirectory, currentPath); std::reverse(currentPath.begin(), currentPath.end()); ss << "cd - /"; for (auto key : currentPath) { - ss << *key << "/"; + ss << "X" << "/"; } ss << "\n"; @@ -286,11 +286,11 @@ const std::string& FileSystem::getLastError() { } bool FileSystem::isPathContainsCurrent(Node* node) { - std::vector currentPath; - std::vector path; + std::vector currentPath; + std::vector path; - root->getNodePath(currentDirectory, currentPath); - root->getNodePath(node, path); + root->getNodeStraightPath(currentDirectory, currentPath); + root->getNodeStraightPath(node, path); std::reverse(currentPath.begin(), currentPath.end()); std::reverse(path.begin(), path.end()); diff --git a/src/Interpreter.cpp b/src/Interpreter.cpp index 62a8d26..fd5938e 100644 --- a/src/Interpreter.cpp +++ b/src/Interpreter.cpp @@ -108,6 +108,8 @@ void Interpreter::interpret(const std::string& command) { std::vector words; getWords(command, words); + std::cout << command << "\n"; + if (words.empty()) { reportError("Empty command"); return; @@ -131,10 +133,10 @@ void Interpreter::interpret(const std::string& command) { bool success = iter->second.callback(mFileSystem, words); + mFileSystem.log(); + if (!success) { reportError(FileSystem::getLastError()); return; } - - mFileSystem.log(); } \ No newline at end of file diff --git a/test/TestTree.cpp b/test/TestTree.cpp deleted file mode 100644 index 5ff8afa..0000000 --- a/test/TestTree.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "Tree.hpp" - -#include "UnitTest++/UnitTest++.h" - -static double randomFloat() { - return static_cast(std::rand()) / static_cast(RAND_MAX); -} - -const auto size = 1000; - -class TestClass { - ui64 val1 = 0; - -public: - TestClass() = default; - explicit TestClass(ui64 val) : val1(val) {} - [[nodiscard]] bool operator==(const TestClass& in) const { return in.val1 == val1; } - [[nodiscard]] ui64 getVal() const { return val1; } - void setVal(ui64 val) { val1 = val; } -}; - -SUITE(AvlTree) { - TEST(Simple) { - AvlTree, TestClass> tree; - - CHECK(tree.size() == 0); - CHECK(tree.getRoot() == nullptr); - - tree.insert(6, TestClass(6)); - CHECK(tree.isValid()); - CHECK(tree.size() == 1); - CHECK(tree.getRoot()->data == TestClass(6)); - - tree.remove(6); - CHECK(tree.isValid()); - CHECK(tree.size() == 0); - CHECK(tree.getRoot() == nullptr); - } - - TEST(Persistance) { - AvlTree, TestClass> tree; - - struct Item { - Item() : - data(0) {} - bool presents = false; - TestClass data; - }; - - Item buff[size]; - - for (auto i = 0; i < size; i++) { - buff[i].data.setVal(i); - } - - // random load - ui64 loadSize = 0; - while (loadSize < size / 2) { - auto idx = ui64(randomFloat() * (size - 1)); - assert(idx < size); - if (!buff[idx].presents) { - tree.insert((i64) buff[idx].data.getVal(), buff[idx].data); - loadSize++; - buff[idx].presents = true; - - CHECK(tree.isValid()); - CHECK(tree.size() == loadSize); - } - } - - for (auto& item : buff) { - if (item.presents) continue; - tree.insert((i64) item.data.getVal(), item.data); - loadSize++; - item.presents = true; - - CHECK(tree.isValid()); - CHECK(tree.size() == loadSize); - } - - CHECK(tree.size() == size); - CHECK(tree.maxNode(tree.getRoot())->data.getVal() == size - 1); - CHECK(tree.minNode(tree.getRoot())->data.getVal() == 0); - - // find - for (auto item : buff) { - auto node = tree.find((i64) item.data.getVal()); - CHECK(node); - if (!node) continue; - CHECK(node->data.getVal() == item.data.getVal()); - } - - CHECK(!tree.find(size + 1)); - CHECK(!tree.find(-1)); - - // random unload - ui64 unloadSize = 0; - while (unloadSize < size / 2) { - auto idx = ui64(randomFloat() * (size - 1)); - if (buff[idx].presents) { - - tree.remove((i64) buff[idx].data.getVal()); - - unloadSize++; - buff[idx].presents = false; - - // find - for (auto item : buff) { - if (!item.presents) continue; - auto node = tree.find((i64) item.data.getVal()); - CHECK(node); - if (!node) continue; - CHECK(node->data.getVal() == item.data.getVal()); - } - - CHECK(tree.isValid()); - CHECK(tree.size() == size - unloadSize); - } - } - - for (auto& item : buff) { - if (item.presents) { - tree.remove((i64) item.data.getVal()); - unloadSize++; - item.presents = false; - - CHECK(tree.isValid()); - CHECK(tree.size() == size - unloadSize); - } - } - - CHECK(tree.size() == 0); - CHECK(tree.getRoot() == nullptr); - CHECK(tree.maxNode(tree.getRoot()) == nullptr); - CHECK(tree.minNode(tree.getRoot()) == nullptr); - } -} \ No newline at end of file