diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-08-20 13:14:19 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-08-20 13:59:47 -0700 |
| commit | 08441fca76084b97c21ead917e54ce6c66d5d012 (patch) | |
| tree | e25b4c236f9864a5e4657d3e0c3ae65e58849dcd | |
| parent | a14485b7fd1a8a268a456ee1b47d79b10ccac875 (diff) | |
| download | rust-08441fca76084b97c21ead917e54ce6c66d5d012.tar.gz rust-08441fca76084b97c21ead917e54ce6c66d5d012.zip | |
Add PosixPath to path2. Add path2 to core build. Add dot/dotdot-normalizing.
| -rw-r--r-- | src/libcore/core.rc | 1 | ||||
| -rw-r--r-- | src/libcore/path2.rs | 248 | ||||
| -rw-r--r-- | src/libcore/str.rs | 1 |
3 files changed, 241 insertions, 9 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc index cd87313c696..f3f1e6e9839 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -252,6 +252,7 @@ mod libc; mod os; #[warn(non_camel_case_types)] mod path; +mod path2; #[warn(non_camel_case_types)] mod rand; #[warn(non_camel_case_types)] diff --git a/src/libcore/path2.rs b/src/libcore/path2.rs index c6b25476b96..50996c7876b 100644 --- a/src/libcore/path2.rs +++ b/src/libcore/path2.rs @@ -1,4 +1,6 @@ -extern mod std; +// NB: transitionary, de-mode-ing. +#[forbid(deprecated_mode)]; +#[forbid(deprecated_pattern)]; struct WindowsPath { host: option<~str>; @@ -31,6 +33,148 @@ trait Path { fn pop_component() -> self; } +// FIXME (#3227): when default methods in traits are working, de-duplicate +// PosixPath and WindowsPath, most of their methods are common. + +impl PosixPath : Path { + fn to_str() -> ~str { + match self.filename() { + none => self.dirname(), + some(ref f) => + if (self.components.len() == 1 && + !self.is_absolute) { + copy *f + } else { + self.dirname() + "/" + *f + } + } + } + + static fn from_str(s: &str) -> PosixPath { + let mut components = str::split_nonempty(s, |c| c == '/'); + let is_absolute = (s.len() != 0 && s[0] == '/' as u8); + return PosixPath { is_absolute: is_absolute, + components: normalize(components) } + } + + fn dirname() -> ~str { + let mut s = ~""; + if self.is_absolute { + s += "/"; + } + let mut d = copy self.components; + if d.len() != 0 { + vec::pop(d); + } + s += str::connect(d, "/"); + if s.len() == 0 { + s = ~"."; + } + return s; + } + + fn filename() -> option<~str> { + match self.components.len() { + 0 => none, + n => some(copy self.components[n - 1]) + } + } + + fn filestem() -> option<~str> { + match self.filename() { + none => none, + some(ref f) => { + match str::rfind_char(*f, '.') { + some(p) => some(f.slice(0, p)), + none => some(copy *f) + } + } + } + } + + fn filetype() -> option<~str> { + match self.filename() { + none => none, + some(ref f) => { + match str::rfind_char(*f, '.') { + some(p) if p+1 < f.len() => some(f.slice(p+1, f.len())), + _ => none + } + } + } + } + + fn with_dirname(d: &str) -> PosixPath { + let dpath = from_str::<PosixPath>(d); + match self.filename() { + some(ref f) => dpath.push_components(~[copy *f]), + none => dpath + } + } + + fn with_filename(f: &str) -> PosixPath { + assert ! str::any(f, |c| windows::is_sep(c as u8)); + self.dir_path().push_components(~[str::from_slice(f)]) + } + + fn with_filestem(s: &str) -> PosixPath { + match self.filetype() { + none => self.with_filename(s), + some(ref t) => + self.with_filename(str::from_slice(s) + "." + *t) + } + } + + fn with_filetype(t: &str) -> PosixPath { + if t.len() == 0 { + match self.filestem() { + none => copy self, + some(s) => self.with_filename(s) + } + } else { + let t = ~"." + str::from_slice(t); + match self.filestem() { + none => self.with_filename(t), + some(ref s) => + self.with_filename(*s + t) + } + } + } + + fn dir_path() -> PosixPath { + if self.components.len() != 0 { + self.pop_component() + } else { + copy self + } + } + + fn file_path() -> PosixPath { + let cs = match self.filename() { + none => ~[], + some(ref f) => ~[copy *f] + }; + return PosixPath { is_absolute: false, + components: cs } + } + + fn push_components(cs: &[~str]) -> PosixPath { + return PosixPath { components: normalize(self.components + cs), + ..self } + } + + fn pop_component() -> PosixPath { + let mut cs = copy self.components; + if cs.len() != 0 { + vec::pop(cs); + } + return PosixPath { components: cs, ..self } + } + + + +} + impl WindowsPath : Path { @@ -82,7 +226,7 @@ impl WindowsPath : Path { return WindowsPath { host: host, device: device, is_absolute: is_absolute, - components: components } + components: normalize(components) } } fn dirname() -> ~str { @@ -112,7 +256,6 @@ impl WindowsPath : Path { fn filename() -> option<~str> { match self.components.len() { 0 => none, - 1 => some(copy self.components[0]), n => some(copy self.components[n - 1]) } } @@ -163,11 +306,18 @@ impl WindowsPath : Path { } fn with_filetype(t: &str) -> WindowsPath { - let t = ~"." + str::from_slice(t); - match self.filestem() { - none => self.with_filename(t), - some(ref s) => - self.with_filename(*s + t) + if t.len() == 0 { + match self.filestem() { + none => copy self, + some(s) => self.with_filename(s) + } + } else { + let t = ~"." + str::from_slice(t); + match self.filestem() { + none => self.with_filename(t), + some(ref s) => + self.with_filename(*s + t) + } } } @@ -191,7 +341,8 @@ impl WindowsPath : Path { } fn push_components(cs: &[~str]) -> WindowsPath { - return WindowsPath { components: self.components + cs, ..self } + return WindowsPath { components: normalize(self.components + cs), + ..self } } fn pop_component() -> WindowsPath { @@ -203,6 +354,85 @@ impl WindowsPath : Path { } } + +fn normalize(components: &[~str]) -> ~[~str] { + let mut cs = ~[]; + for components.each |c| { + if c == ~"." { again; } + if c == ~".." && cs.len() != 0 { + vec::pop(cs); + again; + } + vec::push(cs, copy c); + } + cs +} + +mod posix { + + #[test] + fn test_posix_paths() { + fn mk(s: &str) -> PosixPath { from_str::<PosixPath>(s) } + fn t(wp: &PosixPath, s: &str) { + let ss = wp.to_str(); + let sss = str::from_slice(s); + if (ss != sss) { + debug!("got %s", ss); + debug!("expected %s", sss); + assert ss == sss; + } + } + + t(&(mk("hi")), "hi"); + t(&(mk("hi/there")), "hi/there"); + t(&(mk("hi/there.txt")), "hi/there.txt"); + + t(&(mk("hi/there.txt")), "hi/there.txt"); + t(&(mk("hi/there.txt") + .with_filetype("")), "hi/there"); + + t(&(mk("/a/b/c/there.txt") + .with_dirname("hi")), "hi/there.txt"); + + t(&(mk("hi/there.txt") + .with_dirname(".")), "there.txt"); + + t(&(mk("a/b/../c/././/../foo.txt/")), + "a/foo.txt"); + + t(&(mk("a/b/c") + .push_components([~".."])), "a/b"); + + t(&(mk("there.txt") + .with_filetype("o")), "there.o"); + + t(&(mk("hi/there.txt") + .with_filetype("o")), "hi/there.o"); + + t(&(mk("hi/there.txt") + .with_filetype("o") + .with_dirname("/usr/lib")), + "/usr/lib/there.o"); + + t(&(mk("hi/there.txt") + .with_filetype("o") + .with_dirname("/usr/lib/")), + "/usr/lib/there.o"); + + t(&(mk("hi/there.txt") + .with_filetype("o") + .with_dirname("/usr//lib//")), + "/usr/lib/there.o"); + + t(&(mk("/usr/bin/rust") + .push_components([~"lib", ~"thingy.so"]) + .with_filestem("librustc")), + "/usr/bin/rust/lib/librustc.so"); + + } + +} + // Various windows helpers, and tests for the impl. mod windows { diff --git a/src/libcore/str.rs b/src/libcore/str.rs index d73c71c510a..4d2c98077dd 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -14,6 +14,7 @@ export // Creating a string from_bytes, from_byte, + from_slice, from_char, from_chars, append, |
