1
0
mirror of https://github.com/golang/go synced 2024-10-01 16:18:32 -06: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:
Martin Möhrmann 2016-03-18 08:24:40 +01:00 committed by Rob Pike
parent 3eaa304629
commit 8d9ece9dde
3 changed files with 97 additions and 135 deletions

View File

@ -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.
/*

View File

@ -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'

View File

@ -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: