aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <[email protected]>2011-04-18 20:58:45 -0400
committerBrian Anderson <[email protected]>2011-04-18 21:36:04 -0400
commitd4f1a48111673c158d1c9493be4a87eaa24064b1 (patch)
tree08dddcf2a24b2b1a9b2dd4d4d61eccc33b4b0df3 /src
parentBoilerplate city, for anyone who wants it. (diff)
downloadrust-d4f1a48111673c158d1c9493be4a87eaa24064b1.tar.xz
rust-d4f1a48111673c158d1c9493be4a87eaa24064b1.zip
Support 0 flag in #fmt
Diffstat (limited to 'src')
-rw-r--r--src/comp/front/extfmt.rs21
-rw-r--r--src/lib/ExtFmt.rs54
-rw-r--r--src/test/run-pass/syntax-extension-fmt.rs17
3 files changed, 80 insertions, 12 deletions
diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs
index 287c7e55..cfb27dcc 100644
--- a/src/comp/front/extfmt.rs
+++ b/src/comp/front/extfmt.rs
@@ -171,20 +171,25 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
fn make_flags(common.span sp, vec[flag] flags) -> @ast.expr {
let vec[@ast.expr] flagexprs = vec();
for (flag f in flags) {
+ auto fstr;
alt (f) {
case (flag_left_justify) {
- auto fstr = "flag_left_justify";
- flagexprs += vec(make_rt_path_expr(sp, fstr));
+ fstr = "flag_left_justify";
}
- case (flag_sign_always) {
- auto fstr = "flag_sign_always";
- flagexprs += vec(make_rt_path_expr(sp, fstr));
+ case (flag_left_zero_pad) {
+ fstr = "flag_left_zero_pad";
}
case (flag_space_for_sign) {
- auto fstr = "flag_space_for_sign";
- flagexprs += vec(make_rt_path_expr(sp, fstr));
+ fstr = "flag_space_for_sign";
+ }
+ case (flag_sign_always) {
+ fstr = "flag_sign_always";
+ }
+ case (flag_alternate) {
+ fstr = "flag_alternate";
}
}
+ flagexprs += vec(make_rt_path_expr(sp, fstr));
}
// FIXME: 0-length vectors can't have their type inferred
@@ -319,6 +324,8 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
fail;
}
}
+ case (flag_left_zero_pad) {
+ }
case (_) {
log unsupported;
fail;
diff --git a/src/lib/ExtFmt.rs b/src/lib/ExtFmt.rs
index c6ddad30..ec778f6d 100644
--- a/src/lib/ExtFmt.rs
+++ b/src/lib/ExtFmt.rs
@@ -306,8 +306,10 @@ mod RT {
tag flag {
flag_left_justify;
+ flag_left_zero_pad;
flag_space_for_sign;
flag_sign_always;
+ flag_alternate;
// FIXME: This is a hack to avoid creating 0-length vec exprs,
// which have some difficulty typechecking currently. See
// comments in front.extfmt.make_flags
@@ -344,7 +346,7 @@ mod RT {
s = " " + s;
}
}
- ret pad(cv, s);
+ ret pad(cv, s, pad_signed);
}
fn conv_uint(&conv cv, uint u) -> str {
@@ -364,7 +366,7 @@ mod RT {
res = uint_to_str_prec(u, 2u, prec);
}
}
- ret pad(cv, res);
+ ret pad(cv, res, pad_unsigned);
}
fn conv_bool(&conv cv, bool b) -> str {
@@ -396,7 +398,7 @@ mod RT {
}
}
}
- ret pad(cv, unpadded);
+ ret pad(cv, unpadded, pad_nozero);
}
// Convert an int to string with minimum number of digits. If precision is
@@ -449,7 +451,13 @@ mod RT {
ret _str.unsafe_from_bytes(svec);
}
- fn pad(&conv cv, str s) -> str {
+ tag pad_type {
+ pad_signed;
+ pad_unsigned;
+ pad_nozero;
+ }
+
+ fn pad(&conv cv, str s, pad_type pt) -> str {
alt (cv.width) {
case (count_implied) {
ret s;
@@ -459,11 +467,47 @@ mod RT {
auto uwidth = width as uint;
auto strlen = _str.char_len(s);
if (strlen < uwidth) {
+ auto zero_padding = false;
+ auto signed = false;
+ auto padchar = ' ';
+ alt (pt) {
+ case (pad_nozero) {
+ // fallthrough
+ }
+ case (pad_signed) {
+ signed = true;
+ if (have_flag(cv.flags, flag_left_zero_pad)) {
+ padchar = '0';
+ zero_padding = true;
+ }
+ }
+ case (pad_unsigned) {
+ if (have_flag(cv.flags, flag_left_zero_pad)) {
+ padchar = '0';
+ zero_padding = true;
+ }
+ }
+ }
+
auto diff = uwidth - strlen;
- auto padstr = str_init_elt(' ', diff);
+ auto padstr = str_init_elt(padchar, diff);
if (have_flag(cv.flags, flag_left_justify)) {
ret s + padstr;
} else {
+ // This is completely heinous. If we have a signed
+ // value then potentially rip apart the intermediate
+ // result and insert some zeros. It may make sense
+ // to convert zero padding to a precision instead.
+ if (signed
+ && zero_padding
+ && _str.byte_len(s) > 0u
+ && s.(0) == '-' as u8) {
+
+ auto bytelen = _str.byte_len(s);
+ auto numpart = _str.substr(s, 1u, bytelen - 1u);
+ ret "-" + padstr + numpart;
+ }
+
ret padstr + s;
}
} else {
diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs
index 61143e4a..46d5036a 100644
--- a/src/test/run-pass/syntax-extension-fmt.rs
+++ b/src/test/run-pass/syntax-extension-fmt.rs
@@ -126,4 +126,21 @@ fn main() {
// Plus overrides space
test(#fmt("% +d", 0), "+0");
test(#fmt("%+ d", 0), "+0");
+
+ // 0-padding
+ test(#fmt("%05d", 0), "00000");
+ test(#fmt("%05d", 1), "00001");
+ test(#fmt("%05d", -1), "-0001");
+ test(#fmt("%05u", 1u), "00001");
+ test(#fmt("%05x", 127u), "0007f");
+ test(#fmt("%05X", 127u), "0007F");
+ test(#fmt("%05t", 3u), "00011");
+ // 0-padding a string is undefined but glibc does this:
+ test(#fmt("%05s", "test"), " test");
+ test(#fmt("%05b", true), " true");
+
+ // TODO: Left-justify overrides 0-padding
+ // TODO: Precision overrides 0-padding
+ // TODO: Padding and +
+ // TODO: Padding and ' '
}