Skip to content

Commit 4ca3350

Browse files
committed
---
yaml --- r: 27903 b: refs/heads/try c: 3e52a0a h: refs/heads/master i: 27901: c7cb857 27899: c1e3c0e 27895: 8dd6062 27887: b872216 27871: 651aa07 27839: 96b85ee 27775: 962ecb3 27647: 180fd6d v: v3
1 parent 4d6198b commit 4ca3350

File tree

2 files changed

+312
-1
lines changed

2 files changed

+312
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
5-
refs/heads/try: 19b8598c098630e4031e32046867aaca9681b4cf
5+
refs/heads/try: 3e52a0acdec93357806771eb04f0f479873a637b
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df

branches/try/src/libcore/path2.rs

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
extern mod std;
2+
3+
struct WindowsPath {
4+
host: option<~str>;
5+
device: option<~str>;
6+
is_absolute: bool;
7+
components: ~[~str];
8+
}
9+
10+
struct PosixPath {
11+
is_absolute: bool;
12+
components: ~[~str];
13+
}
14+
15+
trait Path {
16+
17+
static fn from_str((&str)) -> self;
18+
fn to_str() -> ~str;
19+
20+
fn dirname() -> ~str;
21+
fn filename() -> option<~str>;
22+
fn filestem() -> option<~str>;
23+
fn filetype() -> option<~str>;
24+
25+
fn with_dirname((&str)) -> self;
26+
fn with_filename((&str)) -> self;
27+
fn with_filestem((&str)) -> self;
28+
fn with_filetype((&str)) -> self;
29+
30+
fn push_components((&[~str])) -> self;
31+
fn pop_component() -> self;
32+
}
33+
34+
35+
impl WindowsPath : Path {
36+
37+
fn to_str() -> ~str {
38+
match self.filename() {
39+
none => self.dirname(),
40+
some(ref f) =>
41+
if (self.components.len() == 1 &&
42+
!self.is_absolute &&
43+
self.host == none &&
44+
self.device == none) {
45+
copy *f
46+
} else {
47+
self.dirname() + "\\" + *f
48+
}
49+
}
50+
}
51+
52+
static fn from_str(s: &str) -> WindowsPath {
53+
let host;
54+
let device;
55+
let rest;
56+
57+
match windows::extract_drive_prefix(s) {
58+
some((ref d, ref r)) => {
59+
host = none;
60+
device = some(copy *d);
61+
rest = copy *r;
62+
}
63+
none => {
64+
match windows::extract_unc_prefix(s) {
65+
some((ref h, ref r)) => {
66+
host = some(copy *h);
67+
device = none;
68+
rest = copy *r;
69+
}
70+
none => {
71+
host = none;
72+
device = none;
73+
rest = str::from_slice(s);
74+
}
75+
}
76+
}
77+
}
78+
79+
let mut components =
80+
str::split_nonempty(rest, |c| windows::is_sep(c as u8));
81+
let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0]));
82+
return WindowsPath { host: host,
83+
device: device,
84+
is_absolute: is_absolute,
85+
components: components }
86+
}
87+
88+
fn dirname() -> ~str {
89+
let mut s = ~"";
90+
match self.host {
91+
some(h) => { s += "\\\\"; s += h; }
92+
none => { }
93+
}
94+
match self.device {
95+
some(d) => { s += d; s += ":"; }
96+
none => { }
97+
}
98+
if self.is_absolute {
99+
s += "\\";
100+
}
101+
let mut d = copy self.components;
102+
if d.len() != 0 {
103+
vec::pop(d);
104+
}
105+
s += str::connect(d, "\\");
106+
if s.len() == 0 {
107+
s = ~".";
108+
}
109+
return s;
110+
}
111+
112+
fn filename() -> option<~str> {
113+
match self.components.len() {
114+
0 => none,
115+
1 => some(copy self.components[0]),
116+
n => some(copy self.components[n - 1])
117+
}
118+
}
119+
120+
fn filestem() -> option<~str> {
121+
match self.filename() {
122+
none => none,
123+
some(ref f) => {
124+
match str::rfind_char(*f, '.') {
125+
some(p) => some(f.slice(0, p)),
126+
none => some(copy *f)
127+
}
128+
}
129+
}
130+
}
131+
132+
fn filetype() -> option<~str> {
133+
match self.filename() {
134+
none => none,
135+
some(ref f) => {
136+
match str::rfind_char(*f, '.') {
137+
some(p) if p+1 < f.len() => some(f.slice(p+1, f.len())),
138+
_ => none
139+
}
140+
}
141+
}
142+
}
143+
144+
fn with_dirname(d: &str) -> WindowsPath {
145+
let dpath = from_str::<WindowsPath>(d);
146+
match self.filename() {
147+
some(ref f) => dpath.push_components(~[copy *f]),
148+
none => dpath
149+
}
150+
}
151+
152+
fn with_filename(f: &str) -> WindowsPath {
153+
assert ! str::any(f, |c| windows::is_sep(c as u8));
154+
self.dir_path().push_components(~[str::from_slice(f)])
155+
}
156+
157+
fn with_filestem(s: &str) -> WindowsPath {
158+
match self.filetype() {
159+
none => self.with_filename(s),
160+
some(ref t) =>
161+
self.with_filename(str::from_slice(s) + "." + *t)
162+
}
163+
}
164+
165+
fn with_filetype(t: &str) -> WindowsPath {
166+
let t = ~"." + str::from_slice(t);
167+
match self.filestem() {
168+
none => self.with_filename(t),
169+
some(ref s) =>
170+
self.with_filename(*s + t)
171+
}
172+
}
173+
174+
fn dir_path() -> WindowsPath {
175+
if self.components.len() != 0 {
176+
self.pop_component()
177+
} else {
178+
copy self
179+
}
180+
}
181+
182+
fn file_path() -> WindowsPath {
183+
let cs = match self.filename() {
184+
none => ~[],
185+
some(ref f) => ~[copy *f]
186+
};
187+
return WindowsPath { host: none,
188+
device: none,
189+
is_absolute: false,
190+
components: cs }
191+
}
192+
193+
fn push_components(cs: &[~str]) -> WindowsPath {
194+
return WindowsPath { components: self.components + cs, ..self }
195+
}
196+
197+
fn pop_component() -> WindowsPath {
198+
let mut cs = copy self.components;
199+
if cs.len() != 0 {
200+
vec::pop(cs);
201+
}
202+
return WindowsPath { components: cs, ..self }
203+
}
204+
}
205+
206+
// Various windows helpers, and tests for the impl.
207+
mod windows {
208+
209+
#[inline(always)]
210+
fn is_sep(u: u8) -> bool {
211+
u == '/' as u8 || u == '\\' as u8
212+
}
213+
214+
fn extract_unc_prefix(s: &str) -> option<(~str,~str)> {
215+
if (s.len() > 1 &&
216+
s[0] == '\\' as u8 &&
217+
s[1] == '\\' as u8) {
218+
let mut i = 2;
219+
while i < s.len() {
220+
if s[i] == '\\' as u8 {
221+
let pre = s.slice(2, i);
222+
let rest = s.slice(i, s.len());
223+
return some((pre, rest));
224+
}
225+
i += 1;
226+
}
227+
}
228+
none
229+
}
230+
231+
fn extract_drive_prefix(s: &str) -> option<(~str,~str)> {
232+
if (s.len() > 1 &&
233+
libc::isalpha(s[0] as libc::c_int) != 0 &&
234+
s[1] == ':' as u8) {
235+
let rest = if s.len() == 2 { ~"" } else { s.slice(2, s.len()) };
236+
return some((s.slice(0,1), rest));
237+
}
238+
none
239+
}
240+
241+
#[test]
242+
fn test_extract_unc_prefixes() {
243+
assert extract_unc_prefix("\\\\") == none;
244+
assert extract_unc_prefix("\\\\hi") == none;
245+
assert extract_unc_prefix("\\\\hi\\") == some((~"hi", ~"\\"));
246+
assert extract_unc_prefix("\\\\hi\\there") ==
247+
some((~"hi", ~"\\there"));
248+
assert extract_unc_prefix("\\\\hi\\there\\friends.txt") ==
249+
some((~"hi", ~"\\there\\friends.txt"));
250+
}
251+
252+
#[test]
253+
fn test_extract_drive_prefixes() {
254+
assert extract_drive_prefix("c") == none;
255+
assert extract_drive_prefix("c:") == some((~"c", ~""));
256+
assert extract_drive_prefix("d:") == some((~"d", ~""));
257+
assert extract_drive_prefix("z:") == some((~"z", ~""));
258+
assert extract_drive_prefix("c:\\hi") == some((~"c", ~"\\hi"));
259+
assert extract_drive_prefix("d:hi") == some((~"d", ~"hi"));
260+
assert extract_drive_prefix("c:hi\\there.txt") ==
261+
some((~"c", ~"hi\\there.txt"));
262+
assert extract_drive_prefix("c:\\hi\\there.txt") ==
263+
some((~"c", ~"\\hi\\there.txt"));
264+
}
265+
266+
#[test]
267+
fn test_windows_paths() {
268+
fn mk(s: &str) -> WindowsPath { from_str::<WindowsPath>(s) }
269+
fn t(wp: &WindowsPath, s: &str) {
270+
let ss = wp.to_str();
271+
let sss = str::from_slice(s);
272+
if (ss != sss) {
273+
debug!("got %s", ss);
274+
debug!("expected %s", sss);
275+
assert ss == sss;
276+
}
277+
}
278+
279+
t(&(mk("hi")), "hi");
280+
t(&(mk("hi/there")), "hi\\there");
281+
t(&(mk("hi/there.txt")), "hi\\there.txt");
282+
283+
t(&(mk("there.txt")
284+
.with_filetype("o")), "there.o");
285+
286+
t(&(mk("hi/there.txt")
287+
.with_filetype("o")), "hi\\there.o");
288+
289+
t(&(mk("hi/there.txt")
290+
.with_filetype("o")
291+
.with_dirname("c:\\program files A")),
292+
"c:\\program files A\\there.o");
293+
294+
t(&(mk("hi/there.txt")
295+
.with_filetype("o")
296+
.with_dirname("c:\\program files B\\")),
297+
"c:\\program files B\\there.o");
298+
299+
t(&(mk("hi/there.txt")
300+
.with_filetype("o")
301+
.with_dirname("c:\\program files C\\/")),
302+
"c:\\program files C\\there.o");
303+
304+
t(&(mk("c:\\program files (x86)\\rust")
305+
.push_components([~"lib", ~"thingy.dll"])
306+
.with_filename("librustc.dll")),
307+
"c:\\program files (x86)\\rust\\lib\\librustc.dll");
308+
309+
}
310+
311+
}

0 commit comments

Comments
 (0)