diff options
Diffstat (limited to 'libgo/go/fmt/format.go')
-rw-r--r-- | libgo/go/fmt/format.go | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index a89c542cfb5..4d97d1443ed 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -34,15 +34,8 @@ func init() { } } -// A fmt is the raw formatter used by Printf etc. -// It prints into a buffer that must be set up separately. -type fmt struct { - intbuf [nByte]byte - buf *buffer - // width, precision - wid int - prec int - // flags +// flags placed in a separate struct for easy clearing. +type fmtFlags struct { widPresent bool precPresent bool minus bool @@ -52,20 +45,27 @@ type fmt struct { unicode bool uniQuote bool // Use 'x'= prefix for %U if printable. zero bool + + // For the formats %+v %#v, we set the plusV/sharpV flags + // and clear the plus/sharp flags since %+v and %#v are in effect + // different, flagless formats set at the top level. + plusV bool + sharpV bool +} + +// A fmt is the raw formatter used by Printf etc. +// It prints into a buffer that must be set up separately. +type fmt struct { + intbuf [nByte]byte + buf *buffer + // width, precision + wid int + prec int + fmtFlags } func (f *fmt) clearflags() { - f.wid = 0 - f.widPresent = false - f.prec = 0 - f.precPresent = false - f.minus = false - f.plus = false - f.sharp = false - f.space = false - f.unicode = false - f.uniQuote = false - f.zero = false + f.fmtFlags = fmtFlags{} } func (f *fmt) init(buf *buffer) { @@ -114,7 +114,7 @@ func (f *fmt) pad(b []byte) { f.buf.Write(b) return } - padding, left, right := f.computePadding(len(b)) + padding, left, right := f.computePadding(utf8.RuneCount(b)) if left > 0 { f.writePadding(left, padding) } @@ -199,10 +199,36 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { // block but it's not worth the duplication, so ua has 64 bits. i := len(buf) ua := uint64(a) - for ua >= base { - i-- - buf[i] = digits[ua%base] - ua /= base + // use constants for the division and modulo for more efficient code. + // switch cases ordered by popularity. + switch base { + case 10: + for ua >= 10 { + i-- + next := ua / 10 + buf[i] = byte('0' + ua - next*10) + ua = next + } + case 16: + for ua >= 16 { + i-- + buf[i] = digits[ua&0xF] + ua >>= 4 + } + case 8: + for ua >= 8 { + i-- + buf[i] = byte('0' + ua&7) + ua >>= 3 + } + case 2: + for ua >= 2 { + i-- + buf[i] = byte('0' + ua&1) + ua >>= 1 + } + default: + panic("fmt: unknown base; can't happen") } i-- buf[i] = digits[ua] @@ -298,7 +324,7 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) { if i > 0 && f.space { buf = append(buf, ' ') } - if f.sharp { + if f.sharp && (f.space || i == 0) { buf = append(buf, '0', x) } var c byte @@ -314,11 +340,17 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) { // fmt_sx formats a string as a hexadecimal encoding of its bytes. func (f *fmt) fmt_sx(s, digits string) { + if f.precPresent && f.prec < len(s) { + s = s[:f.prec] + } f.fmt_sbx(s, nil, digits) } // fmt_bx formats a byte slice as a hexadecimal encoding of its bytes. func (f *fmt) fmt_bx(b []byte, digits string) { + if f.precPresent && f.prec < len(b) { + b = b[:f.prec] + } f.fmt_sbx("", b, digits) } |