Commit a843b454 authored by Russ Cox's avatar Russ Cox

fmt: add verbs:

	%E - upper case %e
	%G - upper case %g
	%#v - Go syntax

R=r
DELTA=332  (238 added, 47 deleted, 47 changed)
OCL=34091
CL=34145
parent e5962971
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"math"; "math";
"strings"; "strings";
"testing"; "testing";
"unsafe";
) )
func TestFmtInterface(t *testing.T) { func TestFmtInterface(t *testing.T) {
...@@ -32,6 +33,15 @@ const b64 uint64 = 1<<64 - 1 ...@@ -32,6 +33,15 @@ const b64 uint64 = 1<<64 - 1
var array = []int{1, 2, 3, 4, 5} var array = []int{1, 2, 3, 4, 5}
var iarray = []interface{}{1, "hello", 2.5, nil} var iarray = []interface{}{1, "hello", 2.5, nil}
type A struct {
i int;
j uint;
s string;
x []int;
}
var b byte;
var fmttests = []fmtTest{ var fmttests = []fmtTest{
// basic string // basic string
fmtTest{ "%s", "abc", "abc" }, fmtTest{ "%s", "abc", "abc" },
...@@ -79,15 +89,9 @@ var fmttests = []fmtTest{ ...@@ -79,15 +89,9 @@ var fmttests = []fmtTest{
fmtTest{ "%+d", -12345, "-12345" }, fmtTest{ "%+d", -12345, "-12345" },
fmtTest{ "% d", 12345, " 12345" }, fmtTest{ "% d", 12345, " 12345" },
// arrays
fmtTest{ "%v", array, "[1 2 3 4 5]" },
fmtTest{ "%v", iarray, "[1 hello 2.5 <nil>]" },
fmtTest{ "%v", &array, "&[1 2 3 4 5]" },
fmtTest{ "%v", &iarray, "&[1 hello 2.5 <nil>]" },
// erroneous formats // erroneous formats
fmtTest{ "", 2, "?(extra int=2)" }, fmtTest{ "", 2, "?(extra int=2)" },
fmtTest{ "%d", "hello", "%d(string=hello)%" }, fmtTest{ "%d", "hello", "%d(string=hello)" },
// old test/fmt_test.go // old test/fmt_test.go
fmtTest{ "%d", 1234, "1234" }, fmtTest{ "%d", 1234, "1234" },
...@@ -123,6 +127,17 @@ var fmttests = []fmtTest{ ...@@ -123,6 +127,17 @@ var fmttests = []fmtTest{
fmtTest{ "%g", float64(-7), "-7" }, fmtTest{ "%g", float64(-7), "-7" },
fmtTest{ "%g", float64(-1e-9), "-1e-09", }, fmtTest{ "%g", float64(-1e-9), "-1e-09", },
fmtTest{ "%g", float32(-1e-9), "-1e-09" }, fmtTest{ "%g", float32(-1e-9), "-1e-09" },
fmtTest{ "%E", float64(1), "1.000000E+00" },
fmtTest{ "%E", float64(1234.5678e3), "1.234568E+06" },
fmtTest{ "%E", float64(1234.5678e-8), "1.234568E-05" },
fmtTest{ "%E", float64(-7), "-7.000000E+00" },
fmtTest{ "%E", float64(-1e-9), "-1.000000E-09" },
fmtTest{ "%G", float64(1234.5678e3), "1.2345678E+06" },
fmtTest{ "%G", float32(1234.5678e3), "1.2345678E+06" },
fmtTest{ "%G", float64(1234.5678e-8), "1.2345678E-05" },
fmtTest{ "%G", float64(-7), "-7" },
fmtTest{ "%G", float64(-1e-9), "-1E-09", },
fmtTest{ "%G", float32(-1e-9), "-1E-09" },
fmtTest{ "%c", 'x', "x" }, fmtTest{ "%c", 'x', "x" },
fmtTest{ "%c", 0xe4, "ä" }, fmtTest{ "%c", 0xe4, "ä" },
fmtTest{ "%c", 0x672c, "本" }, fmtTest{ "%c", 0x672c, "本" },
...@@ -158,11 +173,39 @@ var fmttests = []fmtTest{ ...@@ -158,11 +173,39 @@ var fmttests = []fmtTest{
fmtTest{ "%20e", math.Inf(1), " +Inf" }, fmtTest{ "%20e", math.Inf(1), " +Inf" },
fmtTest{ "%-20f", math.Inf(-1), "-Inf " }, fmtTest{ "%-20f", math.Inf(-1), "-Inf " },
fmtTest{ "%20g", math.NaN(), " NaN" }, fmtTest{ "%20g", math.NaN(), " NaN" },
// arrays
fmtTest{ "%v", array, "[1 2 3 4 5]" },
fmtTest{ "%v", iarray, "[1 hello 2.5 <nil>]" },
fmtTest{ "%v", &array, "&[1 2 3 4 5]" },
fmtTest{ "%v", &iarray, "&[1 hello 2.5 <nil>]" },
// structs
fmtTest{ "%v", A{1,2,"a",[]int{1,2}}, `{1 2 a [1 2]}` },
fmtTest{ "%+v", A{1,2,"a",[]int{1,2}}, `{i:1 j:2 s:a x:[1 2]}` },
// go syntax
fmtTest{ "%#v", A{1,2,"a",[]int{1,2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}` },
fmtTest{ "%#v", &b, "(*uint8)(PTR)" },
fmtTest{ "%#v", TestFmtInterface, "(func(*testing.T))(PTR)" },
fmtTest{ "%#v", make(chan int), "(chan int)(PTR)" },
fmtTest{ "%#v", uint64(1<<64-1), "0xffffffffffffffff" },
fmtTest{ "%#v", 1000000000, "1000000000" },
} }
func TestSprintf(t *testing.T) { func TestSprintf(t *testing.T) {
for i, tt := range fmttests { for i, tt := range fmttests {
s := Sprintf(tt.fmt, tt.val); s := Sprintf(tt.fmt, tt.val);
if i := strings.Index(s, "0x"); i >= 0 && strings.Index(tt.out, "PTR") >= 0 {
j := i+2;
for ; j < len(s); j++ {
c := s[j];
if (c < '0' || c > '9') && (c < 'a' || c > 'f') {
break;
}
}
s = s[0:i] + "PTR" + s[j:len(s)];
}
if s != tt.out { if s != tt.out {
if ss, ok := tt.val.(string); ok { if ss, ok := tt.val.(string); ok {
// Don't requote the already-quoted strings. // Don't requote the already-quoted strings.
......
...@@ -465,6 +465,11 @@ func (f *Fmt) Fmt_e64(v float64) *Fmt { ...@@ -465,6 +465,11 @@ func (f *Fmt) Fmt_e64(v float64) *Fmt {
return fmtString(f, strconv.Ftoa64(v, 'e', doPrec(f, 6))); return fmtString(f, strconv.Ftoa64(v, 'e', doPrec(f, 6)));
} }
// Fmt_E64 formats a float64 in the form -1.23E+12.
func (f *Fmt) Fmt_E64(v float64) *Fmt {
return fmtString(f, strconv.Ftoa64(v, 'E', doPrec(f, 6)));
}
// Fmt_f64 formats a float64 in the form -1.23. // Fmt_f64 formats a float64 in the form -1.23.
func (f *Fmt) Fmt_f64(v float64) *Fmt { func (f *Fmt) Fmt_f64(v float64) *Fmt {
return fmtString(f, strconv.Ftoa64(v, 'f', doPrec(f, 6))); return fmtString(f, strconv.Ftoa64(v, 'f', doPrec(f, 6)));
...@@ -475,6 +480,11 @@ func (f *Fmt) Fmt_g64(v float64) *Fmt { ...@@ -475,6 +480,11 @@ func (f *Fmt) Fmt_g64(v float64) *Fmt {
return fmtString(f, strconv.Ftoa64(v, 'g', doPrec(f, -1))); return fmtString(f, strconv.Ftoa64(v, 'g', doPrec(f, -1)));
} }
// Fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
func (f *Fmt) Fmt_G64(v float64) *Fmt {
return fmtString(f, strconv.Ftoa64(v, 'G', doPrec(f, -1)));
}
// Fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2). // Fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
func (f *Fmt) Fmt_fb64(v float64) *Fmt { func (f *Fmt) Fmt_fb64(v float64) *Fmt {
return fmtString(f, strconv.Ftoa64(v, 'b', 0)); return fmtString(f, strconv.Ftoa64(v, 'b', 0));
...@@ -489,6 +499,11 @@ func (f *Fmt) Fmt_e32(v float32) *Fmt { ...@@ -489,6 +499,11 @@ func (f *Fmt) Fmt_e32(v float32) *Fmt {
return fmtString(f, strconv.Ftoa32(v, 'e', doPrec(f, 6))); return fmtString(f, strconv.Ftoa32(v, 'e', doPrec(f, 6)));
} }
// Fmt_E32 formats a float32 in the form -1.23E+12.
func (f *Fmt) Fmt_E32(v float32) *Fmt {
return fmtString(f, strconv.Ftoa32(v, 'e', doPrec(f, 6)));
}
// Fmt_f32 formats a float32 in the form -1.23. // Fmt_f32 formats a float32 in the form -1.23.
func (f *Fmt) Fmt_f32(v float32) *Fmt { func (f *Fmt) Fmt_f32(v float32) *Fmt {
return fmtString(f, strconv.Ftoa32(v, 'f', doPrec(f, 6))); return fmtString(f, strconv.Ftoa32(v, 'f', doPrec(f, 6)));
...@@ -499,6 +514,11 @@ func (f *Fmt) Fmt_g32(v float32) *Fmt { ...@@ -499,6 +514,11 @@ func (f *Fmt) Fmt_g32(v float32) *Fmt {
return fmtString(f, strconv.Ftoa32(v, 'g', doPrec(f, -1))); return fmtString(f, strconv.Ftoa32(v, 'g', doPrec(f, -1)));
} }
// Fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
func (f *Fmt) Fmt_G32(v float32) *Fmt {
return fmtString(f, strconv.Ftoa32(v, 'G', doPrec(f, -1)));
}
// Fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2). // Fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
func (f *Fmt) Fmt_fb32(v float32) *Fmt { func (f *Fmt) Fmt_fb32(v float32) *Fmt {
return fmtString(f, strconv.Ftoa32(v, 'b', 0)); return fmtString(f, strconv.Ftoa32(v, 'b', 0));
......
This diff is collapsed.
...@@ -115,20 +115,20 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string { ...@@ -115,20 +115,20 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
shortest = true; shortest = true;
roundShortest(d, mant, exp, flt); roundShortest(d, mant, exp, flt);
switch fmt { switch fmt {
case 'e': case 'e', 'E':
prec = d.nd - 1; prec = d.nd - 1;
case 'f': case 'f':
prec = max(d.nd - d.dp, 0); prec = max(d.nd - d.dp, 0);
case 'g': case 'g', 'G':
prec = d.nd; prec = d.nd;
} }
} else { } else {
switch fmt { switch fmt {
case 'e': case 'e', 'E':
d.Round(prec+1); d.Round(prec+1);
case 'f': case 'f':
d.Round(d.dp+prec); d.Round(d.dp+prec);
case 'g': case 'g', 'G':
if prec == 0 { if prec == 0 {
prec = 1; prec = 1;
} }
...@@ -137,11 +137,11 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string { ...@@ -137,11 +137,11 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
} }
switch fmt { switch fmt {
case 'e': case 'e', 'E':
return fmtE(neg, d, prec); return fmtE(neg, d, prec, fmt);
case 'f': case 'f':
return fmtF(neg, d, prec); return fmtF(neg, d, prec);
case 'g': case 'g', 'G':
// trailing zeros are removed. // trailing zeros are removed.
if prec > d.nd { if prec > d.nd {
prec = d.nd; prec = d.nd;
...@@ -155,7 +155,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string { ...@@ -155,7 +155,7 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
} }
exp := d.dp - 1; exp := d.dp - 1;
if exp < -4 || exp >= eprec { if exp < -4 || exp >= eprec {
return fmtE(neg, d, prec - 1); return fmtE(neg, d, prec - 1, fmt + 'e' - 'g');
} }
return fmtF(neg, d, max(prec - d.dp, 0)); return fmtF(neg, d, max(prec - d.dp, 0));
} }
...@@ -251,7 +251,7 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { ...@@ -251,7 +251,7 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
} }
// %e: -d.ddddde±dd // %e: -d.ddddde±dd
func fmtE(neg bool, d *decimal, prec int) string { func fmtE(neg bool, d *decimal, prec int, fmt byte) string {
buf := make([]byte, 3+max(prec, 0)+30); // "-0." + prec digits + exp buf := make([]byte, 3+max(prec, 0)+30); // "-0." + prec digits + exp
w := 0; // write index w := 0; // write index
...@@ -284,7 +284,7 @@ func fmtE(neg bool, d *decimal, prec int) string { ...@@ -284,7 +284,7 @@ func fmtE(neg bool, d *decimal, prec int) string {
} }
// e± // e±
buf[w] = 'e'; buf[w] = fmt;
w++; w++;
exp := d.dp - 1; exp := d.dp - 1;
if d.nd == 0 { // special case: 0 has exponent 0 if d.nd == 0 { // special case: 0 has exponent 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment