mirror of https://github.com/golang/go.git
fmt: rely on utf8.AppendRune
This is both simpler and more performant. The need for fmt.fmtC to manually check for utf8.MaxRune is subtle to avoid overflow when converting uint64 to rune, so a test case was added to exercise this edge case. Change-Id: I0f2e6cce91dcd4cc6b88190c29807ca1c58e999d Reviewed-on: https://go-review.googlesource.com/c/go/+/412335 Auto-Submit: Joseph Tsai <joetsai@digital-static.net> Auto-Submit: Robert Griesemer <gri@google.com> Run-TryBot: Joseph Tsai <joetsai@digital-static.net> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com> Run-TryBot: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
d11c58eedb
commit
9c916c7901
|
|
@ -249,6 +249,7 @@ var fmtTests = []struct {
|
||||||
{"%.0c", '⌘', "⌘"}, // Specifying precision should have no effect.
|
{"%.0c", '⌘', "⌘"}, // Specifying precision should have no effect.
|
||||||
{"%3c", '⌘', " ⌘"},
|
{"%3c", '⌘', " ⌘"},
|
||||||
{"%-3c", '⌘', "⌘ "},
|
{"%-3c", '⌘', "⌘ "},
|
||||||
|
{"%c", uint64(0x100000000), "\ufffd"},
|
||||||
// Runes that are not printable.
|
// Runes that are not printable.
|
||||||
{"%c", '\U00000e00', "\u0e00"},
|
{"%c", '\U00000e00', "\u0e00"},
|
||||||
{"%c", '\U0010ffff', "\U0010ffff"},
|
{"%c", '\U0010ffff', "\U0010ffff"},
|
||||||
|
|
|
||||||
|
|
@ -461,13 +461,14 @@ func (f *fmt) fmtQ(s string) {
|
||||||
// fmtC formats an integer as a Unicode character.
|
// fmtC formats an integer as a Unicode character.
|
||||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
// If the character is not valid Unicode, it will print '\ufffd'.
|
||||||
func (f *fmt) fmtC(c uint64) {
|
func (f *fmt) fmtC(c uint64) {
|
||||||
|
// Explicitly check whether c exceeds utf8.MaxRune since the conversion
|
||||||
|
// of a uint64 to a rune may lose precision that indicates an overflow.
|
||||||
r := rune(c)
|
r := rune(c)
|
||||||
if c > utf8.MaxRune {
|
if c > utf8.MaxRune {
|
||||||
r = utf8.RuneError
|
r = utf8.RuneError
|
||||||
}
|
}
|
||||||
buf := f.intbuf[:0]
|
buf := f.intbuf[:0]
|
||||||
w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
|
f.pad(utf8.AppendRune(buf, r))
|
||||||
f.pad(buf[:w])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmtQc formats an integer as a single-quoted, escaped Go character constant.
|
// fmtQc formats an integer as a single-quoted, escaped Go character constant.
|
||||||
|
|
|
||||||
|
|
@ -113,18 +113,7 @@ func (b *buffer) writeByte(c byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bp *buffer) writeRune(r rune) {
|
func (bp *buffer) writeRune(r rune) {
|
||||||
if r < utf8.RuneSelf {
|
*bp = utf8.AppendRune(*bp, r)
|
||||||
*bp = append(*bp, byte(r))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
b := *bp
|
|
||||||
n := len(b)
|
|
||||||
for n+utf8.UTFMax > cap(b) {
|
|
||||||
b = append(b, 0)
|
|
||||||
}
|
|
||||||
w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r)
|
|
||||||
*bp = b[:n+w]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pp is used to store a printer's state and is reused with sync.Pool to avoid allocations.
|
// pp is used to store a printer's state and is reused with sync.Pool to avoid allocations.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue