-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
173 lines (152 loc) · 5.7 KB
/
main.cpp
File metadata and controls
173 lines (152 loc) · 5.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
* This is the starting project for the Advanced Programming assessment - 2023-4
* This project enumerates just the directory specified and does not descend into subdirectories
*/
#include <crtdbg.h>
#include <stdlib.h>
#include <iostream>
#include <chrono>
#include <filesystem> // file system needs cpp standard 17 or above. This is enabled in this project, but if you recreated from scratch, set -std=c++17 flags
#include "Item.h"
#include "Folder.h"
#include "File.h"
#include <vector>
#include <algorithm>
#include "Commands.h"
using namespace std;
// function prototype of a helper method to convert timestamps
const tm convertTime(const filesystem::file_time_type& timestamp);
const vector<string> UserInput();
void processDirectory(const filesystem::path& path, Folder* parent);
// C++ entry point
int main()
{
#ifdef _DEBUG
// make sure we are checking for memory leaks when the application ends, but only in the _DEBUG variant
_onexit(_CrtDumpMemoryLeaks);
#endif
const char* path="."; // this is just the local path, so the project folder
string currentPath = "FFS:";
std::unique_ptr<Folder> root = std::make_unique<Folder>(path, convertTime(filesystem::last_write_time(path)), 0);
Folder* current = root.get();
processDirectory(path, root.get());
while (true) {
cout << currentPath << ">";
vector<string> input = UserInput();
if (input.size() == 0) {
// just ignore empty input and restart the while loop
continue;
}
if (input[0] == "cd") {
if (input[1] == "..") {
// Root is the only folder that is created without replacing the parent nullptr
// This will stop trying to move to the directory above root
if (current->getParent() != nullptr) {
current = current->getParent();
// Update the current path
currentPath = filesystem::path(currentPath).parent_path().string();
}
else {
std::cout << "Already at root!\n";
}
}
else {
auto& contents = current->getContents();
auto it = std::find_if(contents.begin(), contents.end(), [&](Item* x) {
Folder* folder = dynamic_cast<Folder*>(x);
if (folder) {
// Passing every character by reference and ensuring it is set to lowercase
// This allows for case insensitive directory names, like in cmd
string folderName = folder->getName();
for (char& ch : folderName) ch = ::tolower(ch);
string inputName = input[1];
for (char& ch : inputName) ch = ::tolower(ch);
return folderName == inputName;
}
return false;
});
// If the directory was found, update 'current'
if (it != contents.end()) {
current = dynamic_cast<Folder*>(*it);
currentPath = currentPath + "\\" + current->getName();
}
else {
std::cout << "Directory cannot be found\n";
}
}
}
if (input[0] == "dir"){
Commands::showDirectory(current);
}
if (input[0] == "sortsize") {
vector<Item*>& contents = current->editContents();
Commands::sortSize(contents, input);
}
if (input[0] == "sortname") {
vector<Item*>& contents = current->editContents();
Commands::sortName(contents, input);
}
if (input[0] == "mkfile") {
vector<Item*>& contents = current->editContents();
Commands::createFile(contents, input);
}
if (input[0] == "mkdir") {
vector<Item*>& contents = current->editContents();
Commands::createFolder(contents, input, current);
}
if (input[0] == "del") {
Commands::deleteItem(current, input);
}
if (input[0] == "exit")
{
cout << "Application will now close";
return 0;
}
}
return 0;
}
// we need to do a little conversion between what the filesystem returns for time stamps and something usable
// just use this function and don't worry about how it works
const tm convertTime(const filesystem::file_time_type& timestamp)
{
using namespace chrono; // just for this function, use chrono to save us prefixing chrono:: everywhere
system_clock::time_point delta=time_point_cast<system_clock::duration>(timestamp-filesystem::file_time_type::clock::now()+system_clock::now());
time_t conversion=system_clock::to_time_t(delta);
tm result;
localtime_s(&result, &conversion);
return result;
}
const vector<string> UserInput() {
// rename and try replace with regex command
vector<string> input;
string command;
getline(cin, command);
istringstream iss(command);
string word;
while(getline(iss, word, ' '))
{
input.push_back(word);
}
return input;
}
void processDirectory(const filesystem::path& path, Folder* parent)
{
for (const auto& item : filesystem::directory_iterator(path))
{
// these variables were brought out the if/else as it is repeated in both
string name = item.path().filename().string();
tm timestamp = convertTime(item.last_write_time());
if (item.is_directory())
{
Folder* folder = new Folder(name, timestamp, 0, parent);
parent->addItem(folder);
processDirectory(item.path(), folder); // Pass the new Folder as the parent for the recursive call
}
else
{
__int64 filesize = item.file_size();
File* file = new File(name, timestamp, filesize);
parent->addItem(file);
}
}
}