Support 0 flag in #fmt
This commit is contained in:
parent
4763cd39ca
commit
d4f1a48111
3 changed files with 80 additions and 12 deletions
|
@ -171,21 +171,26 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
|
||||||
fn make_flags(common.span sp, vec[flag] flags) -> @ast.expr {
|
fn make_flags(common.span sp, vec[flag] flags) -> @ast.expr {
|
||||||
let vec[@ast.expr] flagexprs = vec();
|
let vec[@ast.expr] flagexprs = vec();
|
||||||
for (flag f in flags) {
|
for (flag f in flags) {
|
||||||
|
auto fstr;
|
||||||
alt (f) {
|
alt (f) {
|
||||||
case (flag_left_justify) {
|
case (flag_left_justify) {
|
||||||
auto fstr = "flag_left_justify";
|
fstr = "flag_left_justify";
|
||||||
flagexprs += vec(make_rt_path_expr(sp, fstr));
|
|
||||||
}
|
}
|
||||||
case (flag_sign_always) {
|
case (flag_left_zero_pad) {
|
||||||
auto fstr = "flag_sign_always";
|
fstr = "flag_left_zero_pad";
|
||||||
flagexprs += vec(make_rt_path_expr(sp, fstr));
|
|
||||||
}
|
}
|
||||||
case (flag_space_for_sign) {
|
case (flag_space_for_sign) {
|
||||||
auto fstr = "flag_space_for_sign";
|
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));
|
flagexprs += vec(make_rt_path_expr(sp, fstr));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: 0-length vectors can't have their type inferred
|
// FIXME: 0-length vectors can't have their type inferred
|
||||||
// through the rec that these flags are a member of, so
|
// through the rec that these flags are a member of, so
|
||||||
|
@ -319,6 +324,8 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr {
|
||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case (flag_left_zero_pad) {
|
||||||
|
}
|
||||||
case (_) {
|
case (_) {
|
||||||
log unsupported;
|
log unsupported;
|
||||||
fail;
|
fail;
|
||||||
|
|
|
@ -306,8 +306,10 @@ mod RT {
|
||||||
|
|
||||||
tag flag {
|
tag flag {
|
||||||
flag_left_justify;
|
flag_left_justify;
|
||||||
|
flag_left_zero_pad;
|
||||||
flag_space_for_sign;
|
flag_space_for_sign;
|
||||||
flag_sign_always;
|
flag_sign_always;
|
||||||
|
flag_alternate;
|
||||||
// FIXME: This is a hack to avoid creating 0-length vec exprs,
|
// FIXME: This is a hack to avoid creating 0-length vec exprs,
|
||||||
// which have some difficulty typechecking currently. See
|
// which have some difficulty typechecking currently. See
|
||||||
// comments in front.extfmt.make_flags
|
// comments in front.extfmt.make_flags
|
||||||
|
@ -344,7 +346,7 @@ mod RT {
|
||||||
s = " " + s;
|
s = " " + s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret pad(cv, s);
|
ret pad(cv, s, pad_signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn conv_uint(&conv cv, uint u) -> str {
|
fn conv_uint(&conv cv, uint u) -> str {
|
||||||
|
@ -364,7 +366,7 @@ mod RT {
|
||||||
res = uint_to_str_prec(u, 2u, prec);
|
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 {
|
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
|
// 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);
|
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) {
|
alt (cv.width) {
|
||||||
case (count_implied) {
|
case (count_implied) {
|
||||||
ret s;
|
ret s;
|
||||||
|
@ -459,11 +467,47 @@ mod RT {
|
||||||
auto uwidth = width as uint;
|
auto uwidth = width as uint;
|
||||||
auto strlen = _str.char_len(s);
|
auto strlen = _str.char_len(s);
|
||||||
if (strlen < uwidth) {
|
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 diff = uwidth - strlen;
|
||||||
auto padstr = str_init_elt(' ', diff);
|
auto padstr = str_init_elt(padchar, diff);
|
||||||
if (have_flag(cv.flags, flag_left_justify)) {
|
if (have_flag(cv.flags, flag_left_justify)) {
|
||||||
ret s + padstr;
|
ret s + padstr;
|
||||||
} else {
|
} 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;
|
ret padstr + s;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -126,4 +126,21 @@ fn main() {
|
||||||
// Plus overrides space
|
// Plus overrides space
|
||||||
test(#fmt("% +d", 0), "+0");
|
test(#fmt("% +d", 0), "+0");
|
||||||
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 ' '
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue