Skip to content

Commit ac51237

Browse files
committed
fmt: format 0b, 0o prefixes in %#b and %O
This CL modifies fmt's printer to implement %#b and %O to emit leading 0b and 0o prefixes on binary and octal. (%#o is already taken and emits "0377"; %O emits "0o377".) See golang.org/design/19308-number-literals for background. For #19308. For #12711. Vet update is #29986. Change-Id: I7c38a4484c48a03abe9f6d45c7d981c7c314f583 Reviewed-on: https://go-review.googlesource.com/c/160246 Reviewed-by: Robert Griesemer <[email protected]> Reviewed-by: Rob Pike <[email protected]>
1 parent e1a6d1f commit ac51237

File tree

4 files changed

+31
-12
lines changed

4 files changed

+31
-12
lines changed

src/fmt/doc.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
%c the character represented by the corresponding Unicode code point
2727
%d base 10
2828
%o base 8
29+
%O base 8 with 0o prefix
2930
%q a single-quoted character literal safely escaped with Go syntax.
3031
%x base 16, with lower-case letters for a-f
3132
%X base 16, with upper-case letters for A-F
@@ -113,8 +114,8 @@
113114
+ always print a sign for numeric values;
114115
guarantee ASCII-only output for %q (%+q)
115116
- pad with spaces on the right rather than the left (left-justify the field)
116-
# alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
117-
0X for hex (%#X); suppress 0x for %p (%#p);
117+
# alternate format: add leading 0b for binary (%#b), 0 for octal (%#o),
118+
0x or 0X for hex (%#x or %#X); suppress 0x for %p (%#p);
118119
for %q, print a raw (backquoted) string if strconv.CanBackquote
119120
returns true;
120121
always print a decimal point for %e, %E, %f, %F, %g and %G;

src/fmt/fmt_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,17 @@ var fmtTests = []struct {
354354
{"%+d", -12345, "-12345"},
355355
{"%b", 7, "111"},
356356
{"%b", -6, "-110"},
357+
{"%#b", 7, "0b111"},
358+
{"%#b", -6, "-0b110"},
357359
{"%b", ^uint32(0), "11111111111111111111111111111111"},
358360
{"%b", ^uint64(0), "1111111111111111111111111111111111111111111111111111111111111111"},
359361
{"%b", int64(-1 << 63), zeroFill("-1", 63, "")},
360362
{"%o", 01234, "1234"},
363+
{"%o", -01234, "-1234"},
361364
{"%#o", 01234, "01234"},
365+
{"%#o", -01234, "-01234"},
366+
{"%O", 01234, "0o1234"},
367+
{"%O", -01234, "-0o1234"},
362368
{"%o", ^uint32(0), "37777777777"},
363369
{"%o", ^uint64(0), "1777777777777777777777"},
364370
{"%#X", 0, "0X0"},

src/fmt/format.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func (f *fmt) fmtUnicode(u uint64) {
191191
}
192192

193193
// fmtInteger formats signed and unsigned integers.
194-
func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) {
194+
func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits string) {
195195
negative := isSigned && int64(u) < 0
196196
if negative {
197197
u = -u
@@ -275,6 +275,12 @@ func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) {
275275
// Various prefixes: 0x, -, etc.
276276
if f.sharp {
277277
switch base {
278+
case 2:
279+
// Add a leading 0b.
280+
i--
281+
buf[i] = 'b'
282+
i--
283+
buf[i] = '0'
278284
case 8:
279285
if buf[i] != '0' {
280286
i--
@@ -288,6 +294,12 @@ func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) {
288294
buf[i] = '0'
289295
}
290296
}
297+
if verb == 'O' {
298+
i--
299+
buf[i] = 'o'
300+
i--
301+
buf[i] = '0'
302+
}
291303

292304
if negative {
293305
i--

src/fmt/print.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ func (p *pp) fmtBool(v bool, verb rune) {
363363
func (p *pp) fmt0x64(v uint64, leading0x bool) {
364364
sharp := p.fmt.sharp
365365
p.fmt.sharp = leading0x
366-
p.fmt.fmtInteger(v, 16, unsigned, ldigits)
366+
p.fmt.fmtInteger(v, 16, unsigned, 'v', ldigits)
367367
p.fmt.sharp = sharp
368368
}
369369

@@ -374,18 +374,18 @@ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) {
374374
if p.fmt.sharpV && !isSigned {
375375
p.fmt0x64(v, true)
376376
} else {
377-
p.fmt.fmtInteger(v, 10, isSigned, ldigits)
377+
p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
378378
}
379379
case 'd':
380-
p.fmt.fmtInteger(v, 10, isSigned, ldigits)
380+
p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
381381
case 'b':
382-
p.fmt.fmtInteger(v, 2, isSigned, ldigits)
383-
case 'o':
384-
p.fmt.fmtInteger(v, 8, isSigned, ldigits)
382+
p.fmt.fmtInteger(v, 2, isSigned, verb, ldigits)
383+
case 'o', 'O':
384+
p.fmt.fmtInteger(v, 8, isSigned, verb, ldigits)
385385
case 'x':
386-
p.fmt.fmtInteger(v, 16, isSigned, ldigits)
386+
p.fmt.fmtInteger(v, 16, isSigned, verb, ldigits)
387387
case 'X':
388-
p.fmt.fmtInteger(v, 16, isSigned, udigits)
388+
p.fmt.fmtInteger(v, 16, isSigned, verb, udigits)
389389
case 'c':
390390
p.fmt.fmtC(v)
391391
case 'q':
@@ -483,7 +483,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, typeString string) {
483483
if i > 0 {
484484
p.buf.WriteByte(' ')
485485
}
486-
p.fmt.fmtInteger(uint64(c), 10, unsigned, ldigits)
486+
p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits)
487487
}
488488
p.buf.WriteByte(']')
489489
}

0 commit comments

Comments
 (0)