mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
auto merge of #11642 : erickt/rust/path, r=huonw
This pull request exposes a platform independent way to get the path separator. This is useful when building complicated paths by hand.
This commit is contained in:
commit
18061e85b7
@ -117,6 +117,20 @@ pub use StrComponents = self::windows::StrComponents;
|
||||
#[cfg(windows)]
|
||||
pub use RevStrComponents = self::windows::RevStrComponents;
|
||||
|
||||
/// Alias for the platform-native separator character.
|
||||
#[cfg(unix)]
|
||||
pub use SEP = self::posix::SEP;
|
||||
/// Alias for the platform-native separator byte.
|
||||
#[cfg(windows)]
|
||||
pub use SEP = self::windows::SEP;
|
||||
|
||||
/// Alias for the platform-native separator character.
|
||||
#[cfg(unix)]
|
||||
pub use SEP_BYTE = self::posix::SEP_BYTE;
|
||||
/// Alias for the platform-native separator byte.
|
||||
#[cfg(windows)]
|
||||
pub use SEP_BYTE = self::windows::SEP_BYTE;
|
||||
|
||||
/// Typedef for the platform-native separator char func
|
||||
#[cfg(unix)]
|
||||
pub use is_sep = self::posix::is_sep;
|
||||
|
@ -45,19 +45,21 @@ pub struct Path {
|
||||
}
|
||||
|
||||
/// The standard path separator character
|
||||
pub static sep: char = '/';
|
||||
static sep_byte: u8 = sep as u8;
|
||||
pub static SEP: char = '/';
|
||||
|
||||
/// The standard path separator byte
|
||||
pub static SEP_BYTE: u8 = SEP as u8;
|
||||
|
||||
/// Returns whether the given byte is a path separator
|
||||
#[inline]
|
||||
pub fn is_sep_byte(u: &u8) -> bool {
|
||||
*u as char == sep
|
||||
*u as char == SEP
|
||||
}
|
||||
|
||||
/// Returns whether the given char is a path separator
|
||||
#[inline]
|
||||
pub fn is_sep(c: char) -> bool {
|
||||
c == sep
|
||||
c == SEP
|
||||
}
|
||||
|
||||
impl Eq for Path {
|
||||
@ -115,7 +117,7 @@ impl GenericPathUnsafe for Path {
|
||||
unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Path {
|
||||
let path = Path::normalize(path.container_as_bytes());
|
||||
assert!(!path.is_empty());
|
||||
let idx = path.rposition_elem(&sep_byte);
|
||||
let idx = path.rposition_elem(&SEP_BYTE);
|
||||
Path{ repr: path, sepidx: idx }
|
||||
}
|
||||
|
||||
@ -125,7 +127,7 @@ impl GenericPathUnsafe for Path {
|
||||
None if bytes!("..") == self.repr => {
|
||||
let mut v = vec::with_capacity(3 + filename.len());
|
||||
v.push_all(dot_dot_static);
|
||||
v.push(sep_byte);
|
||||
v.push(SEP_BYTE);
|
||||
v.push_all(filename);
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
@ -135,7 +137,7 @@ impl GenericPathUnsafe for Path {
|
||||
Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => {
|
||||
let mut v = vec::with_capacity(self.repr.len() + 1 + filename.len());
|
||||
v.push_all(self.repr);
|
||||
v.push(sep_byte);
|
||||
v.push(SEP_BYTE);
|
||||
v.push_all(filename);
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
@ -146,22 +148,22 @@ impl GenericPathUnsafe for Path {
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
}
|
||||
self.sepidx = self.repr.rposition_elem(&sep_byte);
|
||||
self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
|
||||
}
|
||||
|
||||
unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
|
||||
let path = path.container_as_bytes();
|
||||
if !path.is_empty() {
|
||||
if path[0] == sep_byte {
|
||||
if path[0] == SEP_BYTE {
|
||||
self.repr = Path::normalize(path);
|
||||
} else {
|
||||
let mut v = vec::with_capacity(self.repr.len() + path.len() + 1);
|
||||
v.push_all(self.repr);
|
||||
v.push(sep_byte);
|
||||
v.push(SEP_BYTE);
|
||||
v.push_all(path);
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
self.sepidx = self.repr.rposition_elem(&sep_byte);
|
||||
self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -211,7 +213,7 @@ impl GenericPath for Path {
|
||||
} else {
|
||||
self.repr.truncate(idx);
|
||||
}
|
||||
self.sepidx = self.repr.rposition_elem(&sep_byte);
|
||||
self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -227,7 +229,7 @@ impl GenericPath for Path {
|
||||
|
||||
#[inline]
|
||||
fn is_absolute(&self) -> bool {
|
||||
self.repr[0] == sep_byte
|
||||
self.repr[0] == SEP_BYTE
|
||||
}
|
||||
|
||||
fn is_ancestor_of(&self, other: &Path) -> bool {
|
||||
@ -291,7 +293,7 @@ impl GenericPath for Path {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Path::new(comps.connect_vec(&sep_byte)))
|
||||
Some(Path::new(comps.connect_vec(&SEP_BYTE)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,14 +335,14 @@ impl Path {
|
||||
fn normalize<V: Vector<u8>+CopyableVector<u8>>(v: V) -> ~[u8] {
|
||||
// borrowck is being very picky
|
||||
let val = {
|
||||
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == sep_byte;
|
||||
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE;
|
||||
let v_ = if is_abs { v.as_slice().slice_from(1) } else { v.as_slice() };
|
||||
let comps = normalize_helper(v_, is_abs);
|
||||
match comps {
|
||||
None => None,
|
||||
Some(comps) => {
|
||||
if is_abs && comps.is_empty() {
|
||||
Some(~[sep_byte])
|
||||
Some(~[SEP_BYTE])
|
||||
} else {
|
||||
let n = if is_abs { comps.len() } else { comps.len() - 1} +
|
||||
comps.iter().map(|v| v.len()).sum();
|
||||
@ -353,7 +355,7 @@ impl Path {
|
||||
}
|
||||
}
|
||||
for comp in it {
|
||||
v.push(sep_byte);
|
||||
v.push(SEP_BYTE);
|
||||
v.push_all(comp);
|
||||
}
|
||||
Some(v)
|
||||
@ -372,7 +374,7 @@ impl Path {
|
||||
/// /a/b/c and a/b/c yield the same set of components.
|
||||
/// A path of "/" yields no components. A path of "." yields one component.
|
||||
pub fn components<'a>(&'a self) -> Components<'a> {
|
||||
let v = if self.repr[0] == sep_byte {
|
||||
let v = if self.repr[0] == SEP_BYTE {
|
||||
self.repr.slice_from(1)
|
||||
} else { self.repr.as_slice() };
|
||||
let mut ret = v.split(is_sep_byte);
|
||||
@ -386,7 +388,7 @@ impl Path {
|
||||
/// Returns an iterator that yields each component of the path in reverse.
|
||||
/// See components() for details.
|
||||
pub fn rev_components<'a>(&'a self) -> RevComponents<'a> {
|
||||
let v = if self.repr[0] == sep_byte {
|
||||
let v = if self.repr[0] == SEP_BYTE {
|
||||
self.repr.slice_from(1)
|
||||
} else { self.repr.as_slice() };
|
||||
let mut ret = v.rsplit(is_sep_byte);
|
||||
|
@ -183,7 +183,7 @@ impl GenericPathUnsafe for Path {
|
||||
None if ".." == self.repr => {
|
||||
let mut s = str::with_capacity(3 + filename.len());
|
||||
s.push_str("..");
|
||||
s.push_char(sep);
|
||||
s.push_char(SEP);
|
||||
s.push_str(filename);
|
||||
self.update_normalized(s);
|
||||
}
|
||||
@ -193,7 +193,7 @@ impl GenericPathUnsafe for Path {
|
||||
Some((_,idxa,end)) if self.repr.slice(idxa,end) == ".." => {
|
||||
let mut s = str::with_capacity(end + 1 + filename.len());
|
||||
s.push_str(self.repr.slice_to(end));
|
||||
s.push_char(sep);
|
||||
s.push_char(SEP);
|
||||
s.push_str(filename);
|
||||
self.update_normalized(s);
|
||||
}
|
||||
@ -206,7 +206,7 @@ impl GenericPathUnsafe for Path {
|
||||
Some((idxb,_,_)) => {
|
||||
let mut s = str::with_capacity(idxb + 1 + filename.len());
|
||||
s.push_str(self.repr.slice_to(idxb));
|
||||
s.push_char(sep);
|
||||
s.push_char(SEP);
|
||||
s.push_str(filename);
|
||||
self.update_normalized(s);
|
||||
}
|
||||
@ -264,8 +264,8 @@ impl GenericPathUnsafe for Path {
|
||||
// if me is "C:" we don't want to add a path separator
|
||||
match me.prefix {
|
||||
Some(DiskPrefix) if me.repr.len() == plen => (),
|
||||
_ if !(me.repr.len() > plen && me.repr[me.repr.len()-1] == sep as u8) => {
|
||||
s.push_char(sep);
|
||||
_ if !(me.repr.len() > plen && me.repr[me.repr.len()-1] == SEP_BYTE) => {
|
||||
s.push_char(SEP);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
@ -460,7 +460,7 @@ impl GenericPath for Path {
|
||||
match self.prefix {
|
||||
Some(DiskPrefix) => {
|
||||
let rest = self.repr.slice_from(self.prefix_len());
|
||||
rest.len() > 0 && rest[0] == sep as u8
|
||||
rest.len() > 0 && rest[0] == SEP_BYTE
|
||||
}
|
||||
Some(_) => true,
|
||||
None => false
|
||||
@ -501,7 +501,7 @@ impl GenericPath for Path {
|
||||
|
||||
fn path_relative_from(&self, base: &Path) -> Option<Path> {
|
||||
fn comp_requires_verbatim(s: &str) -> bool {
|
||||
s == "." || s == ".." || s.contains_char(sep2)
|
||||
s == "." || s == ".." || s.contains_char(SEP2)
|
||||
}
|
||||
|
||||
if !self.equiv_prefix(base) {
|
||||
@ -619,14 +619,14 @@ impl Path {
|
||||
let s = match self.prefix {
|
||||
Some(_) => {
|
||||
let plen = self.prefix_len();
|
||||
if self.repr.len() > plen && self.repr[plen] == sep as u8 {
|
||||
if self.repr.len() > plen && self.repr[plen] == SEP_BYTE {
|
||||
self.repr.slice_from(plen+1)
|
||||
} else { self.repr.slice_from(plen) }
|
||||
}
|
||||
None if self.repr[0] == sep as u8 => self.repr.slice_from(1),
|
||||
None if self.repr[0] == SEP_BYTE => self.repr.slice_from(1),
|
||||
None => self.repr.as_slice()
|
||||
};
|
||||
let ret = s.split_terminator(sep).map(Some);
|
||||
let ret = s.split_terminator(SEP).map(Some);
|
||||
ret
|
||||
}
|
||||
|
||||
@ -703,7 +703,7 @@ impl Path {
|
||||
Some(VerbatimUNCPrefix(x, 0)) if s.len() == 8 + x => {
|
||||
// the server component has no trailing '\'
|
||||
let mut s = s.into_owned();
|
||||
s.push_char(sep);
|
||||
s.push_char(SEP);
|
||||
Some(s)
|
||||
}
|
||||
_ => None
|
||||
@ -739,7 +739,7 @@ impl Path {
|
||||
if is_abs {
|
||||
// normalize C:/ to C:\
|
||||
unsafe {
|
||||
str::raw::as_owned_vec(&mut s)[2] = sep as u8;
|
||||
str::raw::as_owned_vec(&mut s)[2] = SEP_BYTE;
|
||||
}
|
||||
}
|
||||
Some(s)
|
||||
@ -761,7 +761,7 @@ impl Path {
|
||||
}
|
||||
}
|
||||
} else if is_abs && comps.is_empty() {
|
||||
Some(str::from_char(sep))
|
||||
Some(str::from_char(SEP))
|
||||
} else {
|
||||
let prefix_ = s.slice_to(prefix_len(prefix));
|
||||
let n = prefix_.len() +
|
||||
@ -781,7 +781,7 @@ impl Path {
|
||||
Some(UNCPrefix(a,b)) => {
|
||||
s.push_str("\\\\");
|
||||
s.push_str(prefix_.slice(2, a+2));
|
||||
s.push_char(sep);
|
||||
s.push_char(SEP);
|
||||
s.push_str(prefix_.slice(3+a, 3+a+b));
|
||||
}
|
||||
Some(_) => s.push_str(prefix_),
|
||||
@ -795,7 +795,7 @@ impl Path {
|
||||
}
|
||||
}
|
||||
for comp in it {
|
||||
s.push_char(sep);
|
||||
s.push_char(SEP);
|
||||
s.push_str(comp);
|
||||
}
|
||||
Some(s)
|
||||
@ -837,7 +837,7 @@ impl Path {
|
||||
|
||||
fn has_nonsemantic_trailing_slash(&self) -> bool {
|
||||
is_verbatim(self) && self.repr.len() > self.prefix_len()+1 &&
|
||||
self.repr[self.repr.len()-1] == sep as u8
|
||||
self.repr[self.repr.len()-1] == SEP_BYTE
|
||||
}
|
||||
|
||||
fn update_normalized<S: Str>(&mut self, s: S) {
|
||||
@ -877,36 +877,41 @@ pub fn is_verbatim(path: &Path) -> bool {
|
||||
}
|
||||
|
||||
/// The standard path separator character
|
||||
pub static sep: char = '\\';
|
||||
pub static SEP: char = '\\';
|
||||
/// The standard path separator byte
|
||||
pub static SEP_BYTE: u8 = SEP as u8;
|
||||
|
||||
/// The alternative path separator character
|
||||
pub static sep2: char = '/';
|
||||
pub static SEP2: char = '/';
|
||||
/// The alternative path separator character
|
||||
pub static SEP2_BYTE: u8 = SEP2 as u8;
|
||||
|
||||
/// Returns whether the given char is a path separator.
|
||||
/// Allows both the primary separator '\' and the alternative separator '/'.
|
||||
#[inline]
|
||||
pub fn is_sep(c: char) -> bool {
|
||||
c == sep || c == sep2
|
||||
c == SEP || c == SEP2
|
||||
}
|
||||
|
||||
/// Returns whether the given char is a path separator.
|
||||
/// Only allows the primary separator '\'; use is_sep to allow '/'.
|
||||
#[inline]
|
||||
pub fn is_sep_verbatim(c: char) -> bool {
|
||||
c == sep
|
||||
c == SEP
|
||||
}
|
||||
|
||||
/// Returns whether the given byte is a path separator.
|
||||
/// Allows both the primary separator '\' and the alternative separator '/'.
|
||||
#[inline]
|
||||
pub fn is_sep_byte(u: &u8) -> bool {
|
||||
*u as char == sep || *u as char == sep2
|
||||
*u == SEP_BYTE || *u == SEP2_BYTE
|
||||
}
|
||||
|
||||
/// Returns whether the given byte is a path separator.
|
||||
/// Only allows the primary separator '\'; use is_sep_byte to allow '/'.
|
||||
#[inline]
|
||||
pub fn is_sep_byte_verbatim(u: &u8) -> bool {
|
||||
*u as char == sep
|
||||
*u == SEP_BYTE
|
||||
}
|
||||
|
||||
/// Prefix types for Path
|
||||
|
Loading…
Reference in New Issue
Block a user