-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathfilesystem.js
89 lines (78 loc) · 1.66 KB
/
filesystem.js
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
class File {
constructor(name, size) {
this.name = name;
this._size = size;
}
size() {
return this._size;
}
}
class Dir {
constructor(name, parentDir) {
this.isDir = true;
this.parentDir = parentDir;
this.name = name;
this.contents = [];
}
size(ignore) {
if (ignore === this) {
return 0;
}
return this.contents.map((v) => v.size(ignore)).reduce((a, b) => a + b, 0);
}
}
class Filesystem {
constructor(instructions) {
this.rootDir = new Dir('/', null);
this.build(instructions);
}
size(ignore) {
return this.rootDir.size(ignore);
}
build(instructions) {
let currentDir = this.rootDir;
for (let line of instructions) {
if (line.startsWith('$ cd')) {
const [, dir] = /\$ cd (.+)$/.exec(line);
if (dir === '/') {
currentDir = this.rootDir;
} else if (dir === '..') {
currentDir = currentDir.parentDir;
} else {
currentDir = currentDir.contents.find((v) => v.isDir && v.name === dir);
}
} else if (line.startsWith('$ ls')) {
continue;
} else {
// In a `ls` output
if (line.startsWith('dir ')) {
const [, dirName] = /dir (.+)$/.exec(line);
const newDir = new Dir(dirName, currentDir);
currentDir.contents.push(newDir);
} else {
// file
let [, size, fileName] = /(\d+) (.+)$/.exec(line);
size = parseInt(size, 10);
const newFile = new File(fileName, size);
currentDir.contents.push(newFile);
}
}
}
}
static *walk(dir) {
for (let c of dir.contents) {
yield c;
if (c.isDir) {
yield* Filesystem.walk(c);
}
}
}
*[Symbol.iterator]() {
yield* Filesystem.walk(this.rootDir);
}
}
module.exports = {
File,
Dir,
Filesystem,
};