This commit is contained in:
IlyaShurupov 2024-03-31 12:00:19 +03:00
parent d154f8f1a6
commit 1efe2c0a08
13 changed files with 114 additions and 90 deletions

View file

@ -25,9 +25,7 @@ target_link_libraries(TestFSE ${PROJECT_NAME} UnitTest++)
add_executable(TestConsistency "test/TestConsistency.cpp")
target_link_libraries(TestConsistency ${PROJECT_NAME} UnitTest++)
file(COPY "test/consistency_state" DESTINATION "${CMAKE_BINARY_DIR}/")
file(COPY "test/consistency_commands" DESTINATION "${CMAKE_BINARY_DIR}/")
file(COPY "test/checkConsistency" DESTINATION "${CMAKE_BINARY_DIR}/")
file(COPY "test/consistency" DESTINATION "${CMAKE_BINARY_DIR}/")
add_test(NAME UnitTests COMMAND valgrind ./TestFSE)
add_test(NAME TestConsistency COMMAND ./checkConsistency)
add_test(NAME TestConsistency COMMAND ./consistency/check)

View file

@ -10,16 +10,16 @@ public:
Directory(const Directory& node);
~Directory() override;
NodeType getType() const override { return DIRECTORY; }
[[nodiscard]] NodeType getType() const override { return DIRECTORY; }
[[nodiscard]] std::shared_ptr<Node> clone() const override;
bool detachNode(const Key& key) override;
bool attachNode(const Key &newKey, std::shared_ptr<Node> newNode) override;
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0) override;
bool attachNode(const Key &newKey, const std::shared_ptr<Node>& newNode) override;
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth) override;
std::shared_ptr<Node> findNode(const Key& path) override;
[[nodiscard]] ui64 size() const override;
void clearFlags(std::shared_ptr<Node>& directory) override;
bool isHardNode() const override;
[[nodiscard]] bool isHardNode() const override;
void removeIncomingDynamicLinks() override;
void removeOutgoingLinks() override;
@ -34,7 +34,7 @@ public:
}
private:
void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const;
void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const override;
void dumpUtil(std::ostream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) override;
public:

View file

@ -5,12 +5,10 @@
#include <sstream>
// use single vector for incoming links
// move link nodes from link to node class or vise versa
// clean-ups
// links have unique names
// copy operator exit if exists, do not rename
// in subtree links should be in-tree after copy operation
// links have unique names
// use single vector for incoming links
// clean-ups
// update link if exists
class FileSystem {
@ -29,7 +27,7 @@ public:
std::ostream& dump(std::ostream& stream) const;
void log() const;
ui64 size() const;
[[nodiscard]] ui64 size() const;
static const std::string& getLastError();

View file

@ -8,14 +8,13 @@ public:
Link(const Link& node);
~Link() override;
NodeType getType() const override { return LINK; }
[[nodiscard]] NodeType getType() const override { return LINK; }
[[nodiscard]] std::shared_ptr<Node> clone() const override;
[[nodiscard]] std::shared_ptr<Node> getLink() const;
[[nodiscard]] bool isHardLink() const;
std::shared_ptr<Node> getTarget() override;
// link on link is not allowed, so no inf looping here
std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth) override;
void dumpUtil(std::ostream& ss, const Key& key, ui32 currentDepth, std::vector<bool>& indents) override;

View file

