-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPathTree.ts
More file actions
84 lines (66 loc) · 2.29 KB
/
PathTree.ts
File metadata and controls
84 lines (66 loc) · 2.29 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
import { IPathNode } from "./IPathNode";
import { PathNode } from "./PathNode";
export type PathCapture = Map<string, string>;
type PathParts = string[];
export class PathTree {
_root : IPathNode = new PathNode("");
insert(path: string) {
const parts = PathTree.getParts(path);
let node = this._root;
for (const word of parts) {
if (word[0] === ':') {
let wildcard = node.wildcard;
const param = word.substr(1);
for (let parent: IPathNode | null = node; parent !== null; parent = parent.parent) {
if (parent.isWildcard && (param === parent.key)) {
throw new Error("Cannot have the same wildcard on different levels");
}
}
if (!wildcard) {
wildcard = new PathNode(param);
node.addChild(wildcard, true);
}
if (wildcard.key !== param) {
throw new Error("Wildcard parameter is not matching");
}
node = wildcard;
} else {
let child = node.getChild(word);
if (!child) {
child = new PathNode(word);
node.addChild(child, false);
}
node = child;
}
}
node.isLeaf = true;
return node;
}
find(path: string, capture: PathCapture | null): IPathNode | null {
const parts = PathTree.getParts(path);
let node = this._root;
for (const word of parts) {
const child = node.getChild(word);
if (child) {
node = child;
} else if (node.wildcard) {
node = node.wildcard;
if (capture) {
capture.set(node.key, word);
}
} else {
return null;
}
}
return node.isLeaf ? node : null;
}
contains(url: string): boolean {
return this.find(url, null) !== null;
}
private static getParts(path: string): PathParts {
if (path[0] !== '/') {
throw new Error("Path needs a leading slash");
}
return path.substr(1).split("/");
}
}