提交 f13086f4 编写于 作者: E Erick Tryzelaar

Expose platform independent path separators

上级 bf07c808
......@@ -117,6 +117,20 @@
#[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 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
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 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
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 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
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 @@ fn pop(&mut self) -> bool {
} 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 @@ fn root_path(&self) -> Option<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 @@ fn path_relative_from(&self, base: &Path) -> Option<Path> {
}
}
}
Some(Path::new(comps.connect_vec(&sep_byte)))
Some(Path::new(comps.connect_vec(&SEP_BYTE)))
}
}
......@@ -333,14 +335,14 @@ pub fn new_opt<T: BytesContainer>(path: T) -> Option<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 @@ fn normalize<V: Vector<u8>+CopyableVector<u8>>(v: V) -> ~[u8] {
}
}
for comp in it {
v.push(sep_byte);
v.push(SEP_BYTE);
v.push_all(comp);
}
Some(v)
......@@ -372,7 +374,7 @@ fn normalize<V: Vector<u8>+CopyableVector<u8>>(v: V) -> ~[u8] {
/// /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 @@ pub fn components<'a>(&'a self) -> Components<'a> {
/// 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 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
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 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
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 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
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 @@ fn append_path(me: &mut Path, path: &str) {
// 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 @@ fn is_absolute(&self) -> bool {
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 @@ fn is_ancestor_of(&self, other: &Path) -> bool {
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 @@ pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
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 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<~str> {
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 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<~str> {
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 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<~str> {
}
}
} 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 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<~str> {
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 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<~str> {
}
}
for comp in it {
s.push_char(sep);
s.push_char(SEP);
s.push_str(comp);
}
Some(s)
......@@ -837,7 +837,7 @@ fn sepidx_or_prefix_len(&self) -> Option<(uint,uint,uint)> {
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 = '/';
/// The alternative path separator character
pub static sep2: char = '/';
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册