1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

stat: TODO: more tests

This commit is contained in:
Knight 2016-06-01 17:40:16 +08:00
parent e125118510
commit fd652bc285
2 changed files with 93 additions and 23 deletions

View file

@ -1,3 +1,11 @@
// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.
//
extern crate libc; extern crate libc;
extern crate time; extern crate time;
@ -307,8 +315,7 @@ pub fn pretty_fstype<'a>(fstype: i64) -> Cow<'a, str> {
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod test_fsext {
#[allow(unused_imports)]
use super::*; use super::*;
#[test] #[test]

View file

@ -75,12 +75,12 @@ macro_rules! pad_and_print {
) )
} }
macro_rules! print_adjusted { macro_rules! print_adjusted {
($str: ident, $left: expr, $width: expr, $padding: expr) => ( ($str: ident, $left: expr, $width: expr, $padding: expr) => ({
let field_width = cmp::max($width, $str.len()); let field_width = cmp::max($width, $str.len());
let mut result = String::with_capacity(field_width); let mut result = String::with_capacity(field_width);
pad_and_print!(result, $str, $left, field_width, $padding); pad_and_print!(result, $str, $left, field_width, $padding);
); });
($str: ident, $left: expr, $need_prefix: expr, $prefix: expr, $width: expr, $padding: expr) => ( ($str: ident, $left: expr, $need_prefix: expr, $prefix: expr, $width: expr, $padding: expr) => ({
let mut field_width = cmp::max($width, $str.len()); let mut field_width = cmp::max($width, $str.len());
let mut result = String::with_capacity(field_width + $prefix.len()); let mut result = String::with_capacity(field_width + $prefix.len());
if $need_prefix { if $need_prefix {
@ -88,7 +88,7 @@ macro_rules! print_adjusted {
field_width -= $prefix.len(); field_width -= $prefix.len();
} }
pad_and_print!(result, $str, $left, field_width, $padding); pad_and_print!(result, $str, $left, field_width, $padding);
) })
} }
static NAME: &'static str = "stat"; static NAME: &'static str = "stat";
@ -124,20 +124,28 @@ pub enum Token {
}, },
} }
trait ScanNum { pub trait ScanUtil {
/// Return (F, offset)
fn scan_num<F>(&self) -> Option<(F, usize)> where F: std::str::FromStr; fn scan_num<F>(&self) -> Option<(F, usize)> where F: std::str::FromStr;
fn scan_char(&self, radix: u32) -> Option<(char, usize)>;
} }
impl ScanNum for str { impl ScanUtil for str {
fn scan_num<F>(&self) -> Option<(F, usize)> fn scan_num<F>(&self) -> Option<(F, usize)>
where F: std::str::FromStr where F: std::str::FromStr
{ {
let mut chars = self.chars(); let mut chars = self.chars();
let mut i = 0; let mut i = 0;
if let Some(c) = chars.next() {
match c {
'-' | '+' | '0' ... '9' => i += 1,
_ => return None,
}
} else {
return None;
}
while let Some(c) = chars.next() { while let Some(c) = chars.next() {
match c { match c {
'-' | '+' | '0'...'9' => i += 1, '0'...'9' => i += 1,
_ => break, _ => break,
} }
} }
@ -147,6 +155,40 @@ impl ScanNum for str {
None None
} }
} }
fn scan_char(&self, radix: u32) -> Option<(char, usize)> {
let mut chars = self.chars();
let mut i = 0;
let count = match radix {
8 => 3_usize,
16 => 2,
_ => return None,
};
let mut res = 0_u32;
while i < count {
if let Some(c) = chars.next() {
match c.to_digit(radix) {
Some(digit) => {
let tmp = res * radix + digit;
if tmp < 256 {
res = tmp;
} else {
break;
}
}
None => break,
}
} else {
break;
}
i += 1;
}
if i > 0 {
Some((res as u8 as char, i))
} else {
None
}
}
} }
pub struct Stater { pub struct Stater {
@ -354,21 +396,29 @@ impl Stater {
continue; continue;
} }
match chars[i] { match chars[i] {
'x' => { 'x' if i + 1 < bound => {
// TODO: parse character if let Some((c, offset)) = fmtstr[i + 1..].scan_char(16) {
tokens.push(Token::Char(c));
i += offset;
} else {
show_warning!("unrecognized escape '\\x'");
tokens.push(Token::Char('x'));
}
} }
'0'...'7' => { '0'...'7' => {
// TODO: parse character let (c, offset) = fmtstr[i..].scan_char(8).unwrap();
tokens.push(Token::Char(c));
i += offset - 1;
} }
'"' => tokens.push(Token::Char('"')), '"' => tokens.push(Token::Char('"')),
'\\' => tokens.push(Token::Char('\\')), '\\' => tokens.push(Token::Char('\\')),
'a' => tokens.push(Token::Char('\x07')), 'a' => tokens.push(Token::Char('\x07')),
'b' => tokens.push(Token::Char('\x08')), 'b' => tokens.push(Token::Char('\x08')),
'e' => tokens.push(Token::Char('\x1B')), 'e' => tokens.push(Token::Char('\x1B')),
'f' => tokens.push(Token::Char('\x0c')), 'f' => tokens.push(Token::Char('\x0C')),
'n' => tokens.push(Token::Char('\n')), 'n' => tokens.push(Token::Char('\n')),
'r' => tokens.push(Token::Char('\r')), 'r' => tokens.push(Token::Char('\r')),
'v' => tokens.push(Token::Char('\x0b')), 'v' => tokens.push(Token::Char('\x0B')),
c => { c => {
show_warning!("unrecognized escape '\\{}'", c); show_warning!("unrecognized escape '\\{}'", c);
tokens.push(Token::Char(c)); tokens.push(Token::Char(c));
@ -401,10 +451,7 @@ impl Stater {
let default_tokens = if fmtstr.is_empty() { let default_tokens = if fmtstr.is_empty() {
Stater::generate_tokens(&Stater::default_fmt(showfs, terse, false), use_printf).unwrap() Stater::generate_tokens(&Stater::default_fmt(showfs, terse, false), use_printf).unwrap()
} else { } else {
match Stater::generate_tokens(&fmtstr, use_printf) { try!(Stater::generate_tokens(&fmtstr, use_printf))
Ok(ts) => ts,
Err(e) => return Err(e),
}
}; };
let default_dev_tokens = Stater::generate_tokens(&Stater::default_fmt(showfs, terse, true), let default_dev_tokens = Stater::generate_tokens(&Stater::default_fmt(showfs, terse, true),
use_printf) use_printf)
@ -417,6 +464,7 @@ impl Stater {
line.split_whitespace().nth(1).map(|s| s.to_owned()) line.split_whitespace().nth(1).map(|s| s.to_owned())
}) })
.collect::<Vec<String>>(); .collect::<Vec<String>>();
// Reverse sort. The longer comes first.
mount_list.sort_by(|a, b| b.cmp(a)); mount_list.sort_by(|a, b| b.cmp(a));
Ok(Stater { Ok(Stater {
@ -619,18 +667,33 @@ impl Stater {
} }
// string // string
// FIXME:
'w' => { 'w' => {
// time of file birth, human-readable; - if unknown // time of file birth, human-readable; - if unknown
arg = "-".to_owned(); arg = if let Some(elapsed) = meta.created()
.ok()
.map(|t| {
t.elapsed().unwrap()
}) {
pretty_time(elapsed.as_secs() as i64,
elapsed.subsec_nanos() as i64)
} else {
"-".to_owned()
};
otype = OutputType::Str; otype = OutputType::Str;
} }
// int // int
// FIXME:
'W' => { 'W' => {
// time of file birth, seconds since Epoch; 0 if unknown // time of file birth, seconds since Epoch; 0 if unknown
arg = format!("{}", 0); arg = if let Some(elapsed) = meta.created()
.ok()
.map(|t| {
t.elapsed().unwrap()
}) {
format!("{}", elapsed.as_secs())
} else {
"0".to_owned()
};
otype = OutputType::Integer; otype = OutputType::Integer;
} }