use smart pointers
This commit is contained in:
parent
cd593ab024
commit
8e150b52c3
8 changed files with 282 additions and 258 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
12
inc/Link.hpp
12
inc/Link.hpp
|
|
@ -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;
|
||||
};
|
||||
22
inc/Node.hpp
22
inc/Node.hpp
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
40
src/Link.cpp
40
src/Link.cpp
|
|
@ -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)
|
||||
|
|
|
|||
19
src/Node.cpp
19
src/Node.cpp
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue