use smart pointers

This commit is contained in:
IlyaShurupov 2024-03-29 15:07:27 +03:00
parent cd593ab024
commit 8e150b52c3
8 changed files with 282 additions and 258 deletions

View file

@ -3,7 +3,7 @@
#include "Node.hpp"
class Directory : public Node {
typedef std::map<Key, Node*> DirectoryTree;
typedef std::map<Key, std::shared_ptr<Node>> DirectoryTree;
public:
Directory();
@ -11,16 +11,13 @@ public:
~Directory() override;
[[nodiscard]] Directory* clone() const override;
bool attachNode(const std::vector<Key>& directoryPath, const Key& newKey, Node* newNode) override;
bool detachNode(const std::vector<Key>& directoryPath, const Key& key) override;
[[nodiscard]] std::shared_ptr<Node> clone() const override;
bool detachNode(const Key& key) override;
bool attachNode(const Key &newKey, Node *newNode) override;
bool attachNode(const Key &newKey, std::shared_ptr<Node> newNode) override;
Node* findNode(const std::vector<Key>& path, ui32 currentDepth = 0) override;
Node* findNode(const Key& path) override;
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0) override;
std::shared_ptr<Node> findNode(const Key& path) override;
[[nodiscard]] ui64 size() const override;

View file

@ -47,9 +47,10 @@ public:
static const std::string& getLastError();
private:
bool isPathContainsCurrent(Node* node);
bool isPathContainsCurrent(const std::shared_ptr<Node>& node);
std::shared_ptr<Node> getNode(const Path& path, bool parent);
private:
Node* root = nullptr;
Node* currentDirectory = nullptr;
std::shared_ptr<Node> root = nullptr;
std::shared_ptr<Node> currentDirectory = nullptr;
};

View file

@ -4,25 +4,25 @@
class Link : public Node {
public:
Link(Node* target, bool isHard);
Link(const std::shared_ptr<Node>& target, bool isHard);
Link(const Link& node);
~Link() override;
[[nodiscard]] Link* clone() const override;
[[nodiscard]] std::shared_ptr<Node> clone() const override;
[[nodiscard]] Node* getLink() const;
[[nodiscard]] std::shared_ptr<Node> getLink() const;
[[nodiscard]] bool isHard() const;
Node* getTarget() override;
std::shared_ptr<Node> getTarget() override;
// link on link is not allowed, so no inf looping here
Node* findNode(const std::vector<Key>& path, ui32 currentDepth) override;
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth) override;
void dumpUtil(std::stringstream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) override;
bool isLink() const override { return true; }
private:
Node* mLink = nullptr;
std::shared_ptr<Node> mLink = nullptr;
bool mIsHard = false;
};

View file

@ -10,6 +10,7 @@ typedef long i32;
#include <vector>
#include <string>
#include <cassert>
#include <memory>
class Link;
@ -22,13 +23,10 @@ public:
Node(const Node& node);
virtual ~Node();
[[nodiscard]] virtual Node* clone() const;
virtual bool attachNode(const std::vector<Key>& directoryPath, const Key& newKey, Node* newNode) { return false; }
virtual bool detachNode(const std::vector<Key>& directoryPath, const Key& key) { return false; }
[[nodiscard]] virtual std::shared_ptr<Node> clone() const;
virtual bool detachNode(const Key& key) { return false; }
virtual bool attachNode(const Key &newKey, Node *newNode) { return false; }
virtual bool attachNode(const Key &newKey, std::shared_ptr<Node> newNode) { return false; }
virtual void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const {}
@ -38,15 +36,15 @@ public:
void dump(std::stringstream& ss);
void getNodeStraightPath(Node* node, std::vector<const Node*>& path) const;
void getNodeStraightPath(const std::shared_ptr<Node>& node, std::vector<std::shared_ptr<Node>>& path) const;
virtual ui64 size() const { return 0; }
virtual Node* getTarget() { return this; }
virtual std::shared_ptr<Node> getTarget();
virtual Node* findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
virtual std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
virtual Node* findNode(const Key& path) { return nullptr; }
virtual std::shared_ptr<Node> findNode(const Key& path) { return nullptr; }
bool empty() const { return !size(); }
@ -57,8 +55,8 @@ public:
virtual bool isHard() const { return false; }
public:
Node* mParent = nullptr;
std::weak_ptr<Node> mParent;
std::vector<Link*> mIncomingHardLinks;
std::vector<Link*> mIncomingDynamicLinks;
std::vector<std::weak_ptr<Link>> mIncomingHardLinks;
std::vector<std::weak_ptr<Link>> mIncomingDynamicLinks;
};

