about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-08-10 13:38:32 -0700
committerAlex Crichton <alex@alexcrichton.com>2013-08-12 23:18:51 -0700
commit6feb58ed84d8dce2aea35a8be9fd8d7b6883f002 (patch)
treebff648e5d7b25990f46933195ae47732ef1e110f
parentb820748ff5a2bc09b58dd7ac511e0f607d55f2e9 (diff)
downloadrust-6feb58ed84d8dce2aea35a8be9fd8d7b6883f002.tar.gz
rust-6feb58ed84d8dce2aea35a8be9fd8d7b6883f002.zip
Define integer formats for all widths
Closes #1653
-rw-r--r--src/libstd/fmt/mod.rs93
-rw-r--r--src/libsyntax/ext/ifmt.rs1
-rw-r--r--src/test/run-pass/ifmt.rs64
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");*/