diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-08-10 13:38:32 -0700 | 
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-08-12 23:18:51 -0700 | 
| commit | 6feb58ed84d8dce2aea35a8be9fd8d7b6883f002 (patch) | |
| tree | bff648e5d7b25990f46933195ae47732ef1e110f | |
| parent | b820748ff5a2bc09b58dd7ac511e0f607d55f2e9 (diff) | |
| download | rust-6feb58ed84d8dce2aea35a8be9fd8d7b6883f002.tar.gz rust-6feb58ed84d8dce2aea35a8be9fd8d7b6883f002.zip  | |
Define integer formats for all widths
Closes #1653
| -rw-r--r-- | src/libstd/fmt/mod.rs | 93 | ||||
| -rw-r--r-- | src/libsyntax/ext/ifmt.rs | 1 | ||||
| -rw-r--r-- | src/test/run-pass/ifmt.rs | 64 | 
3 files changed, 121 insertions, 37 deletions
diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index a25620cfa69..7085147aaee 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -17,7 +17,6 @@ use rt::io::mem::MemWriter; use rt::io; use str; use sys; -use uint; use util; use vec; @@ -238,7 +237,7 @@ impl<'self> Formatter<'self> { } fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) { - do uint::to_str_bytes(value, 10) |buf| { + do ::uint::to_str_bytes(value, 10) |buf| { let valuestr = str::from_bytes_slice(buf); for piece in pieces.iter() { self.run(piece, Some(valuestr)); @@ -314,7 +313,7 @@ impl<'self> Formatter<'self> { // case where the maximum length will matter. let char_len = s.char_len(); if char_len >= max { - let nchars = uint::min(max, char_len); + let nchars = ::uint::min(max, char_len); self.buf.write(s.slice_chars(0, nchars).as_bytes()); return } @@ -409,52 +408,72 @@ impl Char for char { } } -impl Signed for int { - fn fmt(c: &int, f: &mut Formatter) { - do uint::to_str_bytes(c.abs() as uint, 10) |buf| { - f.pad_integral(buf, "", *c >= 0); - } - } -} - -impl Unsigned for uint { - fn fmt(c: &uint, f: &mut Formatter) { - do uint::to_str_bytes(*c, 10) |buf| { - f.pad_integral(buf, "", true); +macro_rules! int_base(($ty:ident, $into:ident, $base:expr, + $name:ident, $prefix:expr) => { + impl $name for $ty { + fn fmt(c: &$ty, f: &mut Formatter) { + do ::$into::to_str_bytes(*c as $into, $base) |buf| { + f.pad_integral(buf, $prefix, true); + } } } -} - -impl Octal for uint { - fn fmt(c: &uint, f: &mut Formatter) { - do uint::to_str_bytes(*c, 8) |buf| { - f.pad_integral(buf, "0o", true); +}) +macro_rules! upper_hex(($ty:ident, $into:ident) => { + impl UpperHex for $ty { + fn fmt(c: &$ty, f: &mut Formatter) { + do ::$into::to_str_bytes(*c as $into, 16) |buf| { + upperhex(buf, f); + } } } -} +}) -impl LowerHex for uint { - fn fmt(c: &uint, f: &mut Formatter) { - do uint::to_str_bytes(*c, 16) |buf| { - f.pad_integral(buf, "0x", true); +// Not sure why, but this causes an "unresolved enum variant, struct or const" +// when inlined into the above macro... +#[doc(hidden)] +pub fn upperhex(buf: &[u8], f: &mut Formatter) { + let mut local = [0u8, ..16]; + for i in ::iterator::range(0, buf.len()) { + local[i] = match buf[i] as char { + 'a' .. 'f' => (buf[i] - 'a' as u8) + 'A' as u8, + c => c as u8, } } + f.pad_integral(local.slice_to(buf.len()), "0x", true); } -impl UpperHex for uint { - fn fmt(c: &uint, f: &mut Formatter) { - do uint::to_str_bytes(*c, 16) |buf| { - let mut local = [0u8, ..16]; - for (l, &b) in local.mut_iter().zip(buf.iter()) { - *l = match b as char { - 'a' .. 'f' => (b - 'a' as u8) + 'A' as u8, - _ => b, - }; +// FIXME(#4375) shouldn't need an inner module +macro_rules! integer(($signed:ident, $unsigned:ident) => { + mod $signed { + use super::*; + + // Signed is special because it actuall emits the negative sign, + // nothing else should do that, however. + impl Signed for $signed { + fn fmt(c: &$signed, f: &mut Formatter) { + do ::$unsigned::to_str_bytes(c.abs() as $unsigned, 10) |buf| { + f.pad_integral(buf, "", *c >= 0); + } } - f.pad_integral(local.slice_to(buf.len()), "0x", true); } + int_base!($signed, $unsigned, 2, Binary, "0b") + int_base!($signed, $unsigned, 8, Octal, "0o") + int_base!($signed, $unsigned, 16, LowerHex, "0x") + upper_hex!($signed, $unsigned) + + int_base!($unsigned, $unsigned, 2, Binary, "0b") + int_base!($unsigned, $unsigned, 8, Octal, "0o") + int_base!($unsigned, $unsigned, 10, Unsigned, "") + int_base!($unsigned, $unsigned, 16, LowerHex, "0x") + upper_hex!($unsigned, $unsigned) } -} +}) + +integer!(int, uint) +integer!(i8, u8) +integer!(i16, u16) +integer!(i32, u32) +integer!(i64, u64) impl<T> Poly for T { fn fmt(t: &T, f: &mut Formatter) { diff --git a/src/libsyntax/ext/ifmt.rs b/src/libsyntax/ext/ifmt.rs index 66b091849c0..6dda3fc26e8 100644 --- a/src/libsyntax/ext/ifmt.rs +++ b/src/libsyntax/ext/ifmt.rs @@ -638,6 +638,7 @@ impl Context { "X" => "UpperHex", "s" => "String", "p" => "Pointer", + "t" => "Binary", _ => { self.ecx.span_err(sp, fmt!("unknown format trait \ `%s`", tyname)); diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index df61ac76d36..adb19e23c03 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -91,6 +91,70 @@ pub fn main() { t!(ifmt!("{:-#s}", "a"), "a"); t!(ifmt!("{:+#s}", "a"), "a"); + // Formatting integers should select the right implementation based off the + // type of the argument. Also, hex/octal/binary should be defined for + // integers, but they shouldn't emit the negative sign. + t!(ifmt!("{:d}", -1i), "-1"); + t!(ifmt!("{:d}", -1i8), "1"); + t!(ifmt!("{:d}", -1i16), "1"); + t!(ifmt!("{:d}", -1i32), "1"); + t!(ifmt!("{:d}", -1i64), "1"); + t!(ifmt!("{:t}", -1i), "1"); + t!(ifmt!("{:t}", -1i8), "1"); + t!(ifmt!("{:t}", -1i16), "1"); + t!(ifmt!("{:t}", -1i32), "1"); + t!(ifmt!("{:t}", -1i64), "1"); + t!(ifmt!("{:x}", -1i), "1"); + t!(ifmt!("{:x}", -1i8), "1"); + t!(ifmt!("{:x}", -1i16), "1"); + t!(ifmt!("{:x}", -1i32), "1"); + t!(ifmt!("{:x}", -1i64), "1"); + t!(ifmt!("{:X}", -1i), "1"); + t!(ifmt!("{:X}", -1i8), "1"); + t!(ifmt!("{:X}", -1i16), "1"); + t!(ifmt!("{:X}", -1i32), "1"); + t!(ifmt!("{:X}", -1i64), "1"); + t!(ifmt!("{:o}", -1i), "1"); + t!(ifmt!("{:o}", -1i8), "1"); + t!(ifmt!("{:o}", -1i16), "1"); + t!(ifmt!("{:o}", -1i32), "1"); + t!(ifmt!("{:o}", -1i64), "1"); + + t!(ifmt!("{:d}", 1u), "1"); + t!(ifmt!("{:d}", 1u8), "1"); + t!(ifmt!("{:d}", 1u16), "1"); + t!(ifmt!("{:d}", 1u32), "1"); + t!(ifmt!("{:d}", 1u64), "1"); + t!(ifmt!("{:t}", 1u), "1"); + t!(ifmt!("{:t}", 1u8), "1"); + t!(ifmt!("{:t}", 1u16), "1"); + t!(ifmt!("{:t}", 1u32), "1"); + t!(ifmt!("{:t}", 1u64), "1"); + t!(ifmt!("{:x}", 1u), "1"); + t!(ifmt!("{:x}", 1u8), "1"); + t!(ifmt!("{:x}", 1u16), "1"); + t!(ifmt!("{:x}", 1u32), "1"); + t!(ifmt!("{:x}", 1u64), "1"); + t!(ifmt!("{:X}", 1u), "1"); + t!(ifmt!("{:X}", 1u8), "1"); + t!(ifmt!("{:X}", 1u16), "1"); + t!(ifmt!("{:X}", 1u32), "1"); + t!(ifmt!("{:X}", 1u64), "1"); + t!(ifmt!("{:o}", 1u), "1"); + t!(ifmt!("{:o}", 1u8), "1"); + t!(ifmt!("{:o}", 1u16), "1"); + t!(ifmt!("{:o}", 1u32), "1"); + t!(ifmt!("{:o}", 1u64), "1"); + + // Test the flags for formatting integers + t!(ifmt!("{:3d}", 1), "1 "); + t!(ifmt!("{:>3d}", 1), " 1"); + t!(ifmt!("{:#d}", 1), "1"); + t!(ifmt!("{:#x}", 10u), "0xa"); + t!(ifmt!("{:#X}", 10u), "0xA"); + t!(ifmt!("{:#5x}", 10u), "0xa "); + t!(ifmt!("{:#o}", 10u), "0o12"); + // Precision overrides 0-padding // FIXME #2481: Recent gcc's report some of these as warnings /*t!(ifmt!("{:0>6.5d}", 0), ~" 00000");*/  | 
