1
0
mirror of https://github.com/golang/go synced 2024-09-29 12:04:28 -06:00

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:
Joe Tsai 2022-06-15 17:29:25 -07:00 committed by Gopher Robot
parent d11c58eedb
commit 9c916c7901
3 changed files with 5 additions and 14 deletions

View File

@ -249,6 +249,7 @@ var fmtTests = []struct {
{"%.0c", '⌘', "⌘"}, // Specifying precision should have no effect.
{"%3c", '⌘', " ⌘"},
{"%-3c", '⌘', "⌘ "},
{"%c", uint64(0x100000000), "\ufffd"},
// Runes that are not printable.
{"%c", '\U00000e00', "\u0e00"},
{"%c", '\U0010ffff', "\U0010ffff"},

View File

@ -461,13 +461,14 @@ func (f *fmt) fmtQ(s string) {
// fmtC formats an integer as a Unicode character.
// If the character is not valid Unicode, it will print '\ufffd'.
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)
if c > utf8.MaxRune {
r = utf8.RuneError
}
buf := f.intbuf[:0]
w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
f.pad(buf[:w])
f.pad(utf8.AppendRune(buf, r))
}
// fmtQc formats an integer as a single-quoted, escaped Go character constant.

View File

@ -113,18 +113,7 @@ func (b *buffer) writeByte(c byte) {
}
func (bp *buffer) writeRune(r rune) {
if r < utf8.RuneSelf {
*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]
*bp = utf8.AppendRune(*bp, r)
}
// pp is used to store a printer's state and is reused with sync.Pool to avoid allocations.