diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-08-24 15:28:43 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-08-24 15:51:16 -0700 |
| commit | c284b8b1dc348ab8b9c82350dd1b4e53fac1225c (patch) | |
| tree | 99de39b149969275f6f9ddebd7a9f555d91c5bff /src/libcore | |
| parent | a8f1bee4574b8427a052e2fad93a90839288584b (diff) | |
Start using core::path2::Path in a lot of places.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/core.rc | 2 | ||||
| -rw-r--r-- | src/libcore/core.rs | 10 | ||||
| -rw-r--r-- | src/libcore/io.rs | 45 | ||||
| -rw-r--r-- | src/libcore/os.rs | 248 | ||||
| -rw-r--r-- | src/libcore/path2.rs | 294 |
5 files changed, 318 insertions, 281 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 4b1ace5651b..84c0568797c 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -54,7 +54,7 @@ export send_map; export hash; export cmp; export num; -export path; +export path, path2; export managed; // NDM seems to be necessary for resolve to work diff --git a/src/libcore/core.rs b/src/libcore/core.rs index 2f7ae426517..c95a42ea3ec 100644 --- a/src/libcore/core.rs +++ b/src/libcore/core.rs @@ -4,7 +4,12 @@ import option::{some, none}; import option = option::option; -import Path = path::Path; + +import Path = path2::Path; +import GenericPath = path2::GenericPath; +import WindowsPath = path2::WindowsPath; +import PosixPath = path2::PosixPath; + import tuple::{TupleOps, ExtendedTupleOps}; import str::{StrSlice, UniqueStr}; import vec::{ConstVector, CopyableVector, ImmutableVector}; @@ -14,7 +19,8 @@ import num::Num; import ptr::Ptr; import to_str::ToStr; -export Path, option, some, none, unreachable; +export Path, WindowsPath, PosixPath, GenericPath; +export option, some, none, unreachable; export extensions; // The following exports are the extension impls for numeric types export Num, Times, TimesIx; diff --git a/src/libcore/io.rs b/src/libcore/io.rs index a2b02f55b22..452aae49984 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -257,13 +257,14 @@ fn FILE_reader(f: *libc::FILE, cleanup: bool) -> Reader { fn stdin() -> Reader { rustrt::rust_get_stdin() as Reader } -fn file_reader(path: ~str) -> result<Reader, ~str> { - let f = os::as_c_charp(path, |pathbuf| { - os::as_c_charp(~"r", |modebuf| +fn file_reader(path: &Path) -> result<Reader, ~str> { + let f = os::as_c_charp(path.to_str(), |pathbuf| { + os::as_c_charp("r", |modebuf| libc::fopen(pathbuf, modebuf) ) }); - return if f as uint == 0u { result::err(~"error opening " + path) } + return if f as uint == 0u { result::err(~"error opening " + + path.to_str()) } else { result::ok(FILE_reader(f, true)) } @@ -412,7 +413,7 @@ fn fd_writer(fd: fd_t, cleanup: bool) -> Writer { } -fn mk_file_writer(path: ~str, flags: ~[FileFlag]) +fn mk_file_writer(path: &Path, flags: ~[FileFlag]) -> result<Writer, ~str> { #[cfg(windows)] @@ -430,12 +431,13 @@ fn mk_file_writer(path: ~str, flags: ~[FileFlag]) NoFlag => () } } - let fd = do os::as_c_charp(path) |pathbuf| { + let fd = do os::as_c_charp(path.to_str()) |pathbuf| { libc::open(pathbuf, fflags, (S_IRUSR | S_IWUSR) as c_int) }; if fd < (0 as c_int) { - result::err(fmt!("error opening %s: %s", path, os::last_os_error())) + result::err(fmt!("error opening %s: %s", path.to_str(), + os::last_os_error())) } else { result::ok(fd_writer(fd, true)) } @@ -614,19 +616,20 @@ impl<T: Writer> T : WriterUtil { fn write_u8(n: u8) { self.write(&[n]) } } -fn file_writer(path: ~str, flags: ~[FileFlag]) -> result<Writer, ~str> { +fn file_writer(path: &Path, flags: ~[FileFlag]) -> result<Writer, ~str> { result::chain(mk_file_writer(path, flags), |w| result::ok(w)) } // FIXME: fileflags // #2004 -fn buffered_file_writer(path: ~str) -> result<Writer, ~str> { - let f = do os::as_c_charp(path) |pathbuf| { - do os::as_c_charp(~"w") |modebuf| { +fn buffered_file_writer(path: &Path) -> result<Writer, ~str> { + let f = do os::as_c_charp(path.to_str()) |pathbuf| { + do os::as_c_charp("w") |modebuf| { libc::fopen(pathbuf, modebuf) } }; - return if f as uint == 0u { result::err(~"error opening " + path) } + return if f as uint == 0u { result::err(~"error opening " + + path.to_str()) } else { result::ok(FILE_writer(f, true)) } } @@ -709,19 +712,19 @@ fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) -> return bpos as uint; } -fn read_whole_file_str(file: ~str) -> result<~str, ~str> { +fn read_whole_file_str(file: &Path) -> result<~str, ~str> { result::chain(read_whole_file(file), |bytes| { if str::is_utf8(bytes) { result::ok(str::from_bytes(bytes)) } else { - result::err(file + ~" is not UTF-8") + result::err(file.to_str() + ~" is not UTF-8") } }) } // FIXME (#2004): implement this in a low-level way. Going through the // abstractions is pointless. -fn read_whole_file(file: ~str) -> result<~[u8], ~str> { +fn read_whole_file(file: &Path) -> result<~[u8], ~str> { result::chain(file_reader(file), |rdr| { result::ok(rdr.read_whole_stream()) }) @@ -810,7 +813,7 @@ mod tests { #[test] fn test_simple() { - let tmpfile: ~str = ~"tmp/lib-io-test-simple.tmp"; + let tmpfile = &Path("tmp/lib-io-test-simple.tmp"); log(debug, tmpfile); let frood: ~str = ~"A hoopy frood who really knows where his towel is."; @@ -881,7 +884,7 @@ mod tests { #[test] fn file_reader_not_exist() { - match io::file_reader(~"not a file") { + match io::file_reader(&Path("not a file")) { result::err(e) => { assert e == ~"error opening not a file"; } @@ -891,9 +894,9 @@ mod tests { #[test] fn file_writer_bad_name() { - match io::file_writer(~"?/?", ~[]) { + match io::file_writer(&Path("?/?"), ~[]) { result::err(e) => { - assert str::starts_with(e, ~"error opening ?/?"); + assert str::starts_with(e, "error opening"); } result::ok(_) => fail } @@ -901,9 +904,9 @@ mod tests { #[test] fn buffered_file_writer_bad_name() { - match io::buffered_file_writer(~"?/?") { + match io::buffered_file_writer(&Path("?/?")) { result::err(e) => { - assert e == ~"error opening ?/?"; + assert str::starts_with(e, "error opening"); } result::ok(_) => fail } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 749cb246af2..4fb3e744235 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -1,3 +1,7 @@ +// NB: transitionary, de-mode-ing. +#[forbid(deprecated_mode)]; +#[forbid(deprecated_pattern)]; + /*! * Higher-level interfaces to libc::* functions and operating system services. * @@ -16,16 +20,12 @@ * to write OS-ignorant code by default. */ -#[forbid(deprecated_mode)]; -#[forbid(deprecated_pattern)]; - import libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t, mode_t, pid_t, FILE}; import libc::{close, fclose}; import option::{some, none}; -import getcwd = rustrt::rust_getcwd; import consts::*; import task::TaskBuilder; @@ -56,7 +56,11 @@ extern mod rustrt { const tmpbuf_sz : uint = 1000u; -fn as_c_charp<T>(+s: ~str, f: fn(*c_char) -> T) -> T { +fn getcwd() -> Path { + Path(rustrt::rust_getcwd()) +} + +fn as_c_charp<T>(s: &str, f: fn(*c_char) -> T) -> T { str::as_c_str(s, |b| f(b as *c_char)) } @@ -106,7 +110,7 @@ mod win32 { return res; } - fn as_utf16_p<T>(+s: ~str, f: fn(*u16) -> T) -> T { + fn as_utf16_p<T>(s: &str, f: fn(*u16) -> T) -> T { let mut t = str::to_utf16(s); // Null terminate before passing on. t += ~[0u16]; @@ -114,11 +118,11 @@ mod win32 { } } -fn getenv(+n: ~str) -> option<~str> { +fn getenv(n: &str) -> option<~str> { global_env::getenv(n) } -fn setenv(+n: ~str, +v: ~str) { +fn setenv(n: &str, v: &str) { global_env::setenv(n, v) } @@ -143,17 +147,20 @@ mod global_env { MsgEnv(comm::Chan<~[(~str,~str)]>) } - fn getenv(+n: ~str) -> option<~str> { + fn getenv(n: &str) -> option<~str> { let env_ch = get_global_env_chan(); let po = comm::port(); - comm::send(env_ch, MsgGetEnv(n, comm::chan(po))); + comm::send(env_ch, MsgGetEnv(str::from_slice(n), + comm::chan(po))); comm::recv(po) } - fn setenv(+n: ~str, +v: ~str) { + fn setenv(n: &str, v: &str) { let env_ch = get_global_env_chan(); let po = comm::port(); - comm::send(env_ch, MsgSetEnv(n, v, comm::chan(po))); + comm::send(env_ch, MsgSetEnv(str::from_slice(n), + str::from_slice(v), + comm::chan(po))); comm::recv(po) } @@ -212,7 +219,7 @@ mod global_env { } #[cfg(unix)] - fn getenv(+n: ~str) -> option<~str> { + fn getenv(n: &str) -> option<~str> { unsafe { let s = str::as_c_str(n, libc::getenv); return if unsafe::reinterpret_cast(s) == 0 { @@ -225,7 +232,7 @@ mod global_env { } #[cfg(windows)] - fn getenv(+n: ~str) -> option<~str> { + fn getenv(n: &str) -> option<~str> { import libc::types::os::arch::extra::*; import libc::funcs::extra::kernel32::*; import win32::*; @@ -238,7 +245,7 @@ mod global_env { #[cfg(unix)] - fn setenv(+n: ~str, +v: ~str) { + fn setenv(n: &str, v: &str) { // FIXME: remove this when export globs work properly. #1238 import libc::funcs::posix01::unistd::setenv; @@ -251,7 +258,7 @@ mod global_env { #[cfg(windows)] - fn setenv(+n: ~str, +v: ~str) { + fn setenv(n: &str, v: &str) { // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import win32::*; @@ -266,7 +273,7 @@ mod global_env { } fn fdopen(fd: c_int) -> *FILE { - return do as_c_charp(~"r") |modebuf| { + return do as_c_charp("r") |modebuf| { libc::fdopen(fd, modebuf) }; } @@ -365,8 +372,8 @@ fn dup2(src: c_int, dst: c_int) -> c_int { } -fn dll_filename(+base: ~str) -> ~str { - return pre() + base + dll_suffix(); +fn dll_filename(base: &str) -> ~str { + return pre() + str::from_slice(base) + dll_suffix(); #[cfg(unix)] fn pre() -> ~str { ~"lib" } @@ -379,7 +386,7 @@ fn dll_filename(+base: ~str) -> ~str { fn self_exe_path() -> option<Path> { #[cfg(target_os = "freebsd")] - fn load_self() -> option<Path> { + fn load_self() -> option<~str> { unsafe { import libc::funcs::bsd44::*; import libc::consts::os::extra::*; @@ -395,17 +402,17 @@ fn self_exe_path() -> option<Path> { } #[cfg(target_os = "linux")] - fn load_self() -> option<Path> { + fn load_self() -> option<~str> { import libc::funcs::posix01::unistd::readlink; do fill_charp_buf() |buf, sz| { - do as_c_charp(~"/proc/self/exe") |proc_self_buf| { + do as_c_charp("/proc/self/exe") |proc_self_buf| { readlink(proc_self_buf, buf, sz) != (-1 as ssize_t) } } } #[cfg(target_os = "macos")] - fn load_self() -> option<Path> { + fn load_self() -> option<~str> { // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::*; do fill_charp_buf() |buf, sz| { @@ -415,7 +422,7 @@ fn self_exe_path() -> option<Path> { } #[cfg(windows)] - fn load_self() -> option<Path> { + fn load_self() -> option<~str> { // FIXME: remove imports when export globs work properly. #1238 import libc::types::os::arch::extra::*; import libc::funcs::extra::kernel32::*; @@ -426,7 +433,7 @@ fn self_exe_path() -> option<Path> { } do option::map(load_self()) |pth| { - path::dirname(pth) + path::path_sep() + Path(pth).dir_path() } } @@ -447,7 +454,7 @@ fn self_exe_path() -> option<Path> { fn homedir() -> option<Path> { return match getenv(~"HOME") { some(p) => if !str::is_empty(p) { - some(p) + some(Path(p)) } else { secondary() }, @@ -463,7 +470,7 @@ fn homedir() -> option<Path> { fn secondary() -> option<Path> { do option::chain(getenv(~"USERPROFILE")) |p| { if !str::is_empty(p) { - some(p) + some(Path(p)) } else { none } @@ -484,13 +491,13 @@ fn homedir() -> option<Path> { fn tmpdir() -> Path { return lookup(); - fn getenv_nonempty(+v: Path) -> option<Path> { + fn getenv_nonempty(v: &str) -> option<Path> { match getenv(v) { some(x) => if str::is_empty(x) { none } else { - some(x) + some(Path(x)) }, _ => none } @@ -498,28 +505,29 @@ fn tmpdir() -> Path { #[cfg(unix)] fn lookup() -> Path { - option::get_default(getenv_nonempty(~"TMPDIR"), ~"/tmp") + option::get_default(getenv_nonempty("TMPDIR"), + Path("/tmp")) } #[cfg(windows)] fn lookup() -> Path { option::get_default( - option::or(getenv_nonempty(~"TMP"), - option::or(getenv_nonempty(~"TEMP"), - option::or(getenv_nonempty(~"USERPROFILE"), - getenv_nonempty(~"WINDIR")))), - ~"C:\\Windows") + option::or(getenv_nonempty("TMP"), + option::or(getenv_nonempty("TEMP"), + option::or(getenv_nonempty("USERPROFILE"), + getenv_nonempty("WINDIR")))), + Path("C:\\Windows")) } } /// Recursively walk a directory structure -fn walk_dir(+p: Path, f: fn(Path) -> bool) { +fn walk_dir(p: &Path, f: fn((&Path)) -> bool) { walk_dir_(p, f); - fn walk_dir_(+p: Path, f: fn(Path) -> bool) -> bool { + fn walk_dir_(p: &Path, f: fn((&Path)) -> bool) -> bool { let mut keepgoing = true; do list_dir(p).each |q| { - let path = path::connect(p, q); + let path = &p.push(q); if !f(path) { keepgoing = false; false @@ -541,15 +549,15 @@ fn walk_dir(+p: Path, f: fn(Path) -> bool) { } /// Indicates whether a path represents a directory -fn path_is_dir(+p: Path) -> bool { - do str::as_c_str(p) |buf| { +fn path_is_dir(p: &Path) -> bool { + do str::as_c_str(p.to_str()) |buf| { rustrt::rust_path_is_dir(buf) != 0 as c_int } } /// Indicates whether a path exists -fn path_exists(+p: Path) -> bool { - do str::as_c_str(p) |buf| { +fn path_exists(p: &Path) -> bool { + do str::as_c_str(p.to_str()) |buf| { rustrt::rust_path_exists(buf) != 0 as c_int } } @@ -566,58 +574,50 @@ fn path_exists(+p: Path) -> bool { // NB: this is here rather than in path because it is a form of environment // querying; what it does depends on the process working directory, not just // the input paths. -fn make_absolute(+p: Path) -> Path { - if path::path_is_absolute(p) { - p +fn make_absolute(p: &Path) -> Path { + if p.is_absolute { + copy *p } else { - path::connect(getcwd(), p) + getcwd().push_many(p.components) } } /// Creates a directory at the specified path -fn make_dir(+p: Path, mode: c_int) -> bool { +fn make_dir(p: &Path, mode: c_int) -> bool { return mkdir(p, mode); #[cfg(windows)] - fn mkdir(+p: Path, _mode: c_int) -> bool { + fn mkdir(p: &Path, _mode: c_int) -> bool { // FIXME: remove imports when export globs work properly. #1238 import libc::types::os::arch::extra::*; import libc::funcs::extra::kernel32::*; import win32::*; // FIXME: turn mode into something useful? #2623 - do as_utf16_p(p) |buf| { + do as_utf16_p(p.to_str()) |buf| { CreateDirectoryW(buf, unsafe { unsafe::reinterpret_cast(0) }) != (0 as BOOL) } } #[cfg(unix)] - fn mkdir(+p: Path, mode: c_int) -> bool { - do as_c_charp(p) |c| { + fn mkdir(p: &Path, mode: c_int) -> bool { + do as_c_charp(p.to_str()) |c| { libc::mkdir(c, mode as mode_t) == (0 as c_int) } } } /// Lists the contents of a directory -fn list_dir(+p: Path) -> ~[~str] { +fn list_dir(p: &Path) -> ~[~str] { #[cfg(unix)] - fn star(+p: ~str) -> ~str { p } + fn star(p: &Path) -> Path { copy *p } #[cfg(windows)] - fn star(+p: ~str) -> ~str { - let pl = str::len(p); - if pl == 0u || (p[pl - 1u] as char != path::consts::path_sep - || p[pl - 1u] as char != path::consts::alt_path_sep) { - p + path::path_sep() + ~"*" - } else { - p + ~"*" - } - } + fn star(p: &Path) -> Path { p.push("*") } - do rustrt::rust_list_files(star(p)).filter |filename| { + do rustrt::rust_list_files(star(p).to_str()).filter |filename| { filename != ~"." && filename != ~".." } } @@ -627,90 +627,84 @@ fn list_dir(+p: Path) -> ~[~str] { * * This version prepends each entry with the directory. */ -fn list_dir_path(+p: Path) -> ~[~str] { - let mut p = p; - let pl = str::len(p); - if pl == 0u || (p[pl - 1u] as char != path::consts::path_sep - && p[pl - 1u] as char != path::consts::alt_path_sep) { - p += path::path_sep(); - } - os::list_dir(p).map(|f| p + f) +fn list_dir_path(p: &Path) -> ~[~Path] { + os::list_dir(p).map(|f| ~p.push(f)) } /// Removes a directory at the specified path -fn remove_dir(+p: Path) -> bool { +fn remove_dir(p: &Path) -> bool { return rmdir(p); #[cfg(windows)] - fn rmdir(+p: Path) -> bool { + fn rmdir(p: &Path) -> bool { // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import libc::types::os::arch::extra::*; import win32::*; - return do as_utf16_p(p) |buf| { + return do as_utf16_p(p.to_str()) |buf| { RemoveDirectoryW(buf) != (0 as BOOL) }; } #[cfg(unix)] - fn rmdir(+p: Path) -> bool { - return do as_c_charp(p) |buf| { + fn rmdir(p: &Path) -> bool { + return do as_c_charp(p.to_str()) |buf| { libc::rmdir(buf) == (0 as c_int) }; } } -fn change_dir(+p: Path) -> bool { +fn change_dir(p: &Path) -> bool { return chdir(p); #[cfg(windows)] - fn chdir(+p: Path) -> bool { + fn chdir(p: &Path) -> bool { // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import libc::types::os::arch::extra::*; import win32::*; - return do as_utf16_p(p) |buf| { + return do as_utf16_p(p.to_str()) |buf| { SetCurrentDirectoryW(buf) != (0 as BOOL) }; } #[cfg(unix)] - fn chdir(+p: Path) -> bool { - return do as_c_charp(p) |buf| { + fn chdir(p: &Path) -> bool { + return do as_c_charp(p.to_str()) |buf| { libc::chdir(buf) == (0 as c_int) }; } } /// Copies a file from one location to another -fn copy_file(+from: Path, +to: Path) -> bool { +fn copy_file(from: &Path, to: &Path) -> bool { return do_copy_file(from, to); #[cfg(windows)] - fn do_copy_file(+from: Path, +to: Path) -> bool { + fn do_copy_file(from: &Path, to: &Path) -> bool { // FIXME: remove imports when export globs work properly. #1238 import libc::funcs::extra::kernel32::*; import libc::types::os::arch::extra::*; import win32::*; - return do as_utf16_p(from) |fromp| { - do as_utf16_p(to) |top| { + return do as_utf16_p(from.to_str()) |fromp| { + do as_utf16_p(to.to_str()) |top| { CopyFileW(fromp, top, (0 as BOOL)) != (0 as BOOL) } } } #[cfg(unix)] - fn do_copy_file(+from: Path, +to: Path) -> bool { - let istream = do as_c_charp(from) |fromp| { - do as_c_charp(~"rb") |modebuf| { + fn do_copy_file(from: &Path, to: &Path) -> bool { + let istream = do as_c_charp(from.to_str()) |fromp| { + do as_c_charp("rb") |modebuf| { libc::fopen(fromp, modebuf) } }; if istream as uint == 0u { return false; } - let ostream = do as_c_charp(to) |top| { - do as_c_charp(~"w+b") |modebuf| { + let ostream = do as_c_charp(to.to_str()) |top| { + do as_c_charp("w+b") |modebuf| { libc::fopen(top, modebuf) } }; @@ -746,24 +740,24 @@ fn copy_file(+from: Path, +to: Path) -> bool { } /// Deletes an existing file -fn remove_file(+p: Path) -> bool { +fn remove_file(p: &Path) -> bool { return unlink(p); #[cfg(windows)] - fn unlink(+p: Path) -> bool { + fn unlink(p: &Path) -> bool { // FIXME (similar to Issue #2006): remove imports when export globs // work properly. import libc::funcs::extra::kernel32::*; import libc::types::os::arch::extra::*; import win32::*; - return do as_utf16_p(p) |buf| { + return do as_utf16_p(p.to_str()) |buf| { DeleteFileW(buf) != (0 as BOOL) }; } #[cfg(unix)] - fn unlink(+p: Path) -> bool { - return do as_c_charp(p) |buf| { + fn unlink(p: &Path) -> bool { + return do as_c_charp(p.to_str()) |buf| { libc::unlink(buf) == (0 as c_int) }; } @@ -887,11 +881,7 @@ mod tests { log(debug, path); // Hard to test this function - if os::sysname() != ~"win32" { - assert str::starts_with(path, path::path_sep()); - } else { - assert path[1] == ':' as u8; - } + assert path.is_absolute; } #[test] @@ -926,10 +916,10 @@ mod tests { fn test() { assert (!path::path_is_absolute(~"test-path")); - log(debug, ~"Current working directory: " + getcwd()); + log(debug, ~"Current working directory: " + getcwd().to_str()); - log(debug, make_absolute(~"test-path")); - log(debug, make_absolute(~"/usr/bin")); + log(debug, make_absolute(&Path("test-path"))); + log(debug, make_absolute(&Path("/usr/bin"))); } #[test] @@ -938,7 +928,7 @@ mod tests { let oldhome = getenv(~"HOME"); setenv(~"HOME", ~"/home/MountainView"); - assert os::homedir() == some(~"/home/MountainView"); + assert os::homedir() == some(Path("/home/MountainView")); setenv(~"HOME", ~""); assert os::homedir() == none; @@ -959,16 +949,16 @@ mod tests { assert os::homedir() == none; setenv(~"HOME", ~"/home/MountainView"); - assert os::homedir() == some(~"/home/MountainView"); + assert os::homedir() == some(Path("/home/MountainView")); setenv(~"HOME", ~""); setenv(~"USERPROFILE", ~"/home/MountainView"); - assert os::homedir() == some(~"/home/MountainView"); + assert os::homedir() == some(Path("/home/MountainView")); setenv(~"HOME", ~"/home/MountainView"); setenv(~"USERPROFILE", ~"/home/PaloAlto"); - assert os::homedir() == some(~"/home/MountainView"); + assert os::homedir() == some(Path("/home/MountainView")); option::iter(oldhome, |s| setenv(~"HOME", s)); option::iter(olduserprofile, @@ -977,16 +967,18 @@ mod tests { #[test] fn tmpdir() { - assert !str::is_empty(os::tmpdir()); + assert !str::is_empty(os::tmpdir().to_str()); } // Issue #712 #[test] - fn test_list_dir_no_invalid_memory_access() { os::list_dir(~"."); } + fn test_list_dir_no_invalid_memory_access() { + os::list_dir(&Path(".")); + } #[test] fn list_dir() { - let dirs = os::list_dir(~"."); + let dirs = os::list_dir(&Path(".")); // Just assuming that we've got some contents in the current directory assert (vec::len(dirs) > 0u); @@ -995,34 +987,34 @@ mod tests { #[test] fn path_is_dir() { - assert (os::path_is_dir(~".")); - assert (!os::path_is_dir(~"test/stdtest/fs.rs")); + assert (os::path_is_dir(&Path("."))); + assert (!os::path_is_dir(&Path("test/stdtest/fs.rs"))); } #[test] fn path_exists() { - assert (os::path_exists(~".")); - assert (!os::path_exists(~"test/nonexistent-bogus-path")); + assert (os::path_exists(&Path("."))); + assert (!os::path_exists(&Path("test/nonexistent-bogus-path"))); } #[test] fn copy_file_does_not_exist() { - assert !os::copy_file(~"test/nonexistent-bogus-path", - ~"test/other-bogus-path"); - assert !os::path_exists(~"test/other-bogus-path"); + assert !os::copy_file(&Path("test/nonexistent-bogus-path"), + &Path("test/other-bogus-path")); + assert !os::path_exists(&Path("test/other-bogus-path")); } #[test] fn copy_file_ok() { let tempdir = getcwd(); // would like to use $TMPDIR, // doesn't seem to work on Linux - assert (str::len(tempdir) > 0u); - let in = tempdir + path::path_sep() + ~"in.txt"; - let out = tempdir + path::path_sep() + ~"out.txt"; + assert (str::len(tempdir.to_str()) > 0u); + let in = tempdir.push("in.txt"); + let out = tempdir.push("out.txt"); /* Write the temp input file */ - let ostream = do as_c_charp(in) |fromp| { - do as_c_charp(~"w+b") |modebuf| { + let ostream = do as_c_charp(in.to_str()) |fromp| { + do as_c_charp("w+b") |modebuf| { libc::fopen(fromp, modebuf) } }; @@ -1034,14 +1026,14 @@ mod tests { (str::len(s) + 1u) as size_t, ostream) == buf.len() as size_t)}; assert (libc::fclose(ostream) == (0u as c_int)); - let rs = os::copy_file(in, out); - if (!os::path_exists(in)) { - fail (fmt!("%s doesn't exist", in)); + let rs = os::copy_file(&in, &out); + if (!os::path_exists(&in)) { + fail (fmt!("%s doesn't exist", in.to_str())); } assert(rs); - let rslt = run::run_program(~"diff", ~[in, out]); + let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]); assert (rslt == 0); - assert (remove_file(in)); - assert (remove_file(out)); + assert (remove_file(&in)); + assert (remove_file(&out)); } } diff --git a/src/libcore/path2.rs b/src/libcore/path2.rs index 50996c7876b..9d1351db3ac 100644 --- a/src/libcore/path2.rs +++ b/src/libcore/path2.rs @@ -14,73 +14,82 @@ struct PosixPath { components: ~[~str]; } -trait Path { +trait GenericPath { - static fn from_str((&str)) -> self; - fn to_str() -> ~str; + static pure fn from_str((&str)) -> self; - fn dirname() -> ~str; - fn filename() -> option<~str>; - fn filestem() -> option<~str>; - fn filetype() -> option<~str>; + pure fn dirname() -> ~str; + pure fn filename() -> option<~str>; + pure fn filestem() -> option<~str>; + pure fn filetype() -> option<~str>; - fn with_dirname((&str)) -> self; - fn with_filename((&str)) -> self; - fn with_filestem((&str)) -> self; - fn with_filetype((&str)) -> self; + pure fn with_dirname((&str)) -> self; + pure fn with_filename((&str)) -> self; + pure fn with_filestem((&str)) -> self; + pure fn with_filetype((&str)) -> self; - fn push_components((&[~str])) -> self; - fn pop_component() -> self; + pure fn push((&str)) -> self; + pure fn push_rel((&self)) -> self; + pure fn push_many((&[~str])) -> self; + pure fn pop() -> self; } -// FIXME (#3227): when default methods in traits are working, de-duplicate -// PosixPath and WindowsPath, most of their methods are common. +#[cfg(windows)] +type Path = WindowsPath; + +#[cfg(windows)] +pure fn Path(s: &str) -> Path { + from_str::<WindowsPath>(s) +} + +#[cfg(unix)] +type Path = PosixPath; -impl PosixPath : Path { +#[cfg(unix)] +pure fn Path(s: &str) -> Path { + from_str::<PosixPath>(s) +} + +impl PosixPath : ToStr { 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 - } + let mut s = ~""; + if self.is_absolute { + s += "/"; } + s + str::connect(self.components, "/") } +} - static fn from_str(s: &str) -> PosixPath { +// FIXME (#3227): when default methods in traits are working, de-duplicate +// PosixPath and WindowsPath, most of their methods are common. +impl PosixPath : GenericPath { + + static pure 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 = ~"."; + pure fn dirname() -> ~str { + unchecked { + let s = self.dir_path().to_str(); + if s.len() == 0 { + ~"." + } else { + s + } } - return s; } - fn filename() -> option<~str> { + pure fn filename() -> option<~str> { match self.components.len() { 0 => none, n => some(copy self.components[n - 1]) } } - fn filestem() -> option<~str> { + pure fn filestem() -> option<~str> { match self.filename() { none => none, some(ref f) => { @@ -92,7 +101,7 @@ impl PosixPath : Path { } } - fn filetype() -> option<~str> { + pure fn filetype() -> option<~str> { match self.filename() { none => none, some(ref f) => { @@ -104,20 +113,22 @@ impl PosixPath : Path { } } - fn with_dirname(d: &str) -> PosixPath { + pure fn with_dirname(d: &str) -> PosixPath { let dpath = from_str::<PosixPath>(d); match self.filename() { - some(ref f) => dpath.push_components(~[copy *f]), + some(ref f) => dpath.push(*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)]) + pure fn with_filename(f: &str) -> PosixPath { + unchecked { + assert ! str::any(f, |c| windows::is_sep(c as u8)); + self.dir_path().push(f) + } } - fn with_filestem(s: &str) -> PosixPath { + pure fn with_filestem(s: &str) -> PosixPath { match self.filetype() { none => self.with_filename(s), some(ref t) => @@ -125,7 +136,7 @@ impl PosixPath : Path { } } - fn with_filetype(t: &str) -> PosixPath { + pure fn with_filetype(t: &str) -> PosixPath { if t.len() == 0 { match self.filestem() { none => copy self, @@ -141,15 +152,15 @@ impl PosixPath : Path { } } - fn dir_path() -> PosixPath { + pure fn dir_path() -> PosixPath { if self.components.len() != 0 { - self.pop_component() + self.pop() } else { copy self } } - fn file_path() -> PosixPath { + pure fn file_path() -> PosixPath { let cs = match self.filename() { none => ~[], some(ref f) => ~[copy *f] @@ -158,42 +169,56 @@ impl PosixPath : Path { components: cs } } - fn push_components(cs: &[~str]) -> PosixPath { + pure fn push_rel(other: &PosixPath) -> PosixPath { + assert !other.is_absolute; + self.push_many(other.components) + } + + pure fn push_many(cs: &[~str]) -> PosixPath { return PosixPath { components: normalize(self.components + cs), ..self } } - fn pop_component() -> PosixPath { + pure fn push(s: &str) -> PosixPath { + let mut cs = self.components; + unchecked { vec::push(cs, move str::from_slice(s)); } + cs = normalize(cs); + return PosixPath { components: move cs, + ..self } + } + + pure fn pop() -> PosixPath { let mut cs = copy self.components; if cs.len() != 0 { - vec::pop(cs); + unchecked { vec::pop(cs); } } - return PosixPath { components: cs, ..self } + return PosixPath { components: move cs, ..self } } - - - } -impl WindowsPath : Path { - +impl WindowsPath : ToStr { fn to_str() -> ~str { - match self.filename() { - none => self.dirname(), - some(ref f) => - if (self.components.len() == 1 && - !self.is_absolute && - self.host == none && - self.device == none) { - copy *f - } else { - self.dirname() + "\\" + *f - } + let mut s = ~""; + match self.host { + some(h) => { s += "\\\\"; s += h; } + none => { } + } + match self.device { + some(d) => { s += d; s += ":"; } + none => { } + } + if self.is_absolute { + s += "\\"; } + s + str::connect(self.components, "\\") } +} + - static fn from_str(s: &str) -> WindowsPath { +impl WindowsPath : GenericPath { + + static pure fn from_str(s: &str) -> WindowsPath { let host; let device; let rest; @@ -229,38 +254,25 @@ impl WindowsPath : Path { components: normalize(components) } } - fn dirname() -> ~str { - let mut s = ~""; - match self.host { - some(h) => { s += "\\\\"; s += h; } - none => { } - } - match self.device { - some(d) => { s += d; s += ":"; } - none => { } - } - 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 = ~"."; + pure fn dirname() -> ~str { + unchecked { + let s = self.dir_path().to_str(); + if s.len() == 0 { + ~"." + } else { + s + } } - return s; } - fn filename() -> option<~str> { + pure fn filename() -> option<~str> { match self.components.len() { 0 => none, n => some(copy self.components[n - 1]) } } - fn filestem() -> option<~str> { + pure fn filestem() -> option<~str> { match self.filename() { none => none, some(ref f) => { @@ -272,7 +284,7 @@ impl WindowsPath : Path { } } - fn filetype() -> option<~str> { + pure fn filetype() -> option<~str> { match self.filename() { none => none, some(ref f) => { @@ -284,20 +296,20 @@ impl WindowsPath : Path { } } - fn with_dirname(d: &str) -> WindowsPath { + pure fn with_dirname(d: &str) -> WindowsPath { let dpath = from_str::<WindowsPath>(d); match self.filename() { - some(ref f) => dpath.push_components(~[copy *f]), + some(ref f) => dpath.push(*f), none => dpath } } - fn with_filename(f: &str) -> WindowsPath { + pure fn with_filename(f: &str) -> WindowsPath { assert ! str::any(f, |c| windows::is_sep(c as u8)); - self.dir_path().push_components(~[str::from_slice(f)]) + self.dir_path().push(f) } - fn with_filestem(s: &str) -> WindowsPath { + pure fn with_filestem(s: &str) -> WindowsPath { match self.filetype() { none => self.with_filename(s), some(ref t) => @@ -305,7 +317,7 @@ impl WindowsPath : Path { } } - fn with_filetype(t: &str) -> WindowsPath { + pure fn with_filetype(t: &str) -> WindowsPath { if t.len() == 0 { match self.filestem() { none => copy self, @@ -321,15 +333,15 @@ impl WindowsPath : Path { } } - fn dir_path() -> WindowsPath { + pure fn dir_path() -> WindowsPath { if self.components.len() != 0 { - self.pop_component() + self.pop() } else { copy self } } - fn file_path() -> WindowsPath { + pure fn file_path() -> WindowsPath { let cs = match self.filename() { none => ~[], some(ref f) => ~[copy *f] @@ -340,30 +352,47 @@ impl WindowsPath : Path { components: cs } } - fn push_components(cs: &[~str]) -> WindowsPath { + pure fn push_rel(other: &WindowsPath) -> WindowsPath { + assert !other.is_absolute; + self.push_many(other.components) + } + + pure fn push_many(cs: &[~str]) -> WindowsPath { return WindowsPath { components: normalize(self.components + cs), ..self } } - fn pop_component() -> WindowsPath { + pure fn push(s: &str) -> WindowsPath { + let mut cs = self.components; + unchecked { vec::push(cs, move str::from_slice(s)); } + cs = normalize(cs); + return WindowsPath { components: move cs, + ..self } + } + + pure fn pop() -> WindowsPath { let mut cs = copy self.components; if cs.len() != 0 { - vec::pop(cs); + unchecked { vec::pop(cs); } } - return WindowsPath { components: cs, ..self } + return WindowsPath { components: move cs, ..self } } } -fn normalize(components: &[~str]) -> ~[~str] { +pure fn normalize(components: &[~str]) -> ~[~str] { let mut cs = ~[]; - for components.each |c| { - if c == ~"." { again; } - if c == ~".." && cs.len() != 0 { - vec::pop(cs); - again; + unchecked { + for components.each |c| { + unchecked { + if c == ~"." && components.len() > 1 { again; } + if c == ~".." && cs.len() != 0 { + vec::pop(cs); + again; + } + vec::push(cs, copy c); + } } - vec::push(cs, copy c); } cs } @@ -384,6 +413,7 @@ mod posix { } t(&(mk("hi")), "hi"); + t(&(mk("/lib")), "/lib"); t(&(mk("hi/there")), "hi/there"); t(&(mk("hi/there.txt")), "hi/there.txt"); @@ -401,7 +431,7 @@ mod posix { "a/foo.txt"); t(&(mk("a/b/c") - .push_components([~".."])), "a/b"); + .push("..")), "a/b"); t(&(mk("there.txt") .with_filetype("o")), "there.o"); @@ -425,7 +455,7 @@ mod posix { "/usr/lib/there.o"); t(&(mk("/usr/bin/rust") - .push_components([~"lib", ~"thingy.so"]) + .push_many([~"lib", ~"thingy.so"]) .with_filestem("librustc")), "/usr/bin/rust/lib/librustc.so"); @@ -437,11 +467,11 @@ mod posix { mod windows { #[inline(always)] - fn is_sep(u: u8) -> bool { + pure fn is_sep(u: u8) -> bool { u == '/' as u8 || u == '\\' as u8 } - fn extract_unc_prefix(s: &str) -> option<(~str,~str)> { + pure fn extract_unc_prefix(s: &str) -> option<(~str,~str)> { if (s.len() > 1 && s[0] == '\\' as u8 && s[1] == '\\' as u8) { @@ -458,14 +488,20 @@ mod windows { none } - fn extract_drive_prefix(s: &str) -> option<(~str,~str)> { - if (s.len() > 1 && - libc::isalpha(s[0] as libc::c_int) != 0 && - s[1] == ':' as u8) { - let rest = if s.len() == 2 { ~"" } else { s.slice(2, s.len()) }; - return some((s.slice(0,1), rest)); + pure fn extract_drive_prefix(s: &str) -> option<(~str,~str)> { + unchecked { + if (s.len() > 1 && + libc::isalpha(s[0] as libc::c_int) != 0 && + s[1] == ':' as u8) { + let rest = if s.len() == 2 { + ~"" + } else { + s.slice(2, s.len()) + }; + return some((s.slice(0,1), rest)); + } + none } - none } #[test] @@ -532,7 +568,7 @@ mod windows { "c:\\program files C\\there.o"); t(&(mk("c:\\program files (x86)\\rust") - .push_components([~"lib", ~"thingy.dll"]) + .push_many([~"lib", ~"thingy.dll"]) .with_filename("librustc.dll")), "c:\\program files (x86)\\rust\\lib\\librustc.dll"); |