View file

@ -8,24 +8,12 @@
Directory::Directory() {
}
bool Directory::attachNode(const std::vector<Key>& directoryPath, const Key& newKey, Node* newNode) {
Node* node = findNode(directoryPath);
if (!node) {
gError = "Invalid path";
return false;
}
while (node->getTarget() != node) node = node->getTarget();
return node->attachNode(newKey, newNode);
}
bool Directory::attachNode(const Key &newKey, Node *newNode) {
bool Directory::attachNode(const Key &newKey, std::shared_ptr<Node> newNode) {
auto iterNode = mMembers.find(newKey);
if (iterNode != mMembers.end()) {
Node* existingNode = iterNode->second;
if (!(typeid(*existingNode) == typeid(*newNode) && newNode->empty() && existingNode->empty())) {
auto existingNode = iterNode->second;
if (!(false && newNode->empty() && existingNode->empty())) {
gError = "Such node already exists";
return false;
}
@ -33,15 +21,9 @@ bool Directory::attachNode(const Key &newKey, Node *newNode) {
}
mMembers.insert({ newKey, newNode });
newNode->mParent = this;
return true;
}
bool Directory::detachNode(const std::vector<Key>& directoryPath, const Key& key) {
Node* node = findNode(directoryPath);
return node->detachNode(key);
}
bool Directory::detachNode(const Key& key) {
auto removeNode = mMembers.find(key);
if (removeNode == mMembers.end()) {
@ -54,21 +36,16 @@ bool Directory::detachNode(const Key& key) {
// return false;
//}
removeNode->second->mParent = nullptr;
mMembers.erase(key);
return true;
}
Node* Directory::findNode(const Key& key) {
std::shared_ptr<Node> Directory::findNode(const Key& key) {
auto iterNode = mMembers.find(key);
return iterNode != mMembers.end() ? iterNode->second : nullptr;
}
Node* Directory::findNode(const std::vector<Key>& path, ui32 currentDepth) {
if (path.size() == currentDepth) {
return this;
}
std::shared_ptr<Node> Directory::findNode(const std::vector<Key>& path, ui32 currentDepth) {
const Key& key = path[currentDepth];
auto nextNode = mMembers.find(key);
@ -76,6 +53,10 @@ Node* Directory::findNode(const std::vector<Key>& path, ui32 currentDepth) {
return nullptr;
}
if (path.size() == currentDepth + 1) {
return nextNode->second;
}
return nextNode->second->findNode(path, currentDepth + 1);
}
@ -115,16 +96,19 @@ Directory::Directory(const Directory &node) : Node(node) {
for (auto & member : node.mMembers) {
auto newNode = member.second->clone();
mMembers.insert({ member.first, newNode });
newNode->mParent = this;
}
}
Directory::~Directory() {
for (const auto& node : mMembers) {
delete node.second;
// delete node.second;
}
}
Directory *Directory::clone() const {
return new Directory(*this);
std::shared_ptr<Node> Directory::clone() const {
auto out = std::make_shared<Directory>(*this);
for (auto& member : out->mMembers) {
member.second->mParent = out;
}
return out;
}

View file

@ -9,13 +9,47 @@
#include <algorithm>
FileSystem::FileSystem() {
root = new Directory();
root = std::make_shared<Directory>();
currentDirectory = root;
initializeTransitions();
}
FileSystem::~FileSystem() {
delete root;
FileSystem::~FileSystem() = default;
std::shared_ptr<Node> FileSystem::getNode(const Path& path, bool parent) {
auto pathChain = parent ? path.getParentChain() : path.getChain();
auto currentNode = path.isAbsolute() ? root : currentDirectory;
auto parentNode = pathChain.empty() ? currentNode : currentNode->findNode(pathChain);
if (parent) {
while (parentNode->getTarget()) {
parentNode = parentNode->getTarget();
}
}
return parentNode;
}
bool FileSystem::changeCurrent(const Path& path) {
if (path.isInvalid()) {
gError = "Invalid path";
return false;
}
auto parentNode = getNode(path, false);
if (!parentNode) {
gError = "No such directory";
return false;
}
if (!parentNode->isDirectory()) {
gError = "Path is not a directory";
return false;
}
currentDirectory = parentNode;
return true;
}
bool FileSystem::makeDirectory(const Path& path) {
@ -24,15 +58,21 @@ bool FileSystem::makeDirectory(const Path& path) {
return false;
}
Node* parentNode = path.isAbsolute() ? root : currentDirectory;
auto parentNode = getNode(path, true);
auto newDirectory = new Directory();
if (!parentNode->attachNode(path.getParentChain(), path.getFilename(), newDirectory)) {
delete newDirectory;
gError = "Invalid path or node exists";
if (!parentNode) {
gError = "Invalid path";
return false;
}
auto directory = std::make_shared<Directory>();
if (!parentNode->attachNode(path.getFilename(), directory)) {
gError = "File or link with such name already exists";
return false;
}
directory->mParent = parentNode;
return true;
}
@ -42,15 +82,20 @@ bool FileSystem::makeFile(const Path& path) {
return false;
}
Node* parentNode = path.isAbsolute() ? root : currentDirectory;
auto parentNode = getNode(path, true);
auto newFile = new Node();
if (!parentNode->attachNode(path.getParentChain(), path.getFilename(), newFile)) {
delete newFile;
if (!parentNode) {
gError = "Invalid path";
return false;
}
auto newFile = std::make_shared<Node>();
if (!parentNode->attachNode(path.getFilename(), newFile)) {
gError = "Directory with such name already exists";
return false;
}
newFile->mParent = parentNode;
return true;
}
@ -60,11 +105,16 @@ bool FileSystem::removeDirectory(const Path& path, bool recursively) {
return false;
}
Node* parentNode = path.isAbsolute() ? root : currentDirectory;
auto parentNode = getNode(path, true);
auto existingNode = parentNode->findNode(path.getChain());
if (!parentNode) {
gError = "Invalid path";
return false;
}
auto existingNode = parentNode->findNode(path.getFilename());
if (!existingNode) {
gError = "Cant remove, such node doesnt exists";
gError = "Directory with such name does not exist";
return false;
}
@ -83,129 +133,8 @@ bool FileSystem::removeDirectory(const Path& path, bool recursively) {
return false;
}
if (!parentNode->detachNode(path.getParentChain(), path.getFilename())) {
gError = "Can not detach node";
return false;
}
delete existingNode;
return true;
}
bool FileSystem::copyNode(const Path& source, const Path& target) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
Node* workingDirectorySource = source.isAbsolute() ? root : currentDirectory;
Node* workingDirectoryTarget = target.isAbsolute() ? root : currentDirectory;
auto sourceNode = workingDirectorySource->findNode(source.getChain());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
auto targetNode = workingDirectoryTarget->findNode(target.getChain());
if (!targetNode) {
gError = "Invalid target directory";
return false;
}
Key key = source.getFilename();
if (targetNode->findNode(key)) {
// gError = "Node with such name already exists in the target directory";
// return false;
key += "_copy";
}
Node* clonedNode = sourceNode->clone();
if (!targetNode->attachNode(key, clonedNode)) {
delete clonedNode;
return false;
}
return true;
}
bool FileSystem::moveNode(const Path &source, const Path &target) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
Node* workingDirectorySource = source.isAbsolute() ? root : currentDirectory;
Node* workingDirectoryTarget = target.isAbsolute() ? root : currentDirectory;
auto sourceParentNode = workingDirectorySource->findNode(source.getParentChain());
if (!sourceParentNode) {
gError = "Invalid source path";
return false;
}
auto sourceNode = sourceParentNode->findNode(source.getFilename());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
auto targetNode = workingDirectoryTarget->findNode(target.getChain());
if (!targetNode) {
gError = "Invalid target directory";
return false;
}
const Key& key = source.getFilename();
if (sourceParentNode->isHard()) {
gError = "Node contains incoming hard links";
return false;
}
if (!targetNode->attachNode(key, sourceNode)) {
return false;
}
assert(sourceParentNode->detachNode(key));
return true;
}
bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
Node* workingDirectorySource = source.isAbsolute() ? root : currentDirectory;
Node* workingDirectoryTarget = target.isAbsolute() ? root : currentDirectory;
auto sourceNode = workingDirectorySource->findNode(source.getChain());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
if (sourceNode->isLink()) {
gError = "Link on link is not allowed";
return false;
}
auto targetNode = workingDirectoryTarget->findNode(target.getChain());
if (!targetNode || !targetNode->isDirectory()) {
gError = "Invalid target directory";
return false;
}
const Key& key = source.getFilename();
auto targetDirectory = (Directory*)targetNode;
auto newLink = new Link(sourceNode, !isDynamic);
if (!targetDirectory->attachNode(key, newLink)) {
delete newLink;
if (!parentNode->detachNode(path.getFilename())) {
gError = "Can not remove directory because it has hard references";
return false;
}
@ -218,48 +147,160 @@ bool FileSystem::removeFileOrLink(const Path &path) {
return false;
}
Node* parentDirectory = path.isAbsolute() ? root : currentDirectory;
auto parentNode = getNode(path, true);
auto existingNode = parentDirectory->findNode(path.getChain());
if (!existingNode) {
gError = "Cant remove, such node doesnt exists";
return false;
}
if (existingNode->isDirectory()) {
gError = "Path is a directory";
return false;
}
if (!parentDirectory->detachNode(path.getParentChain(), path.getFilename())) {
gError = "Can not remove node";
return false;
}
delete existingNode;
return true;
}
bool FileSystem::changeCurrent(const Path& path) {
if (path.isInvalid()) {
if (!parentNode) {
gError = "Invalid path";
return false;
}
auto node = path.isAbsolute() ? root->findNode(path.getChain(), 0) : currentDirectory->findNode(path.getChain(), 0);
if (!node || !node->isDirectory()) {
gError = "No such directory";
auto existingNode = parentNode->findNode(path.getFilename());
if (!existingNode) {
gError = "File or link with such name does not exist";
return false;
}
currentDirectory = node;
if (existingNode->isDirectory()) {
gError = "Path is not a file or a link";
return false;
}
if (!parentNode->detachNode(path.getFilename())) {
gError = "Can not remove file or link because it has hard references";
return false;
}
return true;
}
bool FileSystem::copyNode(const Path& source, const Path& target) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
auto parentNodeSource = getNode(source, true);
if (!parentNodeSource) {
gError = "Invalid source path";
return false;
}
auto parentNodeTarget = getNode(target, false);
if (!parentNodeTarget) {
gError = "Invalid target path";
return false;
}
auto sourceNode = parentNodeSource->findNode(source.getFilename());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
if (!parentNodeTarget->isDirectory()) {
gError = "Target path is not a directory";
return false;
}
Key key = source.getFilename();
while (parentNodeTarget->findNode(key)) {
// gError = "Node with such name already exists in the target directory";
// return false;
key += "_copy";
}
auto clonedNode = sourceNode->clone();
assert(parentNodeTarget->attachNode(key, clonedNode));
clonedNode->mParent = parentNodeTarget;
return true;
}
bool FileSystem::moveNode(const Path &source, const Path &target) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
auto parentNodeSource = getNode(source, true);
if (!parentNodeSource) {
gError = "Invalid source path";
return false;
}
auto parentNodeTarget = getNode(target, false);
if (!parentNodeTarget) {
gError = "Invalid target path";
return false;
}
auto sourceNode = parentNodeSource->findNode(source.getFilename());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
const Key& key = source.getFilename();
if (sourceNode->isHard()) {
gError = "Node contains incoming hard links";
return false;
}
if (!parentNodeTarget->attachNode(key, sourceNode)) {
gError = "Node with such name already exists";
return false;
}
sourceNode->mParent = parentNodeTarget;
assert(parentNodeSource->detachNode(key));
return true;
}
bool FileSystem::makeLink(const Path& source, const Path& target, bool isDynamic) {
if (source.getDepth() < 1 || source.isInvalid()) {
gError = "Invalid source path";
return false;
}
auto parentNodeSource = getNode(source, true);
if (!parentNodeSource) {
gError = "Invalid source path";
return false;
}
auto parentNodeTarget = getNode(target, false);
if (!parentNodeTarget) {
gError = "Invalid target path";
return false;
}
auto sourceNode = parentNodeSource->findNode(source.getFilename());
if (!sourceNode) {
gError = "Invalid source path";
return false;
}
if (sourceNode->isLink()) {
gError = "Link on link is not allowed";
return false;
}
const Key& key = source.getFilename();
auto newLink = std::shared_ptr<Node>(new Link(sourceNode, !isDynamic));
if (!parentNodeTarget->attachNode(key, newLink)) {
gError = "Node with such name already exists";
return false;
}
newLink->mParent = parentNodeTarget;
return true;
}
void FileSystem::log() const {
std::stringstream ss;
std::vector<const Node*> currentPath;
std::vector<std::shared_ptr<Node>> currentPath;
root->getNodeStraightPath(currentDirectory, currentPath);
std::reverse(currentPath.begin(), currentPath.end());
@ -277,9 +318,9 @@ const std::string& FileSystem::getLastError() {
return gError;
}
bool FileSystem::isPathContainsCurrent(Node* node) {
std::vector<const Node*> currentPath;
std::vector<const Node*> path;
bool FileSystem::isPathContainsCurrent(const std::shared_ptr<Node>& node) {
std::vector<std::shared_ptr<Node>> currentPath;
std::vector<std::shared_ptr<Node>> path;
root->getNodeStraightPath(currentDirectory, currentPath);
root->getNodeStraightPath(node, path);

View file

@ -5,31 +5,31 @@
#include <cassert>
#include <algorithm>
Link::Link(Node* target, bool isHard) {
Link::Link(const std::shared_ptr<Node>& target, bool isHard) {
mIsHard = isHard;
mLink = target;
if (mIsHard) {
target->mIncomingHardLinks.push_back(this);
} else {
target->mIncomingDynamicLinks.push_back(this);
}
// if (mIsHard) {
// target->mIncomingHardLinks.push_back(std::shared_ptr<Link>(this));
// } else {
// target->mIncomingDynamicLinks.push_back(std::shared_ptr<Link>(this));
//}
}
Link::Link(const Link &node) : Node(node) {
mLink = node.mLink;
mIsHard = node.mIsHard;
assert(mLink);
if (mIsHard) {
mLink->mIncomingHardLinks.push_back(this);
} else {
mLink->mIncomingDynamicLinks.push_back(this);
}
// assert(mLink);
// if (mIsHard) {
// mLink->mIncomingHardLinks.push_back(std::shared_ptr<Link>(this));
// } else {
// mLink->mIncomingDynamicLinks.push_back(std::shared_ptr<Link>(this));
// }
}
Link *Link::clone() const {
return new Link(*this);
std::shared_ptr<Node> Link::clone() const {
return std::make_shared<Link>(*this);
}
Link::~Link() {
@ -40,7 +40,7 @@ Link::~Link() {
// mLink = nullptr;
}
Node *Link::getLink() const {
std::shared_ptr<Node> Link::getLink() const {
return mLink;
}
@ -48,13 +48,13 @@ bool Link::isHard() const {
return mIsHard;
}
Node* Link::getTarget() {
return getLink();
std::shared_ptr<Node> Link::getTarget() {
return getLink();
}
Node* Link::findNode(const std::vector<Key>& path, ui32 currentDepth) {
std::shared_ptr<Node> Link::findNode(const std::vector<Key>& path, ui32 currentDepth) {
if (path.size() == currentDepth) {
return this;
return std::shared_ptr<Node>(this);
}
assert(mLink);
return mLink->findNode(path, currentDepth + 1);
@ -64,7 +64,7 @@ Node* Link::findNode(const std::vector<Key>& path, ui32 currentDepth) {
void Link::dumpUtil(std::stringstream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) {
indent(ss, currentDepth, indents);
ss << key << (isHard() ? " hlink[/" : " dlink[/");
std::vector<const Node*> path;
std::vector<std::shared_ptr<Node>> path;
getNodeStraightPath(getLink(), path);
std::reverse(path.begin(), path.end());
for (auto tmp : path)

View file

@ -1,6 +1,7 @@
#include "Node.hpp"
#include <memory>
#include <sstream>
#include <cassert>
#include <algorithm>
@ -18,8 +19,8 @@ Node::~Node() {
//
}
Node *Node::clone() const {
return new Node(*this);
std::shared_ptr<Node> Node::clone() const {
return std::make_shared<Node>(*this);
}
ui32 Node::getMaxDepth() const {
@ -28,17 +29,19 @@ ui32 Node::getMaxDepth() const {
return maxDepth;
}
Node* Node::findNode(const std::vector<Key>& path, ui32 currentDepth) {
if (path.size() - 1 == currentDepth) {
return this;
}
std::shared_ptr<Node> Node::findNode(const std::vector<Key>& path, ui32 currentDepth) {
assert(false);
return nullptr;
}
void Node::getNodeStraightPath(Node* node, std::vector<const Node*>& path) const {
std::shared_ptr<Node> Node::getTarget() {
return nullptr;
}
void Node::getNodeStraightPath(const std::shared_ptr<Node>& node, std::vector<std::shared_ptr<Node>>& path) const {
if (!node) return;
path.push_back(node);
getNodeStraightPath(node->mParent, path);
getNodeStraightPath(node->mParent.lock(), path);
}
void Node::dump(std::stringstream& ss) {