mirror of
https://github.com/golang/go
synced 2024-11-26 02:47:58 -07:00
Made format string handling more efficient.
R=rsc, r, r2 CC=golang-dev https://golang.org/cl/3421042
This commit is contained in:
parent
29d0f02bd2
commit
754f0402c3
@ -45,11 +45,6 @@ func TestFmtInterface(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type fmtTest struct {
|
|
||||||
fmt string
|
|
||||||
val interface{}
|
|
||||||
out string
|
|
||||||
}
|
|
||||||
|
|
||||||
const b32 uint32 = 1<<32 - 1
|
const b32 uint32 = 1<<32 - 1
|
||||||
const b64 uint64 = 1<<64 - 1
|
const b64 uint64 = 1<<64 - 1
|
||||||
@ -106,7 +101,11 @@ func (p *P) String() string {
|
|||||||
|
|
||||||
var b byte
|
var b byte
|
||||||
|
|
||||||
var fmttests = []fmtTest{
|
var fmttests = []struct {
|
||||||
|
fmt string
|
||||||
|
val interface{}
|
||||||
|
out string
|
||||||
|
}{
|
||||||
{"%d", 12345, "12345"},
|
{"%d", 12345, "12345"},
|
||||||
{"%v", 12345, "12345"},
|
{"%v", 12345, "12345"},
|
||||||
{"%t", true, "true"},
|
{"%t", true, "true"},
|
||||||
@ -439,6 +438,12 @@ func BenchmarkSprintfIntInt(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkSprintfPrefixedInt(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCountMallocs(t *testing.T) {
|
func TestCountMallocs(t *testing.T) {
|
||||||
mallocs := 0 - runtime.MemStats.Mallocs
|
mallocs := 0 - runtime.MemStats.Mallocs
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
@ -485,12 +490,10 @@ func (*flagPrinter) Format(f State, c int) {
|
|||||||
io.WriteString(f, "["+s+"]")
|
io.WriteString(f, "["+s+"]")
|
||||||
}
|
}
|
||||||
|
|
||||||
type flagTest struct {
|
var flagtests = []struct {
|
||||||
in string
|
in string
|
||||||
out string
|
out string
|
||||||
}
|
}{
|
||||||
|
|
||||||
var flagtests = []flagTest{
|
|
||||||
{"%a", "[%a]"},
|
{"%a", "[%a]"},
|
||||||
{"%-a", "[%-a]"},
|
{"%-a", "[%-a]"},
|
||||||
{"%+a", "[%+a]"},
|
{"%+a", "[%+a]"},
|
||||||
@ -524,11 +527,10 @@ func TestStructPrinter(t *testing.T) {
|
|||||||
s.a = "abc"
|
s.a = "abc"
|
||||||
s.b = "def"
|
s.b = "def"
|
||||||
s.c = 123
|
s.c = 123
|
||||||
type Test struct {
|
var tests = []struct {
|
||||||
fmt string
|
fmt string
|
||||||
out string
|
out string
|
||||||
}
|
}{
|
||||||
var tests = []Test{
|
|
||||||
{"%v", "{abc def 123}"},
|
{"%v", "{abc def 123}"},
|
||||||
{"%+v", "{a:abc b:def c:123}"},
|
{"%+v", "{a:abc b:def c:123}"},
|
||||||
}
|
}
|
||||||
@ -622,13 +624,11 @@ func TestFormatterPrintln(t *testing.T) {
|
|||||||
|
|
||||||
func args(a ...interface{}) []interface{} { return a }
|
func args(a ...interface{}) []interface{} { return a }
|
||||||
|
|
||||||
type starTest struct {
|
var startests = []struct {
|
||||||
fmt string
|
fmt string
|
||||||
in []interface{}
|
in []interface{}
|
||||||
out string
|
out string
|
||||||
}
|
}{
|
||||||
|
|
||||||
var startests = []starTest{
|
|
||||||
{"%*d", args(4, 42), " 42"},
|
{"%*d", args(4, 42), " 42"},
|
||||||
{"%.*d", args(4, 42), "0042"},
|
{"%.*d", args(4, 42), "0042"},
|
||||||
{"%*.*d", args(8, 4, 42), " 0042"},
|
{"%*.*d", args(8, 4, 42), " 0042"},
|
||||||
@ -644,18 +644,9 @@ var startests = []starTest{
|
|||||||
{"%*d", args(int32(4), 42), "%!(BADWIDTH)42"},
|
{"%*d", args(int32(4), 42), "%!(BADWIDTH)42"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there's no conversion from []T to ...T, but we can fake it. These
|
|
||||||
// functions do the faking. We index the table by the length of the param list.
|
|
||||||
var sprintf = []func(string, []interface{}) string{
|
|
||||||
0: func(f string, i []interface{}) string { return Sprintf(f) },
|
|
||||||
1: func(f string, i []interface{}) string { return Sprintf(f, i[0]) },
|
|
||||||
2: func(f string, i []interface{}) string { return Sprintf(f, i[0], i[1]) },
|
|
||||||
3: func(f string, i []interface{}) string { return Sprintf(f, i[0], i[1], i[2]) },
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWidthAndPrecision(t *testing.T) {
|
func TestWidthAndPrecision(t *testing.T) {
|
||||||
for _, tt := range startests {
|
for _, tt := range startests {
|
||||||
s := sprintf[len(tt.in)](tt.fmt, tt.in)
|
s := Sprintf(tt.fmt, tt.in...)
|
||||||
if s != tt.out {
|
if s != tt.out {
|
||||||
t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
|
t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
|
||||||
}
|
}
|
||||||
|
@ -118,12 +118,7 @@ func (p *pp) Flag(b int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *pp) add(c int) {
|
func (p *pp) add(c int) {
|
||||||
if c < utf8.RuneSelf {
|
p.buf.WriteRune(c)
|
||||||
p.buf.WriteByte(byte(c))
|
|
||||||
} else {
|
|
||||||
w := utf8.EncodeRune(p.runeBuf[0:], c)
|
|
||||||
p.buf.Write(p.runeBuf[0:w])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement Write so we can call Fprintf on a pp (through State), for
|
// Implement Write so we can call Fprintf on a pp (through State), for
|
||||||
@ -825,12 +820,18 @@ func (p *pp) doPrintf(format string, a []interface{}) {
|
|||||||
end := len(format)
|
end := len(format)
|
||||||
fieldnum := 0 // we process one field per non-trivial format
|
fieldnum := 0 // we process one field per non-trivial format
|
||||||
for i := 0; i < end; {
|
for i := 0; i < end; {
|
||||||
c, w := utf8.DecodeRuneInString(format[i:])
|
lasti := i
|
||||||
if c != '%' {
|
for i < end && format[i] != '%' {
|
||||||
p.buf.WriteRune(c)
|
i++
|
||||||
i += w
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
if i > lasti {
|
||||||
|
p.buf.WriteString(format[lasti:i])
|
||||||
|
}
|
||||||
|
if i >= end {
|
||||||
|
// done processing format string
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// Process one verb
|
// Process one verb
|
||||||
i++
|
i++
|
||||||
// flags and widths
|
// flags and widths
|
||||||
@ -876,7 +877,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
|
|||||||
p.buf.Write(noVerbBytes)
|
p.buf.Write(noVerbBytes)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c, w = utf8.DecodeRuneInString(format[i:])
|
c, w := utf8.DecodeRuneInString(format[i:])
|
||||||
i += w
|
i += w
|
||||||
// percent is special - absorbs no operand
|
// percent is special - absorbs no operand
|
||||||
if c == '%' {
|
if c == '%' {
|
||||||
|
Loading…
Reference in New Issue
Block a user