@ -1,10 +1,5 @@
#pragma once
typedef unsigned long long ui64;
typedef unsigned long ui32;
typedef long long i64;
typedef long i32;
#include <map>
#include <utility>
#include <vector>
@ -12,6 +7,9 @@ typedef long i32;
#include <cassert>
#include <memory>
typedef unsigned long long ui64;
typedef unsigned long ui32;
class Link;
class Directory;
@ -26,32 +24,44 @@ public:
Node(const Node& node);
virtual ~Node();
virtual NodeType getType() const { return FILE; }
virtual std::shared_ptr<Node> clone() const;
virtual bool detachNode(const Key& key) { return false; }
virtual bool attachNode(const Key &newKey, std::shared_ptr<Node> newNode) { return false; }
virtual void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const {}
virtual void dumpUtil(std::ostream& stream, const Key& key, ui32 currentDepth, std::vector<bool>& indents);
virtual ui64 size() const { return 0; }
virtual std::shared_ptr<Node> getTarget();
virtual std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth = 0);
virtual std::shared_ptr<Node> findNode(const Key& path) { return nullptr; }
// modification
virtual bool detachNode(const Key& key);
virtual bool attachNode(const Key &newKey, const std::shared_ptr<Node>& newNode);
virtual std::shared_ptr<Node> findNode(const std::vector<Key>& path, ui32 currentDepth);
virtual std::shared_ptr<Node> findNode(const Key& path);
[[nodiscard]] virtual std::shared_ptr<Node> clone() const;
virtual void clearFlags(std::shared_ptr<Node>& directory);
virtual bool isHardNode() const;
virtual void removeIncomingDynamicLinks();
virtual void removeOutgoingLinks() {}
ui32 getMaxDepth() const;
// logging
std::ostream& dump(std::ostream &stream);
void getNodeStraightPath(const std::shared_ptr<Node>& node, std::vector<std::shared_ptr<Node>>& path) const;
bool empty() const { return !size(); }
virtual void dumpUtil(std::ostream& stream, const Key& key, ui32 currentDepth, std::vector<bool>& indents);
static void indent(std::ostream& ss, ui32 depth, std::vector<bool>& indents);
// link support
virtual void clearFlags(std::shared_ptr<Node>& directory);
virtual void removeIncomingDynamicLinks();
virtual void removeOutgoingLinks();
virtual std::shared_ptr<Node> getTarget();
[[nodiscard]] virtual bool isHardNode() const;
// general queries
[[nodiscard]] virtual NodeType getType() const;
[[nodiscard]] virtual ui64 size() const;
[[nodiscard]] ui32 getMaxDepth() const;
virtual void getMaxDepthUtil(ui32 depth, ui32& maxDepth) const;
void getNodeStraightPath(const std::shared_ptr<Node>& node, std::vector<std::shared_ptr<Node>>& path) const;
[[nodiscard]] bool empty() const;
public:
// TODO : remove key duplication
Key mKey;
// to mark currently working subtree recursively.
std::weak_ptr<Node> mWorkingNodeFlag;
// to trace path from current node to the root
std::weak_ptr<Node> mParent;
// to remove incoming links
std::vector<std::weak_ptr<Link>> mIncomingHardLinks;
std::vector<std::weak_ptr<Link>> mIncomingDynamicLinks;
};

View file

@ -3,25 +3,26 @@
#include <vector>
#include <string>
typedef unsigned long long ui64;
extern std::vector<char> transitions;
void initializeTransitions();
class Path {
public:
Path() = default;
Path(const std::string& path);
explicit Path(const std::string& path);
void set(const std::string& path);
const std::string& operator[](int idx) const;
bool isValid() const;
bool isInvalid() const;
bool isAbsolute() const;
int getDepth() const;
[[nodiscard]] bool isInvalid() const;
[[nodiscard]] bool isAbsolute() const;
[[nodiscard]] ui64 getDepth() const;
const std::vector<std::string>& getChain() const;
std::vector<std::string> getParentChain() const;
const std::string& getFilename() const;
[[nodiscard]] const std::vector<std::string>& getChain() const;
[[nodiscard]] std::vector<std::string> getParentChain() const;
[[nodiscard]] const std::string& getFilename() const;
private:
std::vector<std::string> mChain;

View file

@ -2,16 +2,13 @@
#include "Directory.hpp"
#include "Link.hpp"
#include <sstream>
#include <algorithm>
#include <iostream>
Directory::Directory() = default;
Directory::~Directory() = default;
Directory::~Directory() {
}
bool Directory::attachNode(const Key &newKey, std::shared_ptr<Node> newNode) {
bool Directory::attachNode(const Key &newKey, const std::shared_ptr<Node>& newNode) {
assert(mMembers.find(newKey) == mMembers.end());
mMembers.insert({ newKey, newNode });
newNode->mKey = newKey;

View file

@ -22,7 +22,7 @@ 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);
auto parentNode = pathChain.empty() ? currentNode : currentNode->findNode(pathChain, 0);
if (parent && parentNode) {
while (parentNode->getTarget()) {
@ -299,7 +299,7 @@ bool FileSystem::copyNode(const Path& source, const Path& target) {
if (!sourceNode) {
gError = "Invalid source path";
return false;
};
}
if (parentNodeTarget->getType() != Node::DIRECTORY) {
gError = "Target path is not a directory";

View file

@ -15,7 +15,7 @@ Interpreter::Interpreter() {
"change working directory",
1,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.changeCurrent(args[1]);
return filesystem.changeCurrent(Path(args[1]));
}
};
@ -23,7 +23,7 @@ Interpreter::Interpreter() {
"create directory",
1,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.makeDirectory(args[1]);
return filesystem.makeDirectory(Path(args[1]));
}
};
@ -31,7 +31,7 @@ Interpreter::Interpreter() {
"remove directory",
1,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.removeDirectory(args[1], false);
return filesystem.removeDirectory(Path(args[1]), false);
}
};
@ -39,7 +39,7 @@ Interpreter::Interpreter() {
"remove directory recursively",
1,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.removeDirectory(args[1], true);
return filesystem.removeDirectory(Path(args[1]), true);
}
};
@ -47,7 +47,7 @@ Interpreter::Interpreter() {
"make file",
1,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.makeFile(args[1]);
return filesystem.makeFile(Path(args[1]));
}
};
@ -55,7 +55,7 @@ Interpreter::Interpreter() {
"remove file or link",
1,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.removeFileOrLink(args[1]);
return filesystem.removeFileOrLink(Path(args[1]));
}
};
@ -63,7 +63,7 @@ Interpreter::Interpreter() {
"recursive copy of a node",
2,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.copyNode(args[1], args[2]);
return filesystem.copyNode(Path(args[1]), Path(args[2]));
}
};
@ -71,7 +71,7 @@ Interpreter::Interpreter() {
"move node",
2,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.moveNode(args[1], args[2]);
return filesystem.moveNode(Path(args[1]), Path(args[2]));
}
};
@ -79,7 +79,7 @@ Interpreter::Interpreter() {
"make hard link",
2,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.makeLink(args[1], args[2], false);
return filesystem.makeLink(Path(args[1]), Path(args[2]), false);
}
};
@ -87,7 +87,7 @@ Interpreter::Interpreter() {
"make dynamic link",
2,
[](FileSystem& filesystem, const std::vector<std::string>& args){
return filesystem.makeLink(args[1], args[2], true);
return filesystem.makeLink(Path(args[1]), Path(args[2]), true);
}
};
}

View file

@ -1,7 +1,6 @@
#include "Link.hpp"
#include <sstream>
#include <cassert>
#include <algorithm>
#include <iostream>
@ -63,6 +62,7 @@ std::shared_ptr<Node> Link::getTarget() {
std::shared_ptr<Node> Link::findNode(const std::vector<Key>& path, ui32 currentDepth) {
assert(path.size() != currentDepth);
// link on link is not allowed, so no inf looping here
return getLink()->findNode(path, currentDepth);
}

View file

@ -3,7 +3,6 @@
#include "Link.hpp"
#include <memory>
#include <sstream>
#include <cassert>
#include <algorithm>
#include <iostream>
@ -25,7 +24,6 @@ ui32 Node::getMaxDepth() const {
}
std::shared_ptr<Node> Node::findNode(const std::vector<Key>& path, ui32 currentDepth) {
// assert(false);
return nullptr;
}
@ -94,4 +92,32 @@ void Node::indent(std::ostream& ss, ui32 depth, std::vector<bool>& indents) {
ss << (indents[i] ? " |" : " ");
}
ss << " |_";
}
}
void Node::removeOutgoingLinks() {}
bool Node::detachNode(const Key &key) {
return false;
}
bool Node::attachNode(const Key &newKey, const std::shared_ptr<Node> &newNode) {
return false;
}
std::shared_ptr<Node> Node::findNode(const Key &path) {
return nullptr;
}
bool Node::empty() const {
return !size();
}
void Node::getMaxDepthUtil(ui32 depth, ui32 &maxDepth) const {}
Node::NodeType Node::getType() const {
return Node::FILE;
}
ui64 Node::size() const {
return 0;
}

View file

@ -20,10 +20,6 @@ Path::Path(const std::string& path) {
set(path);
}
bool Path::isValid() const {
return mIsValid;
}
bool Path::isInvalid() const {
return !mIsValid;
}
@ -32,7 +28,7 @@ bool Path::isAbsolute() const {
return mAbsolute;
}
int Path::getDepth() const {
ui64 Path::getDepth() const {
return mChain.size();
}
@ -62,25 +58,24 @@ void Path::set(const std::string& path) {
std::string lowercasePath = path;
const auto drivePrefixSize = std::strlen(drivePrefix);
if (drivePrefixSize) {
if ((lowercasePath.size() >= drivePrefixSize) && (std::memcmp(lowercasePath.c_str(), drivePrefix, drivePrefixSize) == 0)) {
lowercasePath.erase(0, drivePrefixSize);
mAbsolute = true;
if (lowercasePath.empty()) lowercasePath = "/";
else if (lowercasePath[0] != '/') {
mIsValid = false;
return;
}
} else {
if (lowercasePath[0] == '/') {
mIsValid = false;
return;
}
assert(drivePrefixSize);
if ((lowercasePath.size() >= drivePrefixSize) && (std::memcmp(lowercasePath.c_str(), drivePrefix, drivePrefixSize) == 0)) {
lowercasePath.erase(0, drivePrefixSize);
mAbsolute = true;
if (lowercasePath.empty()) lowercasePath = "/";
else if (lowercasePath[0] != '/') {
mIsValid = false;
return;
}
} else {
mAbsolute = path.front() == '/';
if (lowercasePath[0] == '/') {
mIsValid = false;
return;
}
}
mDirectory = path.back() == '/';
mChain.clear();

View file

@ -5,7 +5,7 @@
// generates and saves final state to check if there are any logic changes to the code
int main(int argc, char* argv[]) {
int main(int, char*[]) {
Interpreter interpreter;
interpreter.logType = Interpreter::NONE;