From 802deac3233d91bcd6ba5a87c6a4de8b3e12425e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 28 Oct 2011 23:23:51 -0700 Subject: [PATCH] stdlib: Add fs::splitext Splits a path into the filename + extension --- src/lib/fs.rs | 49 ++++++++++++++++++++++++++++++++++++ src/test/stdtest/fs.rs | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src/lib/fs.rs b/src/lib/fs.rs index 5787e9c510c3..057f933d0a56 100644 --- a/src/lib/fs.rs +++ b/src/lib/fs.rs @@ -176,6 +176,55 @@ fn split(p: path) -> [path] { ret split2; } +/* +Function: splitext + +Split a path into a pair of strings with the first element being the filename +without the extension and the second being either empty or the file extension +including the period. Leading periods in the basename are ignored. If the +path includes directory components then they are included in the filename part +of the result pair. +*/ +fn splitext(p: path) -> (str, str) { + if str::is_empty(p) { ("", "") } + else { + let parts = str::split(p, '.' as u8); + if vec::len(parts) > 1u { + let base = str::connect(vec::init(parts), "."); + let ext = "." + option::get(vec::last(parts)); + + fn is_dotfile(base: str) -> bool { + str::is_empty(base) + || str::ends_with( + base, str::from_char(os_fs::path_sep)) + || str::ends_with( + base, str::from_char(os_fs::alt_path_sep)) + } + + fn ext_contains_sep(ext: str) -> bool { + vec::len(split(ext)) > 1u + } + + fn no_basename(ext: str) -> bool { + str::ends_with( + ext, str::from_char(os_fs::path_sep)) + || str::ends_with( + ext, str::from_char(os_fs::alt_path_sep)) + } + + if is_dotfile(base) + || ext_contains_sep(ext) + || no_basename(ext) { + (p, "") + } else { + (base, ext) + } + } else { + (p, "") + } + } +} + /* Function: normalize diff --git a/src/test/stdtest/fs.rs b/src/test/stdtest/fs.rs index 14467ea59a65..66cec07c7955 100644 --- a/src/test/stdtest/fs.rs +++ b/src/test/stdtest/fs.rs @@ -156,4 +156,60 @@ fn normalize12() { #[cfg(target_os = "win32")] fn path_is_absolute_win32() { assert fs::path_is_absolute("C:/whatever"); +} + +#[test] +fn splitext_empty() { + let (base, ext) = fs::splitext(""); + assert base == ""; + assert ext == ""; +} + +#[test] +fn splitext_ext() { + let (base, ext) = fs::splitext("grum.exe"); + assert base == "grum"; + assert ext == ".exe"; +} + +#[test] +fn splitext_noext() { + let (base, ext) = fs::splitext("grum"); + assert base == "grum"; + assert ext == ""; +} + +#[test] +fn splitext_dotfile() { + let (base, ext) = fs::splitext(".grum"); + assert base == ".grum"; + assert ext == ""; +} + +#[test] +fn splitext_path_ext() { + let (base, ext) = fs::splitext("oh/grum.exe"); + assert base == "oh/grum"; + assert ext == ".exe"; +} + +#[test] +fn splitext_path_noext() { + let (base, ext) = fs::splitext("oh/grum"); + assert base == "oh/grum"; + assert ext == ""; +} + +#[test] +fn splitext_dot_in_path() { + let (base, ext) = fs::splitext("oh.my/grum"); + assert base == "oh.my/grum"; + assert ext == ""; +} + +#[test] +fn splitext_nobasename() { + let (base, ext) = fs::splitext("oh.my/"); + assert base == "oh.my/"; + assert ext == ""; } \ No newline at end of file