mirror of
https://github.com/golang/go
synced 2024-11-12 09:50:21 -07:00
fmt: debugging formats for characters: %+q %#U
%+q uses strconv.Quote[Rune]ToASCII, guaranteeing ASCII-only output. %#U a quoted character if the rune is printable: 'x'=U+0078; otherwise it's as before: U+000A. R=golang-dev, gri, rsc CC=golang-dev https://golang.org/cl/4589047
This commit is contained in:
parent
4b1170d2b1
commit
d152fe74e1
@ -63,11 +63,13 @@
|
||||
number of characters to output, truncating if necessary.
|
||||
|
||||
Other flags:
|
||||
+ always print a sign for numeric values
|
||||
+ 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);
|
||||
print a raw (backquoted) string if possible for %q (%#q)
|
||||
print a raw (backquoted) string if possible for %q (%#q);
|
||||
write e.g. U+0078 'x' if the character is printable for %U (%#U).
|
||||
' ' (space) leave a space for elided sign in numbers (% d);
|
||||
put spaces between bytes printing strings or slices in hex (% x, % X)
|
||||
0 pad with leading zeros rather than spaces
|
||||
|
@ -133,6 +133,7 @@ var fmttests = []struct {
|
||||
{"%q", "\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`},
|
||||
{"%q", "abc\xffdef", `"abc\xffdef"`},
|
||||
{"%q", "\u263a", `"☺"`},
|
||||
{"%+q", "\u263a", `"\u263a"`},
|
||||
{"%q", "\U0010ffff", `"\U0010ffff"`},
|
||||
|
||||
// escaped characters
|
||||
@ -145,6 +146,8 @@ var fmttests = []struct {
|
||||
{"%q", uint64(0xFFFFFFFF), `%!q(uint64=4294967295)`},
|
||||
{"%q", '"', `'"'`},
|
||||
{"%q", '\'', `'\''`},
|
||||
{"%q", "\u263a", `"☺"`},
|
||||
{"%+q", "\u263a", `"\u263a"`},
|
||||
|
||||
// width
|
||||
{"%5s", "abc", " abc"},
|
||||
@ -187,6 +190,12 @@ var fmttests = []struct {
|
||||
{"%U", 0x12345, "U+12345"},
|
||||
{"%10.6U", 0xABC, " U+000ABC"},
|
||||
{"%-10.6U", 0xABC, "U+000ABC "},
|
||||
{"%U", '\n', `U+000A`},
|
||||
{"%#U", '\n', `U+000A`},
|
||||
{"%U", 'x', `U+0078`},
|
||||
{"%#U", 'x', `U+0078 'x'`},
|
||||
{"%U", '\u263a', `U+263A`},
|
||||
{"%#U", '\u263a', `U+263A '☺'`},
|
||||
|
||||
// floats
|
||||
{"%+.3e", 0.0, "+0.000e+00"},
|
||||
|
@ -7,6 +7,7 @@ package fmt
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
"unicode"
|
||||
"utf8"
|
||||
)
|
||||
|
||||
@ -50,6 +51,7 @@ type fmt struct {
|
||||
sharp bool
|
||||
space bool
|
||||
unicode bool
|
||||
uniQuote bool // Use 'x'= prefix for %U if printable.
|
||||
zero bool
|
||||
}
|
||||
|
||||
@ -63,6 +65,7 @@ func (f *fmt) clearflags() {
|
||||
f.sharp = false
|
||||
f.space = false
|
||||
f.unicode = false
|
||||
f.uniQuote = false
|
||||
f.zero = false
|
||||
}
|
||||
|
||||
@ -232,6 +235,24 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
|
||||
i--
|
||||
buf[i] = ' '
|
||||
}
|
||||
|
||||
// If we want a quoted char for %#U, move the data up to make room.
|
||||
if f.unicode && f.uniQuote && a >= 0 && a <= unicode.MaxRune && unicode.IsPrint(int(a)) {
|
||||
runeWidth := utf8.RuneLen(int(a))
|
||||
width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
|
||||
copy(buf[i-width:], buf[i:]) // guaranteed to have enough room.
|
||||
i -= width
|
||||
// Now put " 'x'" at the end.
|
||||
j := len(buf) - width
|
||||
buf[j] = ' '
|
||||
j++
|
||||
buf[j] = '\''
|
||||
j++
|
||||
utf8.EncodeRune(buf[j:], int(a))
|
||||
j += runeWidth
|
||||
buf[j] = '\''
|
||||
}
|
||||
|
||||
f.pad(buf[i:])
|
||||
}
|
||||
|
||||
@ -291,7 +312,11 @@ func (f *fmt) fmt_q(s string) {
|
||||
if f.sharp && strconv.CanBackquote(s) {
|
||||
quoted = "`" + s + "`"
|
||||
} else {
|
||||
quoted = strconv.Quote(s)
|
||||
if f.plus {
|
||||
quoted = strconv.QuoteToASCII(s)
|
||||
} else {
|
||||
quoted = strconv.Quote(s)
|
||||
}
|
||||
}
|
||||
f.padString(quoted)
|
||||
}
|
||||
@ -299,7 +324,12 @@ func (f *fmt) fmt_q(s string) {
|
||||
// fmt_qc formats the integer as a single-quoted, escaped Go character constant.
|
||||
// If the character is not valid Unicode, it will print '\ufffd'.
|
||||
func (f *fmt) fmt_qc(c int64) {
|
||||
quoted := strconv.QuoteRune(int(c))
|
||||
var quoted string
|
||||
if f.plus {
|
||||
quoted = strconv.QuoteRuneToASCII(int(c))
|
||||
} else {
|
||||
quoted = strconv.QuoteRune(int(c))
|
||||
}
|
||||
f.padString(quoted)
|
||||
}
|
||||
|
||||
|
@ -363,6 +363,8 @@ func (p *pp) fmt0x64(v uint64, leading0x bool) {
|
||||
// temporarily turning on the unicode flag and tweaking the precision.
|
||||
func (p *pp) fmtUnicode(v int64) {
|
||||
precPresent := p.fmt.precPresent
|
||||
sharp := p.fmt.sharp
|
||||
p.fmt.sharp = false
|
||||
prec := p.fmt.prec
|
||||
if !precPresent {
|
||||
// If prec is already set, leave it alone; otherwise 4 is minimum.
|
||||
@ -370,10 +372,13 @@ func (p *pp) fmtUnicode(v int64) {
|
||||
p.fmt.precPresent = true
|
||||
}
|
||||
p.fmt.unicode = true // turn on U+
|
||||
p.fmt.uniQuote = sharp
|
||||
p.fmt.integer(int64(v), 16, unsigned, udigits)
|
||||
p.fmt.unicode = false
|
||||
p.fmt.uniQuote = false
|
||||
p.fmt.prec = prec
|
||||
p.fmt.precPresent = precPresent
|
||||
p.fmt.sharp = sharp
|
||||
}
|
||||
|
||||
func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) {
|
||||
|
Loading…
Reference in New Issue
Block a user