|  | @@ -1,154 +1,144 @@
 | 
											
												
													
														|  |  use alloc::string::String;
 |  |  use alloc::string::String;
 | 
											
												
													
														|  |  use platform::types::*;
 |  |  use platform::types::*;
 | 
											
												
													
														|  | -use platform::Write;
 |  | 
 | 
											
												
													
														|  | 
 |  | +use platform::{self, Write};
 | 
											
												
													
														|  |  use tm;
 |  |  use tm;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  pub unsafe fn strftime<W: Write>(
 |  |  pub unsafe fn strftime<W: Write>(
 | 
											
												
													
														|  | -    toplevel: bool,
 |  | 
 | 
											
												
													
														|  | -    mut w: &mut W,
 |  | 
 | 
											
												
													
														|  | -    maxsize: usize,
 |  | 
 | 
											
												
													
														|  | -    mut format: *const c_char,
 |  | 
 | 
											
												
													
														|  | 
 |  | +    w: &mut W,
 | 
											
												
													
														|  | 
 |  | +    format: *const c_char,
 | 
											
												
													
														|  |      t: *const tm,
 |  |      t: *const tm,
 | 
											
												
													
														|  |  ) -> size_t {
 |  |  ) -> size_t {
 | 
											
												
													
														|  | -    let mut written = 0;
 |  | 
 | 
											
												
													
														|  | -    if toplevel {
 |  | 
 | 
											
												
													
														|  | -        // Reserve nul byte
 |  | 
 | 
											
												
													
														|  | -        written += 1;
 |  | 
 | 
											
												
													
														|  | -    }
 |  | 
 | 
											
												
													
														|  | -    macro_rules! w {
 |  | 
 | 
											
												
													
														|  | -        (reserve $amount:expr) => {{
 |  | 
 | 
											
												
													
														|  | -            if written + $amount > maxsize {
 |  | 
 | 
											
												
													
														|  | -                return 0;
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            written += $amount;
 |  | 
 | 
											
												
													
														|  | -        }};
 |  | 
 | 
											
												
													
														|  | -        (byte $b:expr) => {{
 |  | 
 | 
											
												
													
														|  | -            w!(reserve 1);
 |  | 
 | 
											
												
													
														|  | -            if w.write_u8($b).is_err() {
 |  | 
 | 
											
												
													
														|  | -                return !0;
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -        }};
 |  | 
 | 
											
												
													
														|  | -        (char $chr:expr) => {{
 |  | 
 | 
											
												
													
														|  | -            w!(reserve $chr.len_utf8());
 |  | 
 | 
											
												
													
														|  | -            if w.write_char($chr).is_err() {
 |  | 
 | 
											
												
													
														|  | -                return !0;
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -        }};
 |  | 
 | 
											
												
													
														|  | -        (recurse $fmt:expr) => {{
 |  | 
 | 
											
												
													
														|  | -            let mut fmt = String::with_capacity($fmt.len() + 1);
 |  | 
 | 
											
												
													
														|  | -            fmt.push_str($fmt);
 |  | 
 | 
											
												
													
														|  | -            fmt.push('\0');
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -            let count = strftime(false, w, maxsize - written, fmt.as_ptr() as *mut c_char, t);
 |  | 
 | 
											
												
													
														|  | -            if count == 0 {
 |  | 
 | 
											
												
													
														|  | -                return 0;
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -            written += count;
 |  | 
 | 
											
												
													
														|  | -            assert!(written <= maxsize);
 |  | 
 | 
											
												
													
														|  | -        }};
 |  | 
 | 
											
												
													
														|  | -        ($str:expr) => {{
 |  | 
 | 
											
												
													
														|  | -            w!(reserve $str.len());
 |  | 
 | 
											
												
													
														|  | -            if w.write_str($str).is_err() {
 |  | 
 | 
											
												
													
														|  | -                return !0;
 |  | 
 | 
											
												
													
														|  | -            }
 |  | 
 | 
											
												
													
														|  | -        }};
 |  | 
 | 
											
												
													
														|  | -        ($fmt:expr, $($args:expr),+) => {{
 |  | 
 | 
											
												
													
														|  | -            // Would use write!() if I could get the length written
 |  | 
 | 
											
												
													
														|  | -            w!(&format!($fmt, $($args),+))
 |  | 
 | 
											
												
													
														|  | -        }};
 |  | 
 | 
											
												
													
														|  | -    }
 |  | 
 | 
											
												
													
														|  | -    const WDAYS: [&'static str; 7] = [
 |  | 
 | 
											
												
													
														|  | -        "Sunday",
 |  | 
 | 
											
												
													
														|  | -        "Monday",
 |  | 
 | 
											
												
													
														|  | -        "Tuesday",
 |  | 
 | 
											
												
													
														|  | -        "Wednesday",
 |  | 
 | 
											
												
													
														|  | -        "Thursday",
 |  | 
 | 
											
												
													
														|  | -        "Friday",
 |  | 
 | 
											
												
													
														|  | -        "Saturday",
 |  | 
 | 
											
												
													
														|  | -    ];
 |  | 
 | 
											
												
													
														|  | -    const MONTHS: [&'static str; 12] = [
 |  | 
 | 
											
												
													
														|  | -        "January",
 |  | 
 | 
											
												
													
														|  | -        "Febuary",
 |  | 
 | 
											
												
													
														|  | -        "March",
 |  | 
 | 
											
												
													
														|  | -        "April",
 |  | 
 | 
											
												
													
														|  | -        "May",
 |  | 
 | 
											
												
													
														|  | -        "June",
 |  | 
 | 
											
												
													
														|  | -        "July",
 |  | 
 | 
											
												
													
														|  | -        "August",
 |  | 
 | 
											
												
													
														|  | -        "September",
 |  | 
 | 
											
												
													
														|  | -        "October",
 |  | 
 | 
											
												
													
														|  | -        "November",
 |  | 
 | 
											
												
													
														|  | -        "December",
 |  | 
 | 
											
												
													
														|  | -    ];
 |  | 
 | 
											
												
													
														|  | 
 |  | +    pub unsafe fn inner_strftime<W: Write>(
 | 
											
												
													
														|  | 
 |  | +        mut w: &mut W,
 | 
											
												
													
														|  | 
 |  | +        mut format: *const c_char,
 | 
											
												
													
														|  | 
 |  | +        t: *const tm,
 | 
											
												
													
														|  | 
 |  | +    ) -> bool {
 | 
											
												
													
														|  | 
 |  | +        macro_rules! w {
 | 
											
												
													
														|  | 
 |  | +            (byte $b:expr) => {{
 | 
											
												
													
														|  | 
 |  | +                if w.write_u8($b).is_err() {
 | 
											
												
													
														|  | 
 |  | +                    return false;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }};
 | 
											
												
													
														|  | 
 |  | +            (char $chr:expr) => {{
 | 
											
												
													
														|  | 
 |  | +                if w.write_char($chr).is_err() {
 | 
											
												
													
														|  | 
 |  | +                    return false;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }};
 | 
											
												
													
														|  | 
 |  | +            (recurse $fmt:expr) => {{
 | 
											
												
													
														|  | 
 |  | +                let mut fmt = String::with_capacity($fmt.len() + 1);
 | 
											
												
													
														|  | 
 |  | +                fmt.push_str($fmt);
 | 
											
												
													
														|  | 
 |  | +                fmt.push('\0');
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    while *format != 0 {
 |  | 
 | 
											
												
													
														|  | -        if *format as u8 != b'%' {
 |  | 
 | 
											
												
													
														|  | -            w!(byte(*format as u8));
 |  | 
 | 
											
												
													
														|  | -            format = format.offset(1);
 |  | 
 | 
											
												
													
														|  | -            continue;
 |  | 
 | 
											
												
													
														|  | 
 |  | +                if !inner_strftime(w, fmt.as_ptr() as *mut c_char, t) {
 | 
											
												
													
														|  | 
 |  | +                    return false;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }};
 | 
											
												
													
														|  | 
 |  | +            ($str:expr) => {{
 | 
											
												
													
														|  | 
 |  | +                if w.write_str($str).is_err() {
 | 
											
												
													
														|  | 
 |  | +                    return false;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }};
 | 
											
												
													
														|  | 
 |  | +            ($fmt:expr, $($args:expr),+) => {{
 | 
											
												
													
														|  | 
 |  | +                // Would use write!() if I could get the length written
 | 
											
												
													
														|  | 
 |  | +                if write!(w, $fmt, $($args),+).is_err() {
 | 
											
												
													
														|  | 
 |  | +                    return false;
 | 
											
												
													
														|  | 
 |  | +                }
 | 
											
												
													
														|  | 
 |  | +            }};
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  | 
 |  | +        const WDAYS: [&'static str; 7] = [
 | 
											
												
													
														|  | 
 |  | +            "Sunday",
 | 
											
												
													
														|  | 
 |  | +            "Monday",
 | 
											
												
													
														|  | 
 |  | +            "Tuesday",
 | 
											
												
													
														|  | 
 |  | +            "Wednesday",
 | 
											
												
													
														|  | 
 |  | +            "Thursday",
 | 
											
												
													
														|  | 
 |  | +            "Friday",
 | 
											
												
													
														|  | 
 |  | +            "Saturday",
 | 
											
												
													
														|  | 
 |  | +        ];
 | 
											
												
													
														|  | 
 |  | +        const MONTHS: [&'static str; 12] = [
 | 
											
												
													
														|  | 
 |  | +            "January",
 | 
											
												
													
														|  | 
 |  | +            "Febuary",
 | 
											
												
													
														|  | 
 |  | +            "March",
 | 
											
												
													
														|  | 
 |  | +            "April",
 | 
											
												
													
														|  | 
 |  | +            "May",
 | 
											
												
													
														|  | 
 |  | +            "June",
 | 
											
												
													
														|  | 
 |  | +            "July",
 | 
											
												
													
														|  | 
 |  | +            "August",
 | 
											
												
													
														|  | 
 |  | +            "September",
 | 
											
												
													
														|  | 
 |  | +            "October",
 | 
											
												
													
														|  | 
 |  | +            "November",
 | 
											
												
													
														|  | 
 |  | +            "December",
 | 
											
												
													
														|  | 
 |  | +        ];
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        format = format.offset(1);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        while *format != 0 {
 | 
											
												
													
														|  | 
 |  | +            if *format as u8 != b'%' {
 | 
											
												
													
														|  | 
 |  | +                w!(byte *format as u8);
 | 
											
												
													
														|  | 
 |  | +                format = format.offset(1);
 | 
											
												
													
														|  | 
 |  | +                continue;
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        if *format as u8 == b'E' || *format as u8 == b'O' {
 |  | 
 | 
											
												
													
														|  | -            // Ignore because these do nothing without locale
 |  | 
 | 
											
												
													
														|  |              format = format.offset(1);
 |  |              format = format.offset(1);
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        match *format as u8 {
 |  | 
 | 
											
												
													
														|  | -            b'%' => w!(byte b'%'),
 |  | 
 | 
											
												
													
														|  | -            b'n' => w!(byte b'\n'),
 |  | 
 | 
											
												
													
														|  | -            b't' => w!(byte b'\t'),
 |  | 
 | 
											
												
													
														|  | -            b'a' => w!(&WDAYS[(*t).tm_wday as usize][..3]),
 |  | 
 | 
											
												
													
														|  | -            b'A' => w!(WDAYS[(*t).tm_wday as usize]),
 |  | 
 | 
											
												
													
														|  | -            b'b' | b'h' => w!(&MONTHS[(*t).tm_mon as usize][..3]),
 |  | 
 | 
											
												
													
														|  | -            b'B' => w!(MONTHS[(*t).tm_mon as usize]),
 |  | 
 | 
											
												
													
														|  | -            b'C' => {
 |  | 
 | 
											
												
													
														|  | -                let mut year = (*t).tm_year / 100;
 |  | 
 | 
											
												
													
														|  | -                // Round up
 |  | 
 | 
											
												
													
														|  | -                if (*t).tm_year % 100 != 0 {
 |  | 
 | 
											
												
													
														|  | -                    year += 1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            if *format as u8 == b'E' || *format as u8 == b'O' {
 | 
											
												
													
														|  | 
 |  | +                // Ignore because these do nothing without locale
 | 
											
												
													
														|  | 
 |  | +                format = format.offset(1);
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            match *format as u8 {
 | 
											
												
													
														|  | 
 |  | +                b'%' => w!(byte b'%'),
 | 
											
												
													
														|  | 
 |  | +                b'n' => w!(byte b'\n'),
 | 
											
												
													
														|  | 
 |  | +                b't' => w!(byte b'\t'),
 | 
											
												
													
														|  | 
 |  | +                b'a' => w!(&WDAYS[(*t).tm_wday as usize][..3]),
 | 
											
												
													
														|  | 
 |  | +                b'A' => w!(WDAYS[(*t).tm_wday as usize]),
 | 
											
												
													
														|  | 
 |  | +                b'b' | b'h' => w!(&MONTHS[(*t).tm_mon as usize][..3]),
 | 
											
												
													
														|  | 
 |  | +                b'B' => w!(MONTHS[(*t).tm_mon as usize]),
 | 
											
												
													
														|  | 
 |  | +                b'C' => {
 | 
											
												
													
														|  | 
 |  | +                    let mut year = (*t).tm_year / 100;
 | 
											
												
													
														|  | 
 |  | +                    // Round up
 | 
											
												
													
														|  | 
 |  | +                    if (*t).tm_year % 100 != 0 {
 | 
											
												
													
														|  | 
 |  | +                        year += 1;
 | 
											
												
													
														|  | 
 |  | +                    }
 | 
											
												
													
														|  | 
 |  | +                    w!("{:02}", year + 19);
 | 
											
												
													
														|  |                  }
 |  |                  }
 | 
											
												
													
														|  | -                w!("{:02}", year + 19);
 |  | 
 | 
											
												
													
														|  | 
 |  | +                b'd' => w!("{:02}", (*t).tm_mday),
 | 
											
												
													
														|  | 
 |  | +                b'D' => w!(recurse "%m/%d/%y"),
 | 
											
												
													
														|  | 
 |  | +                b'e' => w!("{:2}", (*t).tm_mday),
 | 
											
												
													
														|  | 
 |  | +                b'F' => w!(recurse "%Y-%m-%d"),
 | 
											
												
													
														|  | 
 |  | +                b'H' => w!("{:02}", (*t).tm_hour),
 | 
											
												
													
														|  | 
 |  | +                b'I' => w!("{:02}", ((*t).tm_hour + 12 - 1) % 12 + 1),
 | 
											
												
													
														|  | 
 |  | +                b'j' => w!("{:03}", (*t).tm_yday),
 | 
											
												
													
														|  | 
 |  | +                b'k' => w!("{:2}", (*t).tm_hour),
 | 
											
												
													
														|  | 
 |  | +                b'l' => w!("{:2}", ((*t).tm_hour + 12 - 1) % 12 + 1),
 | 
											
												
													
														|  | 
 |  | +                b'm' => w!("{:02}", (*t).tm_mon + 1),
 | 
											
												
													
														|  | 
 |  | +                b'M' => w!("{:02}", (*t).tm_min),
 | 
											
												
													
														|  | 
 |  | +                b'p' => w!(if (*t).tm_hour < 12 { "AM" } else { "PM" }),
 | 
											
												
													
														|  | 
 |  | +                b'P' => w!(if (*t).tm_hour < 12 { "am" } else { "pm" }),
 | 
											
												
													
														|  | 
 |  | +                b'r' => w!(recurse "%I:%M:%S %p"),
 | 
											
												
													
														|  | 
 |  | +                b'R' => w!(recurse "%H:%M"),
 | 
											
												
													
														|  | 
 |  | +                // Nothing is modified in mktime, but the C standard of course requires a mutable pointer ._.
 | 
											
												
													
														|  | 
 |  | +                b's' => w!("{}", ::mktime(t as *mut tm)),
 | 
											
												
													
														|  | 
 |  | +                b'S' => w!("{:02}", (*t).tm_sec),
 | 
											
												
													
														|  | 
 |  | +                b'T' => w!(recurse "%H:%M:%S"),
 | 
											
												
													
														|  | 
 |  | +                b'u' => w!("{}", ((*t).tm_wday + 7 - 1) % 7 + 1),
 | 
											
												
													
														|  | 
 |  | +                b'U' => w!("{}", ((*t).tm_yday + 7 - (*t).tm_wday) / 7),
 | 
											
												
													
														|  | 
 |  | +                b'w' => w!("{}", (*t).tm_wday),
 | 
											
												
													
														|  | 
 |  | +                b'W' => w!("{}", ((*t).tm_yday + 7 - ((*t).tm_wday + 6) % 7) / 7),
 | 
											
												
													
														|  | 
 |  | +                b'y' => w!("{:02}", (*t).tm_year % 100),
 | 
											
												
													
														|  | 
 |  | +                b'Y' => w!("{}", (*t).tm_year + 1900),
 | 
											
												
													
														|  | 
 |  | +                b'z' => w!("+0000"), // TODO
 | 
											
												
													
														|  | 
 |  | +                b'Z' => w!("UTC"),   // TODO
 | 
											
												
													
														|  | 
 |  | +                b'+' => w!(recurse "%a %b %d %T %Z %Y"),
 | 
											
												
													
														|  | 
 |  | +                _ => return false,
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  | -            b'd' => w!("{:02}", (*t).tm_mday),
 |  | 
 | 
											
												
													
														|  | -            b'D' => w!(recurse "%m/%d/%y"),
 |  | 
 | 
											
												
													
														|  | -            b'e' => w!("{:2}", (*t).tm_mday),
 |  | 
 | 
											
												
													
														|  | -            b'F' => w!(recurse "%Y-%m-%d"),
 |  | 
 | 
											
												
													
														|  | -            b'H' => w!("{:02}", (*t).tm_hour),
 |  | 
 | 
											
												
													
														|  | -            b'I' => w!("{:02}", ((*t).tm_hour + 12 - 1) % 12 + 1),
 |  | 
 | 
											
												
													
														|  | -            b'j' => w!("{:03}", (*t).tm_yday),
 |  | 
 | 
											
												
													
														|  | -            b'k' => w!("{:2}", (*t).tm_hour),
 |  | 
 | 
											
												
													
														|  | -            b'l' => w!("{:2}", ((*t).tm_hour + 12 - 1) % 12 + 1),
 |  | 
 | 
											
												
													
														|  | -            b'm' => w!("{:02}", (*t).tm_mon + 1),
 |  | 
 | 
											
												
													
														|  | -            b'M' => w!("{:02}", (*t).tm_min),
 |  | 
 | 
											
												
													
														|  | -            b'p' => w!(if (*t).tm_hour < 12 { "AM" } else { "PM" }),
 |  | 
 | 
											
												
													
														|  | -            b'P' => w!(if (*t).tm_hour < 12 { "am" } else { "pm" }),
 |  | 
 | 
											
												
													
														|  | -            b'r' => w!(recurse "%I:%M:%S %p"),
 |  | 
 | 
											
												
													
														|  | -            b'R' => w!(recurse "%H:%M"),
 |  | 
 | 
											
												
													
														|  | -            // Nothing is modified in mktime, but the C standard of course requires a mutable pointer ._.
 |  | 
 | 
											
												
													
														|  | -            b's' => w!("{}", ::mktime(t as *mut tm)),
 |  | 
 | 
											
												
													
														|  | -            b'S' => w!("{:02}", (*t).tm_sec),
 |  | 
 | 
											
												
													
														|  | -            b'T' => w!(recurse "%H:%M:%S"),
 |  | 
 | 
											
												
													
														|  | -            b'u' => w!("{}", ((*t).tm_wday + 7 - 1) % 7 + 1),
 |  | 
 | 
											
												
													
														|  | -            b'U' => w!("{}", ((*t).tm_yday + 7 - (*t).tm_wday) / 7),
 |  | 
 | 
											
												
													
														|  | -            b'w' => w!("{}", (*t).tm_wday),
 |  | 
 | 
											
												
													
														|  | -            b'W' => w!("{}", ((*t).tm_yday + 7 - ((*t).tm_wday + 6) % 7) / 7),
 |  | 
 | 
											
												
													
														|  | -            b'y' => w!("{:02}", (*t).tm_year % 100),
 |  | 
 | 
											
												
													
														|  | -            b'Y' => w!("{}", (*t).tm_year + 1900),
 |  | 
 | 
											
												
													
														|  | -            b'z' => w!("+0000"), // TODO
 |  | 
 | 
											
												
													
														|  | -            b'Z' => w!("UTC"),   // TODO
 |  | 
 | 
											
												
													
														|  | -            b'+' => w!(recurse "%a %b %d %T %Z %Y"),
 |  | 
 | 
											
												
													
														|  | -            _ => return 0,
 |  | 
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        format = format.offset(1);
 |  | 
 | 
											
												
													
														|  | -    }
 |  | 
 | 
											
												
													
														|  | -    if toplevel {
 |  | 
 | 
											
												
													
														|  | -        // nul byte is already counted in written
 |  | 
 | 
											
												
													
														|  | -        if w.write_u8(0).is_err() {
 |  | 
 | 
											
												
													
														|  | -            return !0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            format = format.offset(1);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  | 
 |  | +        true
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | -    written
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    let mut w = platform::CountingWriter::new(w);
 | 
											
												
													
														|  | 
 |  | +    if !inner_strftime(&mut w, format, t) {
 | 
											
												
													
														|  | 
 |  | +        return 0;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    w.written
 | 
											
												
													
														|  |  }
 |  |  }
 |