Skip to content

Commit 6feb58e

Browse files
committed
Define integer formats for all widths
Closes #1653
1 parent b820748 commit 6feb58e

File tree

3 files changed

+121
-37
lines changed

3 files changed

+121
-37
lines changed

src/libstd/fmt/mod.rs

+56-37
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use rt::io::mem::MemWriter;
1717
use rt::io;
1818
use str;
1919
use sys;
20-
use uint;
2120
use util;
2221
use vec;
2322

@@ -238,7 +237,7 @@ impl<'self> Formatter<'self> {
238237
}
239238

240239
fn runplural(&mut self, value: uint, pieces: &[rt::Piece]) {
241-
do uint::to_str_bytes(value, 10) |buf| {
240+
do ::uint::to_str_bytes(value, 10) |buf| {
242241
let valuestr = str::from_bytes_slice(buf);
243242
for piece in pieces.iter() {
244243
self.run(piece, Some(valuestr));
@@ -314,7 +313,7 @@ impl<'self> Formatter<'self> {
314313
// case where the maximum length will matter.
315314
let char_len = s.char_len();
316315
if char_len >= max {
317-
let nchars = uint::min(max, char_len);
316+
let nchars = ::uint::min(max, char_len);
318317
self.buf.write(s.slice_chars(0, nchars).as_bytes());
319318
return
320319
}
@@ -409,52 +408,72 @@ impl Char for char {
409408
}
410409
}
411410

412-
impl Signed for int {
413-
fn fmt(c: &int, f: &mut Formatter) {
414-
do uint::to_str_bytes(c.abs() as uint, 10) |buf| {
415-
f.pad_integral(buf, "", *c >= 0);
416-
}
417-
}
418-
}
419-
420-
impl Unsigned for uint {
421-
fn fmt(c: &uint, f: &mut Formatter) {
422-
do uint::to_str_bytes(*c, 10) |buf| {
423-
f.pad_integral(buf, "", true);
411+
macro_rules! int_base(($ty:ident, $into:ident, $base:expr,
412+
$name:ident, $prefix:expr) => {
413+
impl $name for $ty {
414+
fn fmt(c: &$ty, f: &mut Formatter) {
415+
do ::$into::to_str_bytes(*c as $into, $base) |buf| {
416+
f.pad_integral(buf, $prefix, true);
417+
}
424418
}
425419
}
426-
}
427-
428-
impl Octal for uint {
429-
fn fmt(c: &uint, f: &mut Formatter) {
430-
do uint::to_str_bytes(*c, 8) |buf| {
431-
f.pad_integral(buf, "0o", true);
420+
})
421+
macro_rules! upper_hex(($ty:ident, $into:ident) => {
422+
impl UpperHex for $ty {
423+
fn fmt(c: &$ty, f: &mut Formatter) {
424+
do ::$into::to_str_bytes(*c as $into, 16) |buf| {
425+
upperhex(buf, f);
426+
}
432427
}
433428
}
434-
}
429+
})
435430

436-
impl LowerHex for uint {
437-
fn fmt(c: &uint, f: &mut Formatter) {
438-
do uint::to_str_bytes(*c, 16) |buf| {
439-
f.pad_integral(buf, "0x", true);
431+
// Not sure why, but this causes an "unresolved enum variant, struct or const"
432+
// when inlined into the above macro...
433+
#[doc(hidden)]
434+
pub fn upperhex(buf: &[u8], f: &mut Formatter) {
435+
let mut local = [0u8, ..16];
436+
for i in ::iterator::range(0, buf.len()) {
437+
local[i] = match buf[i] as char {
438+
'a' .. 'f' => (buf[i] - 'a' as u8) + 'A' as u8,
439+
c => c as u8,
440440
}
441441
}
442+
f.pad_integral(local.slice_to(buf.len()), "0x", true);
442443
}
443444

444-
impl UpperHex for uint {
445-
fn fmt(c: &uint, f: &mut Formatter) {
446-
do uint::to_str_bytes(*c, 16) |buf| {
447-
let mut local = [0u8, ..16];
448-
for (l, &b) in local.mut_iter().zip(buf.iter()) {
449-
*l = match b as char {
450-
'a' .. 'f' => (b - 'a' as u8) + 'A' as u8,
451-
_ => b,
452-
};
445+
// FIXME(#4375) shouldn't need an inner module
446+
macro_rules! integer(($signed:ident, $unsigned:ident) => {
447+
mod $signed {
448+
use super::*;
449+
450+
// Signed is special because it actuall emits the negative sign,
451+
// nothing else should do that, however.
452+
impl Signed for $signed {
453+
fn fmt(c: &$signed, f: &mut Formatter) {
454+
do ::$unsigned::to_str_bytes(c.abs() as $unsigned, 10) |buf| {
455+
f.pad_integral(buf, "", *c >= 0);
456+
}
453457
}
454-
f.pad_integral(local.slice_to(buf.len()), "0x", true);
455458
}
459+
int_base!($signed, $unsigned, 2, Binary, "0b")
460+
int_base!($signed, $unsigned, 8, Octal, "0o")
461+
int_base!($signed, $unsigned, 16, LowerHex, "0x")
462+
upper_hex!($signed, $unsigned)
463+
464+
int_base!($unsigned, $unsigned, 2, Binary, "0b")
465+
int_base!($unsigned, $unsigned, 8, Octal, "0o")
466+
int_base!($unsigned, $unsigned, 10, Unsigned, "")
467+
int_base!($unsigned, $unsigned, 16, LowerHex, "0x")
468+
upper_hex!($unsigned, $unsigned)
456469
}
457-
}
470+
})
471+
472+
integer!(int, uint)
473+
integer!(i8, u8)
474+
integer!(i16, u16)
475+
integer!(i32, u32)
476+
integer!(i64, u64)
458477

459478
impl<T> Poly for T {
460479
fn fmt(t: &T, f: &mut Formatter) {

src/libsyntax/ext/ifmt.rs

+1
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ impl Context {
638638
"X" => "UpperHex",
639639
"s" => "String",
640640
"p" => "Pointer",
641+
"t" => "Binary",
641642
_ => {
642643
self.ecx.span_err(sp, fmt!("unknown format trait \
643644
`%s`", tyname));

src/test/run-pass/ifmt.rs

+64
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,70 @@ pub fn main() {
9191
t!(ifmt!("{:-#s}", "a"), "a");
9292
t!(ifmt!("{:+#s}", "a"), "a");
9393

94+
// Formatting integers should select the right implementation based off the
95+
// type of the argument. Also, hex/octal/binary should be defined for
96+
// integers, but they shouldn't emit the negative sign.
97+
t!(ifmt!("{:d}", -1i), "-1");
98+
t!(ifmt!("{:d}", -1i8), "1");
99+
t!(ifmt!("{:d}", -1i16), "1");
100+
t!(ifmt!("{:d}", -1i32), "1");
101+
t!(ifmt!("{:d}", -1i64), "1");
102+
t!(ifmt!("{:t}", -1i), "1");
103+
t!(ifmt!("{:t}", -1i8), "1");
104+
t!(ifmt!("{:t}", -1i16), "1");
105+
t!(ifmt!("{:t}", -1i32), "1");
106+
t!(ifmt!("{:t}", -1i64), "1");
107+
t!(ifmt!("{:x}", -1i), "1");
108+
t!(ifmt!("{:x}", -1i8), "1");
109+
t!(ifmt!("{:x}", -1i16), "1");
110+
t!(ifmt!("{:x}", -1i32), "1");
111+
t!(ifmt!("{:x}", -1i64), "1");
112+
t!(ifmt!("{:X}", -1i), "1");
113+
t!(ifmt!("{:X}", -1i8), "1");
114+
t!(ifmt!("{:X}", -1i16), "1");
115+
t!(ifmt!("{:X}", -1i32), "1");
116+
t!(ifmt!("{:X}", -1i64), "1");
117+
t!(ifmt!("{:o}", -1i), "1");
118+
t!(ifmt!("{:o}", -1i8), "1");
119+
t!(ifmt!("{:o}", -1i16), "1");
120+
t!(ifmt!("{:o}", -1i32), "1");
121+
t!(ifmt!("{:o}", -1i64), "1");
122+
123+
t!(ifmt!("{:d}", 1u), "1");
124+
t!(ifmt!("{:d}", 1u8), "1");
125+
t!(ifmt!("{:d}", 1u16), "1");
126+
t!(ifmt!("{:d}", 1u32), "1");
127+
t!(ifmt!("{:d}", 1u64), "1");
128+
t!(ifmt!("{:t}", 1u), "1");
129+
t!(ifmt!("{:t}", 1u8), "1");
130+
t!(ifmt!("{:t}", 1u16), "1");
131+
t!(ifmt!("{:t}", 1u32), "1");
132+
t!(ifmt!("{:t}", 1u64), "1");
133+
t!(ifmt!("{:x}", 1u), "1");
134+
t!(ifmt!("{:x}", 1u8), "1");
135+
t!(ifmt!("{:x}", 1u16), "1");
136+
t!(ifmt!("{:x}", 1u32), "1");
137+
t!(ifmt!("{:x}", 1u64), "1");
138+
t!(ifmt!("{:X}", 1u), "1");
139+
t!(ifmt!("{:X}", 1u8), "1");
140+
t!(ifmt!("{:X}", 1u16), "1");
141+
t!(ifmt!("{:X}", 1u32), "1");
142+
t!(ifmt!("{:X}", 1u64), "1");
143+
t!(ifmt!("{:o}", 1u), "1");
144+
t!(ifmt!("{:o}", 1u8), "1");
145+
t!(ifmt!("{:o}", 1u16), "1");
146+
t!(ifmt!("{:o}", 1u32), "1");
147+
t!(ifmt!("{:o}", 1u64), "1");
148+
149+
// Test the flags for formatting integers
150+
t!(ifmt!("{:3d}", 1), "1 ");
151+
t!(ifmt!("{:>3d}", 1), " 1");
152+
t!(ifmt!("{:#d}", 1), "1");
153+
t!(ifmt!("{:#x}", 10u), "0xa");
154+
t!(ifmt!("{:#X}", 10u), "0xA");
155+
t!(ifmt!("{:#5x}", 10u), "0xa ");
156+
t!(ifmt!("{:#o}", 10u), "0o12");
157+
94158
// Precision overrides 0-padding
95159
// FIXME #2481: Recent gcc's report some of these as warnings
96160
/*t!(ifmt!("{:0>6.5d}", 0), ~" 00000");*/

0 commit comments

Comments
 (0)