diff options
| author | Brian Anderson <[email protected]> | 2011-04-18 20:58:45 -0400 |
|---|---|---|
| committer | Brian Anderson <[email protected]> | 2011-04-18 21:36:04 -0400 |
| commit | d4f1a48111673c158d1c9493be4a87eaa24064b1 (patch) | |
| tree | 08dddcf2a24b2b1a9b2dd4d4d61eccc33b4b0df3 /src | |
| parent | Boilerplate city, for anyone who wants it. (diff) | |
| download | rust-d4f1a48111673c158d1c9493be4a87eaa24064b1.tar.xz rust-d4f1a48111673c158d1c9493be4a87eaa24064b1.zip | |
Support 0 flag in #fmt
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/front/extfmt.rs | 21 | ||||
| -rw-r--r-- | src/lib/ExtFmt.rs | 54 | ||||
| -rw-r--r-- | src/test/run-pass/syntax-extension-fmt.rs | 17 |
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 ' ' } |