mirror of
https://github.com/golang/go
synced 2024-11-19 06:54:39 -07:00
fmt: unify integer formatting
Deduplicate the verb switch for signed and unsigned integer formatting. Make names of integer related functions consistent with names of other fmt functions. Consolidate basic integer tests. Change-Id: I0c19c24f1c2c06a3b1a4d7d377dcdac3b36bb0f5 Reviewed-on: https://go-review.googlesource.com/20831 Run-TryBot: Rob Pike <r@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
3eaa304629
commit
8d9ece9dde
@ -48,11 +48,6 @@ func TestFmtInterface(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
b32 uint32 = 1<<32 - 1
|
||||
b64 uint64 = 1<<64 - 1
|
||||
)
|
||||
|
||||
var (
|
||||
NaN = math.NaN()
|
||||
posInf = math.Inf(1)
|
||||
@ -319,23 +314,47 @@ var fmtTests = []struct {
|
||||
{"%-10v", nil, "<nil> "},
|
||||
|
||||
// integers
|
||||
{"%d", 12345, "12345"},
|
||||
{"%d", -12345, "-12345"},
|
||||
{"%d", uint(12345), "12345"},
|
||||
{"%d", int(-12345), "-12345"},
|
||||
{"%d", ^uint8(0), "255"},
|
||||
{"%d", ^uint16(0), "65535"},
|
||||
{"%d", ^uint32(0), "4294967295"},
|
||||
{"%d", ^uint64(0), "18446744073709551615"},
|
||||
{"%d", int8(-1 << 7), "-128"},
|
||||
{"%d", int16(-1 << 15), "-32768"},
|
||||
{"%d", int32(-1 << 31), "-2147483648"},
|
||||
{"%d", int64(-1 << 63), "-9223372036854775808"},
|
||||
{"%.d", 0, ""},
|
||||
{"%.0d", 0, ""},
|
||||
{"% d", 12345, " 12345"},
|
||||
{"%+d", 12345, "+12345"},
|
||||
{"%+d", -12345, "-12345"},
|
||||
{"%b", 7, "111"},
|
||||
{"%b", -6, "-110"},
|
||||
{"%b", ^uint32(0), "11111111111111111111111111111111"},
|
||||
{"%b", ^uint64(0), "1111111111111111111111111111111111111111111111111111111111111111"},
|
||||
{"%o", 01234, "1234"},
|
||||
{"%#o", 01234, "01234"},
|
||||
{"%o", ^uint32(0), "37777777777"},
|
||||
{"%o", ^uint64(0), "1777777777777777777777"},
|
||||
{"%#X", 0, "0X0"},
|
||||
{"%x", 0x12abcdef, "12abcdef"},
|
||||
{"%X", 0x12abcdef, "12ABCDEF"},
|
||||
{"%x", ^uint32(0), "ffffffff"},
|
||||
{"%X", ^uint64(0), "FFFFFFFFFFFFFFFF"},
|
||||
{"%.20b", 7, "00000000000000000111"},
|
||||
{"%10d", 12345, " 12345"},
|
||||
{"%10d", -12345, " -12345"},
|
||||
{"%+10d", 12345, " +12345"},
|
||||
{"%010d", 12345, "0000012345"},
|
||||
{"%010d", -12345, "-000012345"},
|
||||
{"%-10d", 12345, "12345 "},
|
||||
{"%010.3d", 1, " 001"},
|
||||
{"%010.3d", -1, " -001"},
|
||||
{"%+d", 12345, "+12345"},
|
||||
{"%+d", -12345, "-12345"},
|
||||
{"%+d", 0, "+0"},
|
||||
{"% d", 0, " 0"},
|
||||
{"% d", 12345, " 12345"},
|
||||
{"%.0d", 0, ""},
|
||||
{"%.d", 0, ""},
|
||||
{"%20.8d", 1234, " 00001234"},
|
||||
{"%20.8d", -1234, " -00001234"},
|
||||
{"%-20.8d", 1234, "00001234 "},
|
||||
{"%-20.8d", -1234, "-00001234 "},
|
||||
{"%-#20.8x", 0x1234abc, "0x01234abc "},
|
||||
{"%-#20.8X", 0x1234abc, "0X01234ABC "},
|
||||
{"%-#20.8o", 01234, "00001234 "},
|
||||
|
||||
// unicode format
|
||||
{"%U", 0, "U+0000"},
|
||||
@ -453,25 +472,6 @@ var fmtTests = []struct {
|
||||
{"%-08G", complex(NaN, NaN), "(NaN +NaN i)"},
|
||||
|
||||
// old test/fmt_test.go
|
||||
{"%d", 1234, "1234"},
|
||||
{"%d", -1234, "-1234"},
|
||||
{"%d", uint(1234), "1234"},
|
||||
{"%d", uint32(b32), "4294967295"},
|
||||
{"%d", uint64(b64), "18446744073709551615"},
|
||||
{"%o", 01234, "1234"},
|
||||
{"%#o", 01234, "01234"},
|
||||
{"%o", uint32(b32), "37777777777"},
|
||||
{"%o", uint64(b64), "1777777777777777777777"},
|
||||
{"%x", 0x1234abcd, "1234abcd"},
|
||||
{"%#x", 0x1234abcd, "0x1234abcd"},
|
||||
{"%x", b32 - 0x1234567, "fedcba98"},
|
||||
{"%X", 0x1234abcd, "1234ABCD"},
|
||||
{"%X", b32 - 0x1234567, "FEDCBA98"},
|
||||
{"%#X", 0, "0X0"},
|
||||
{"%x", b64, "ffffffffffffffff"},
|
||||
{"%b", 7, "111"},
|
||||
{"%b", b64, "1111111111111111111111111111111111111111111111111111111111111111"},
|
||||
{"%b", -6, "-110"},
|
||||
{"%e", 1.0, "1.000000e+00"},
|
||||
{"%e", 1234.5678e3, "1.234568e+06"},
|
||||
{"%e", 1234.5678e-8, "1.234568e-05"},
|
||||
@ -498,15 +498,6 @@ var fmtTests = []struct {
|
||||
{"%G", -7.0, "-7"},
|
||||
{"%G", -1e-9, "-1E-09"},
|
||||
{"%G", float32(-1e-9), "-1E-09"},
|
||||
{"%20.8d", 1234, " 00001234"},
|
||||
{"%20.8d", -1234, " -00001234"},
|
||||
{"%20d", 1234, " 1234"},
|
||||
{"%-20.8d", 1234, "00001234 "},
|
||||
{"%-20.8d", -1234, "-00001234 "},
|
||||
{"%-#20.8x", 0x1234abc, "0x01234abc "},
|
||||
{"%-#20.8X", 0x1234abc, "0X01234ABC "},
|
||||
{"%-#20.8o", 01234, "00001234 "},
|
||||
{"%.20b", 7, "00000000000000000111"},
|
||||
{"%20.5s", "qwertyuiop", " qwert"},
|
||||
{"%.5s", "qwertyuiop", "qwert"},
|
||||
{"%-20.5s", "qwertyuiop", "qwert "},
|
||||
@ -822,11 +813,11 @@ var fmtTests = []struct {
|
||||
{"%0.100f", -1.0, zeroFill("-1.", 100, "")},
|
||||
|
||||
// Used to panic: integer function didn't look at f.prec, f.unicode, f.width or sign.
|
||||
{"%#.80x", 42, "0x0000000000000000000000000000000000000000000000000000000000000000000000000000002a"},
|
||||
{"%.65d", -44, "-00000000000000000000000000000000000000000000000000000000000000044"},
|
||||
{"%+.65d", 44, "+00000000000000000000000000000000000000000000000000000000000000044"},
|
||||
{"% .65d", 44, " 00000000000000000000000000000000000000000000000000000000000000044"},
|
||||
{"% +.65d", 44, "+00000000000000000000000000000000000000000000000000000000000000044"},
|
||||
{"%#.65x", 42, zeroFill("0x", 65, "2a")},
|
||||
{"%.65d", -42, zeroFill("-", 65, "42")},
|
||||
{"%+.65d", 42, zeroFill("+", 65, "42")},
|
||||
{"% .65d", 42, zeroFill(" ", 65, "42")},
|
||||
{"% +.65d", 42, zeroFill("+", 65, "42")},
|
||||
|
||||
// Comparison of padding rules with C printf.
|
||||
/*
|
||||
|
@ -190,17 +190,16 @@ func (f *fmt) fmt_unicode(u uint64) {
|
||||
f.zero = oldZero
|
||||
}
|
||||
|
||||
// integer; interprets prec but not wid. Once formatted, result is sent to pad()
|
||||
// and then flags are cleared.
|
||||
func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
|
||||
// fmt_integer formats signed and unsigned integers.
|
||||
func (f *fmt) fmt_integer(u uint64, base int, isSigned bool, digits string) {
|
||||
// precision of 0 and value of 0 means "print nothing"
|
||||
if f.precPresent && f.prec == 0 && a == 0 {
|
||||
if f.precPresent && f.prec == 0 && u == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
negative := signedness == signed && a < 0
|
||||
negative := isSigned && int64(u) < 0
|
||||
if negative {
|
||||
a = -a
|
||||
u = -u
|
||||
}
|
||||
|
||||
var buf []byte = f.intbuf[0:]
|
||||
@ -233,45 +232,43 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
|
||||
}
|
||||
}
|
||||
|
||||
// format a into buf, ending at buf[i]. (printing is easier right-to-left.)
|
||||
// a is made into unsigned ua. we could make things
|
||||
// marginally faster by splitting the 32-bit case out into a separate
|
||||
// block but it's not worth the duplication, so ua has 64 bits.
|
||||
// Because printing is easier right-to-left: format u into buf, ending at buf[i].
|
||||
// We could make things marginally faster by splitting the 32-bit case out
|
||||
// into a separate block but it's not worth the duplication, so u has 64 bits.
|
||||
i := len(buf)
|
||||
ua := uint64(a)
|
||||
// use constants for the division and modulo for more efficient code.
|
||||
// switch cases ordered by popularity.
|
||||
// Use constants for the division and modulo for more efficient code.
|
||||
// Switch cases ordered by popularity.
|
||||
switch base {
|
||||
case 10:
|
||||
for ua >= 10 {
|
||||
for u >= 10 {
|
||||
i--
|
||||
next := ua / 10
|
||||
buf[i] = byte('0' + ua - next*10)
|
||||
ua = next
|
||||
next := u / 10
|
||||
buf[i] = byte('0' + u - next*10)
|
||||
u = next
|
||||
}
|
||||
case 16:
|
||||
for ua >= 16 {
|
||||
for u >= 16 {
|
||||
i--
|
||||
buf[i] = digits[ua&0xF]
|
||||
ua >>= 4
|
||||
buf[i] = digits[u&0xF]
|
||||
u >>= 4
|
||||
}
|
||||
case 8:
|
||||
for ua >= 8 {
|
||||
for u >= 8 {
|
||||
i--
|
||||
buf[i] = byte('0' + ua&7)
|
||||
ua >>= 3
|
||||
buf[i] = byte('0' + u&7)
|
||||
u >>= 3
|
||||
}
|
||||
case 2:
|
||||
for ua >= 2 {
|
||||
for u >= 2 {
|
||||
i--
|
||||
buf[i] = byte('0' + ua&1)
|
||||
ua >>= 1
|
||||
buf[i] = byte('0' + u&1)
|
||||
u >>= 1
|
||||
}
|
||||
default:
|
||||
panic("fmt: unknown base; can't happen")
|
||||
}
|
||||
i--
|
||||
buf[i] = digits[ua]
|
||||
buf[i] = digits[u]
|
||||
for i > 0 && prec > len(buf)-i {
|
||||
i--
|
||||
buf[i] = '0'
|
||||
|
@ -338,68 +338,42 @@ func (p *pp) fmtBool(v bool, verb rune) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pp) fmtInt64(v int64, verb rune) {
|
||||
switch verb {
|
||||
case 'b':
|
||||
p.fmt.integer(v, 2, signed, ldigits)
|
||||
case 'c':
|
||||
p.fmt.fmt_c(uint64(v))
|
||||
case 'd', 'v':
|
||||
p.fmt.integer(v, 10, signed, ldigits)
|
||||
case 'o':
|
||||
p.fmt.integer(v, 8, signed, ldigits)
|
||||
case 'q':
|
||||
if 0 <= v && v <= utf8.MaxRune {
|
||||
p.fmt.fmt_qc(uint64(v))
|
||||
} else {
|
||||
p.badVerb(verb)
|
||||
}
|
||||
case 'x':
|
||||
p.fmt.integer(v, 16, signed, ldigits)
|
||||
case 'U':
|
||||
p.fmt.fmt_unicode(uint64(v))
|
||||
case 'X':
|
||||
p.fmt.integer(v, 16, signed, udigits)
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
}
|
||||
|
||||
// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or
|
||||
// not, as requested, by temporarily setting the sharp flag.
|
||||
func (p *pp) fmt0x64(v uint64, leading0x bool) {
|
||||
sharp := p.fmt.sharp
|
||||
p.fmt.sharp = leading0x
|
||||
p.fmt.integer(int64(v), 16, unsigned, ldigits)
|
||||
p.fmt.fmt_integer(v, 16, unsigned, ldigits)
|
||||
p.fmt.sharp = sharp
|
||||
}
|
||||
|
||||
func (p *pp) fmtUint64(v uint64, verb rune) {
|
||||
// fmtInteger formats a signed or unsigned integer.
|
||||
func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) {
|
||||
switch verb {
|
||||
case 'b':
|
||||
p.fmt.integer(int64(v), 2, unsigned, ldigits)
|
||||
case 'c':
|
||||
p.fmt.fmt_c(v)
|
||||
case 'd':
|
||||
p.fmt.integer(int64(v), 10, unsigned, ldigits)
|
||||
case 'v':
|
||||
if p.fmt.sharpV {
|
||||
if p.fmt.sharpV && !isSigned {
|
||||
p.fmt0x64(v, true)
|
||||
} else {
|
||||
p.fmt.integer(int64(v), 10, unsigned, ldigits)
|
||||
p.fmt.fmt_integer(v, 10, isSigned, ldigits)
|
||||
}
|
||||
case 'd':
|
||||
p.fmt.fmt_integer(v, 10, isSigned, ldigits)
|
||||
case 'b':
|
||||
p.fmt.fmt_integer(v, 2, isSigned, ldigits)
|
||||
case 'o':
|
||||
p.fmt.integer(int64(v), 8, unsigned, ldigits)
|
||||
p.fmt.fmt_integer(v, 8, isSigned, ldigits)
|
||||
case 'x':
|
||||
p.fmt.fmt_integer(v, 16, isSigned, ldigits)
|
||||
case 'X':
|
||||
p.fmt.fmt_integer(v, 16, isSigned, udigits)
|
||||
case 'c':
|
||||
p.fmt.fmt_c(v)
|
||||
case 'q':
|
||||
if 0 <= v && v <= utf8.MaxRune {
|
||||
if v <= utf8.MaxRune {
|
||||
p.fmt.fmt_qc(v)
|
||||
} else {
|
||||
p.badVerb(verb)
|
||||
}
|
||||
case 'x':
|
||||
p.fmt.integer(int64(v), 16, unsigned, ldigits)
|
||||
case 'X':
|
||||
p.fmt.integer(int64(v), 16, unsigned, udigits)
|
||||
case 'U':
|
||||
p.fmt.fmt_unicode(v)
|
||||
default:
|
||||
@ -489,7 +463,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, typeString string) {
|
||||
if i > 0 {
|
||||
p.buf.WriteByte(' ')
|
||||
}
|
||||
p.fmt.integer(int64(c), 10, unsigned, ldigits)
|
||||
p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits)
|
||||
}
|
||||
p.buf.WriteByte(']')
|
||||
}
|
||||
@ -538,7 +512,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune) {
|
||||
case 'p':
|
||||
p.fmt0x64(uint64(u), !p.fmt.sharp)
|
||||
case 'b', 'o', 'd', 'x', 'X':
|
||||
p.fmtUint64(uint64(u), verb)
|
||||
p.fmtInteger(uint64(u), unsigned, verb)
|
||||
default:
|
||||
p.badVerb(verb)
|
||||
}
|
||||
@ -657,27 +631,27 @@ func (p *pp) printArg(arg interface{}, verb rune) {
|
||||
case complex128:
|
||||
p.fmtComplex(f, 128, verb)
|
||||
case int:
|
||||
p.fmtInt64(int64(f), verb)
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int8:
|
||||
p.fmtInt64(int64(f), verb)
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int16:
|
||||
p.fmtInt64(int64(f), verb)
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int32:
|
||||
p.fmtInt64(int64(f), verb)
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case int64:
|
||||
p.fmtInt64(f, verb)
|
||||
p.fmtInteger(uint64(f), signed, verb)
|
||||
case uint:
|
||||
p.fmtUint64(uint64(f), verb)
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint8:
|
||||
p.fmtUint64(uint64(f), verb)
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint16:
|
||||
p.fmtUint64(uint64(f), verb)
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint32:
|
||||
p.fmtUint64(uint64(f), verb)
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case uint64:
|
||||
p.fmtUint64(f, verb)
|
||||
p.fmtInteger(f, unsigned, verb)
|
||||
case uintptr:
|
||||
p.fmtUint64(uint64(f), verb)
|
||||
p.fmtInteger(uint64(f), unsigned, verb)
|
||||
case string:
|
||||
p.fmtString(f, verb)
|
||||
case []byte:
|
||||
@ -737,9 +711,9 @@ BigSwitch:
|
||||
case reflect.Bool:
|
||||
p.fmtBool(f.Bool(), verb)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
p.fmtInt64(f.Int(), verb)
|
||||
p.fmtInteger(uint64(f.Int()), signed, verb)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
p.fmtUint64(f.Uint(), verb)
|
||||
p.fmtInteger(f.Uint(), unsigned, verb)
|
||||
case reflect.Float32:
|
||||
p.fmtFloat(f.Float(), 32, verb)
|
||||
case reflect.Float64:
|
||||
|
Loading…
Reference in New Issue
Block a user