]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: format 0b, 0o prefixes in %#b and %O
authorRuss Cox <rsc@golang.org>
Wed, 30 Jan 2019 03:24:36 +0000 (22:24 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 26 Feb 2019 05:16:56 +0000 (05:16 +0000)
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 <gri@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
src/fmt/doc.go
src/fmt/fmt_test.go
src/fmt/format.go
src/fmt/print.go

index c349f8e321ffee94858839b7b8235d03e4e4b4e0..e0edff456c6c152529b85e6811f50153f6436678 100644 (file)
@@ -26,6 +26,7 @@
                %c      the character represented by the corresponding Unicode code point
                %d      base 10
                %o      base 8
+               %O      base 8 with 0o prefix
                %q      a single-quoted character literal safely escaped with Go syntax.
                %x      base 16, with lower-case letters for a-f
                %X      base 16, with upper-case letters for A-F
                +       always print a sign for numeric values;
                        guarantee ASCII-only output for %q (%+q)
                -       pad with spaces on the right rather than the left (left-justify the field)
-               #       alternate format: add leading 0 for octal (%#o), 0x for hex (%#x);
-                       0X for hex (%#X); suppress 0x for %p (%#p);
+               #       alternate format: add leading 0b for binary (%#b), 0 for octal (%#o),
+                       0x or 0X for hex (%#x or %#X); suppress 0x for %p (%#p);
                        for %q, print a raw (backquoted) string if strconv.CanBackquote
                        returns true;
                        always print a decimal point for %e, %E, %f, %F, %g and %G;
index 2d10c7a8418923e9b7c9edb048745a8d591637d5..bbaf40a6199cb7c97604618a3966b2d3ebbaae79 100644 (file)
@@ -354,11 +354,17 @@ var fmtTests = []struct {
        {"%+d", -12345, "-12345"},
        {"%b", 7, "111"},
        {"%b", -6, "-110"},
+       {"%#b", 7, "0b111"},
+       {"%#b", -6, "-0b110"},
        {"%b", ^uint32(0), "11111111111111111111111111111111"},
        {"%b", ^uint64(0), "1111111111111111111111111111111111111111111111111111111111111111"},
        {"%b", int64(-1 << 63), zeroFill("-1", 63, "")},
        {"%o", 01234, "1234"},
+       {"%o", -01234, "-1234"},
        {"%#o", 01234, "01234"},
+       {"%#o", -01234, "-01234"},
+       {"%O", 01234, "0o1234"},
+       {"%O", -01234, "-0o1234"},
        {"%o", ^uint32(0), "37777777777"},
        {"%o", ^uint64(0), "1777777777777777777777"},
        {"%#X", 0, "0X0"},
index 6d939080957c92e87a484bfb8539b3cc94b3e5ce..24e7e9551a151f49f9a2b0a759c19e09c041533d 100644 (file)
@@ -191,7 +191,7 @@ func (f *fmt) fmtUnicode(u uint64) {
 }
 
 // fmtInteger formats signed and unsigned integers.
-func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) {
+func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits string) {
        negative := isSigned && int64(u) < 0
        if negative {
                u = -u
@@ -275,6 +275,12 @@ func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) {
        // Various prefixes: 0x, -, etc.
        if f.sharp {
                switch base {
+               case 2:
+                       // Add a leading 0b.
+                       i--
+                       buf[i] = 'b'
+                       i--
+                       buf[i] = '0'
                case 8:
                        if buf[i] != '0' {
                                i--
@@ -288,6 +294,12 @@ func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) {
                        buf[i] = '0'
                }
        }
+       if verb == 'O' {
+               i--
+               buf[i] = 'o'
+               i--
+               buf[i] = '0'
+       }
 
        if negative {
                i--
index 9976b8d2636fc05093d36001246cf267eb457ecb..121c7c59e42441caddcba8cbba81bf4da0adc928 100644 (file)
@@ -363,7 +363,7 @@ func (p *pp) fmtBool(v bool, verb rune) {
 func (p *pp) fmt0x64(v uint64, leading0x bool) {
        sharp := p.fmt.sharp
        p.fmt.sharp = leading0x
-       p.fmt.fmtInteger(v, 16, unsigned, ldigits)
+       p.fmt.fmtInteger(v, 16, unsigned, 'v', ldigits)
        p.fmt.sharp = sharp
 }
 
@@ -374,18 +374,18 @@ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) {
                if p.fmt.sharpV && !isSigned {
                        p.fmt0x64(v, true)
                } else {
-                       p.fmt.fmtInteger(v, 10, isSigned, ldigits)
+                       p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
                }
        case 'd':
-               p.fmt.fmtInteger(v, 10, isSigned, ldigits)
+               p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
        case 'b':
-               p.fmt.fmtInteger(v, 2, isSigned, ldigits)
-       case 'o':
-               p.fmt.fmtInteger(v, 8, isSigned, ldigits)
+               p.fmt.fmtInteger(v, 2, isSigned, verb, ldigits)
+       case 'o', 'O':
+               p.fmt.fmtInteger(v, 8, isSigned, verb, ldigits)
        case 'x':
-               p.fmt.fmtInteger(v, 16, isSigned, ldigits)
+               p.fmt.fmtInteger(v, 16, isSigned, verb, ldigits)
        case 'X':
-               p.fmt.fmtInteger(v, 16, isSigned, udigits)
+               p.fmt.fmtInteger(v, 16, isSigned, verb, udigits)
        case 'c':
                p.fmt.fmtC(v)
        case 'q':
@@ -483,7 +483,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, typeString string) {
                                if i > 0 {
                                        p.buf.WriteByte(' ')
                                }
-                               p.fmt.fmtInteger(uint64(c), 10, unsigned, ldigits)
+                               p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits)
                        }
                        p.buf.WriteByte(']')
                }