forked from AssemblyScript/assemblyscript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpath.ts
More file actions
128 lines (116 loc) · 3.24 KB
/
path.ts
File metadata and controls
128 lines (116 loc) · 3.24 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
/**
* @fileoverview Various file path utility.
* @license Apache-2.0
*/
import {
CharCode
} from "./text";
import {
PATH_DELIMITER
} from "../common";
const separator = CharCode.SLASH;
/**
* Normalizes the specified path, removing interior placeholders.
* Expects a posix-compatible relative path (not Windows compatible).
*/
export function normalizePath(path: string): string {
var pos = 0;
var len = path.length;
// trim leading './'
while (pos + 1 < len &&
path.charCodeAt(pos) == CharCode.DOT &&
path.charCodeAt(pos + 1) == separator
) {
pos += 2;
}
if (pos > 0 || len < path.length) {
path = path.substring(pos, len);
len -= pos;
pos = 0;
}
var atEnd: bool;
while (pos + 1 < len) {
atEnd = false;
// we are only interested in '/.' sequences ...
if (
path.charCodeAt(pos) == separator &&
path.charCodeAt(pos + 1) == CharCode.DOT
) {
// '/.' ( '/' | $ )
atEnd = pos + 2 == len;
if (atEnd ||
pos + 2 < len &&
path.charCodeAt(pos + 2) == separator
) {
path = atEnd
? path.substring(0, pos)
: path.substring(0, pos) + path.substring(pos + 2);
len -= 2;
continue;
}
// '/.' ( './' | '.' $ )
atEnd = pos + 3 == len;
if (atEnd && path.charCodeAt(pos + 2) == CharCode.DOT ||
pos + 3 < len &&
path.charCodeAt(pos + 2) == CharCode.DOT &&
path.charCodeAt(pos + 3) == separator
) {
// find preceeding '/'
let ipos = pos;
while (--ipos >= 0) {
if (path.charCodeAt(ipos) == separator) {
if (pos - ipos != 3 ||
path.charCodeAt(ipos + 1) != CharCode.DOT ||
path.charCodeAt(ipos + 2) != CharCode.DOT
) { // exclude '..' itself
path = atEnd
? path.substring(0, ipos)
: path.substring(0, ipos) + path.substring(pos + 3);
len -= pos + 3 - ipos;
pos = ipos - 1; // incremented again at end of loop
}
break;
}
}
// if there's no preceeding '/', trim start if non-empty
if (ipos < 0 && pos > 0) {
if (pos != 2 ||
path.charCodeAt(0) != CharCode.DOT ||
path.charCodeAt(1) != CharCode.DOT
) { // exclude '..' itself
path = path.substring(pos + 4);
len = path.length;
continue;
}
}
}
}
pos++;
}
return len > 0 ? path : ".";
}
/** Resolves the specified path relative to the specified origin. */
export function resolvePath(normalizedPath: string, origin: string): string {
if (normalizedPath.startsWith("std/")) {
return normalizedPath;
}
return normalizePath(
dirname(origin) + PATH_DELIMITER + normalizedPath
);
}
/** Obtains the directory portion of a normalized path. */
export function dirname(normalizedPath: string): string {
var pos = normalizedPath.length;
if (pos <= 1) {
if (pos == 0) return ".";
if (normalizedPath.charCodeAt(0) == separator) {
return normalizedPath;
}
}
while (--pos > 0) {
if (normalizedPath.charCodeAt(pos) == separator) {
return normalizedPath.substring(0, pos);
}
}
return ".";
}