mirror of https://github.com/golang/go.git
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
This commit is contained in:
parent
e596297139
commit
a843b4541a
|
|
@ -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
|
||||||
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{
|
||||||
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{
|
||||||
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{
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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));
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,11 @@
|
||||||
The verbs:
|
The verbs:
|
||||||
|
|
||||||
General:
|
General:
|
||||||
%v for any operand type, the value in a default format.
|
%v the value in a default format.
|
||||||
when printing structs, the plus flag (%+v) adds field names
|
when printing structs, the plus flag (%+v) adds field names
|
||||||
|
%#v a Go-syntax representation of the value
|
||||||
|
%T a Go-syntax representation of the type of the value
|
||||||
|
|
||||||
Boolean:
|
Boolean:
|
||||||
%t the word true or false
|
%t the word true or false
|
||||||
Integer:
|
Integer:
|
||||||
|
|
@ -23,16 +26,16 @@
|
||||||
%X base 16, with upper-case letters for A-F
|
%X base 16, with upper-case letters for A-F
|
||||||
Floating-point:
|
Floating-point:
|
||||||
%e scientific notation, e.g. -1234.456e+78
|
%e scientific notation, e.g. -1234.456e+78
|
||||||
|
%E scientific notation, e.g. -1234.456E+78
|
||||||
%f decimal point but no exponent, e.g. 123.456
|
%f decimal point but no exponent, e.g. 123.456
|
||||||
%g whichever of %e or %f produces more compact output
|
%g whichever of %e or %f produces more compact output
|
||||||
|
%G whichever of %E or %f produces more compact output
|
||||||
String and slice of bytes:
|
String and slice of bytes:
|
||||||
%s the uninterpreted bytes of the string or slice
|
%s the uninterpreted bytes of the string or slice
|
||||||
%q a double-quoted string safely escaped with Go syntax
|
%q a double-quoted string safely escaped with Go syntax
|
||||||
%x base 16 notation with two characters per byte
|
%x base 16 notation with two characters per byte
|
||||||
Pointer:
|
Pointer:
|
||||||
%p base 16 notation, with leading 0x
|
%p base 16 notation, with leading 0x
|
||||||
Type:
|
|
||||||
%T a Go-syntax representation of the type of the operand
|
|
||||||
|
|
||||||
There is no 'u' flag. Integers are printed unsigned if they have unsigned type.
|
There is no 'u' flag. Integers are printed unsigned if they have unsigned type.
|
||||||
Similarly, there is no need to specify the size of the operand (int8, int64).
|
Similarly, there is no need to specify the size of the operand (int8, int64).
|
||||||
|
|
@ -95,21 +98,29 @@ type State interface {
|
||||||
Flag(int) bool;
|
Flag(int) bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatter is the interface implemented by objects with a custom formatter.
|
// Formatter is the interface implemented by values with a custom formatter.
|
||||||
// The implementation of Format may call Sprintf or Fprintf(f) etc.
|
// The implementation of Format may call Sprintf or Fprintf(f) etc.
|
||||||
// to generate its output.
|
// to generate its output.
|
||||||
type Formatter interface {
|
type Formatter interface {
|
||||||
Format(f State, c int);
|
Format(f State, c int);
|
||||||
}
|
}
|
||||||
|
|
||||||
// String represents any object being printed that has a String() method that
|
// Stringer is implemented by any value that has a String method(),
|
||||||
// returns a string, which defines the ``native'' format for that object.
|
// which defines the ``native'' format for that value.
|
||||||
// Any such object will be printed using that method if passed
|
// The String method is used to print values passed as an operand
|
||||||
// as operand to a %s or %v format or to an unformatted printer such as Print.
|
// to a %s or %v format or to an unformatted printer such as Print.
|
||||||
type Stringer interface {
|
type Stringer interface {
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GoStringer is implemented by any value that has a GoString() method,
|
||||||
|
// which defines the Go syntax for that value.
|
||||||
|
// The GoString method is used to print values passed as an operand
|
||||||
|
// to a %#v format.
|
||||||
|
type GoStringer interface {
|
||||||
|
GoString() string
|
||||||
|
}
|
||||||
|
|
||||||
const runeSelf = utf8.RuneSelf
|
const runeSelf = utf8.RuneSelf
|
||||||
const allocSize = 32
|
const allocSize = 32
|
||||||
|
|
||||||
|
|
@ -392,15 +403,28 @@ func parsenum(s string, start, end int) (n int, got bool, newi int) {
|
||||||
return num, isnum, start;
|
return num, isnum, start;
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pp) printField(field reflect.Value) (was_string bool) {
|
type uintptrGetter interface {
|
||||||
|
Get() uintptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pp) printField(field reflect.Value, plus, sharp bool, depth int) (was_string bool) {
|
||||||
inter := field.Interface();
|
inter := field.Interface();
|
||||||
if inter != nil {
|
if inter != nil {
|
||||||
if stringer, ok := inter.(Stringer); ok {
|
switch {
|
||||||
p.addstr(stringer.String());
|
default:
|
||||||
return false; // this value is not a string
|
if stringer, ok := inter.(Stringer); ok {
|
||||||
|
p.addstr(stringer.String());
|
||||||
|
return false; // this value is not a string
|
||||||
|
}
|
||||||
|
case sharp:
|
||||||
|
if stringer, ok := inter.(GoStringer); ok {
|
||||||
|
p.addstr(stringer.GoString());
|
||||||
|
return false; // this value is not a string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s := "";
|
s := "";
|
||||||
|
BigSwitch:
|
||||||
switch f := field.(type) {
|
switch f := field.(type) {
|
||||||
case *reflect.BoolValue:
|
case *reflect.BoolValue:
|
||||||
s = p.fmt.Fmt_boolean(f.Get()).Str();
|
s = p.fmt.Fmt_boolean(f.Get()).Str();
|
||||||
|
|
@ -415,79 +439,160 @@ func (p *pp) printField(field reflect.Value) (was_string bool) {
|
||||||
s = p.fmt.Fmt_g64(float64(f.Get())).Str();
|
s = p.fmt.Fmt_g64(float64(f.Get())).Str();
|
||||||
}
|
}
|
||||||
case *reflect.StringValue:
|
case *reflect.StringValue:
|
||||||
s = p.fmt.Fmt_s(f.Get()).Str();
|
if sharp {
|
||||||
was_string = true;
|
s = p.fmt.Fmt_q(f.Get()).Str();
|
||||||
case *reflect.PtrValue:
|
} else {
|
||||||
v := f.Get();
|
s = p.fmt.Fmt_s(f.Get()).Str();
|
||||||
if v == 0 {
|
was_string = true;
|
||||||
s = "<nil>";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// pointer to array?
|
|
||||||
if a, ok := f.Elem().(reflect.ArrayOrSliceValue); ok {
|
|
||||||
p.addstr("&");
|
|
||||||
p.printField(a);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p.fmt.sharp = !p.fmt.sharp; // turn 0x on by default
|
|
||||||
s = p.fmt.Fmt_ux64(uint64(v)).Str();
|
|
||||||
case reflect.ArrayOrSliceValue:
|
|
||||||
p.addstr("[");
|
|
||||||
for i := 0; i < f.Len(); i++ {
|
|
||||||
if i > 0 {
|
|
||||||
p.addstr(" ");
|
|
||||||
}
|
|
||||||
p.printField(f.Elem(i));
|
|
||||||
}
|
|
||||||
p.addstr("]");
|
|
||||||
case *reflect.MapValue:
|
case *reflect.MapValue:
|
||||||
p.addstr("map[");
|
if sharp {
|
||||||
|
p.addstr(field.Type().String());
|
||||||
|
p.addstr("{");
|
||||||
|
} else {
|
||||||
|
p.addstr("map[");
|
||||||
|
}
|
||||||
keys := f.Keys();
|
keys := f.Keys();
|
||||||
for i, key := range keys {
|
for i, key := range keys {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
p.addstr(" ");
|
if sharp {
|
||||||
|
p.addstr(", ");
|
||||||
|
} else {
|
||||||
|
p.addstr(" ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.printField(key);
|
p.printField(key, plus, sharp, depth+1);
|
||||||
p.addstr(":");
|
p.addstr(":");
|
||||||
p.printField(f.Elem(key));
|
p.printField(f.Elem(key), plus, sharp, depth+1);
|
||||||
|
}
|
||||||
|
if sharp {
|
||||||
|
p.addstr("}");
|
||||||
|
} else {
|
||||||
|
p.addstr("]");
|
||||||
}
|
}
|
||||||
p.addstr("]");
|
|
||||||
case *reflect.StructValue:
|
case *reflect.StructValue:
|
||||||
|
if sharp {
|
||||||
|
p.addstr(field.Type().String());
|
||||||
|
}
|
||||||
p.add('{');
|
p.add('{');
|
||||||
v := f;
|
v := f;
|
||||||
t := v.Type().(*reflect.StructType);
|
t := v.Type().(*reflect.StructType);
|
||||||
donames := p.fmt.plus;
|
|
||||||
p.fmt.clearflags(); // clear flags for p.printField
|
p.fmt.clearflags(); // clear flags for p.printField
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
p.add(' ')
|
if sharp {
|
||||||
|
p.addstr(", ");
|
||||||
|
} else {
|
||||||
|
p.addstr(" ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if donames {
|
if plus || sharp {
|
||||||
if f := t.Field(i); f.Name != "" {
|
if f := t.Field(i); f.Name != "" {
|
||||||
p.addstr(f.Name);
|
p.addstr(f.Name);
|
||||||
p.add(':');
|
p.add(':');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.printField(getField(v, i));
|
p.printField(getField(v, i), plus, sharp, depth+1);
|
||||||
}
|
}
|
||||||
p.add('}');
|
p.addstr("}");
|
||||||
case *reflect.InterfaceValue:
|
case *reflect.InterfaceValue:
|
||||||
value := f.Elem();
|
value := f.Elem();
|
||||||
if value == nil {
|
if value == nil {
|
||||||
s = "<nil>"
|
if sharp {
|
||||||
|
p.addstr(field.Type().String());
|
||||||
|
p.addstr("(nil)");
|
||||||
|
} else {
|
||||||
|
s = "<nil>"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return p.printField(value);
|
return p.printField(value, plus, sharp, depth+1);
|
||||||
|
}
|
||||||
|
case reflect.ArrayOrSliceValue:
|
||||||
|
if sharp {
|
||||||
|
p.addstr(field.Type().String());
|
||||||
|
p.addstr("{");
|
||||||
|
} else {
|
||||||
|
p.addstr("[");
|
||||||
|
}
|
||||||
|
for i := 0; i < f.Len(); i++ {
|
||||||
|
if i > 0 {
|
||||||
|
if sharp {
|
||||||
|
p.addstr(", ");
|
||||||
|
} else {
|
||||||
|
p.addstr(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.printField(f.Elem(i), plus, sharp, depth+1);
|
||||||
|
}
|
||||||
|
if sharp {
|
||||||
|
p.addstr("}");
|
||||||
|
} else {
|
||||||
|
p.addstr("]");
|
||||||
|
}
|
||||||
|
case *reflect.PtrValue:
|
||||||
|
v := f.Get();
|
||||||
|
// pointer to array or slice or struct? ok at top level
|
||||||
|
// but not embedded (avoid loops)
|
||||||
|
if v != 0 && depth == 0 {
|
||||||
|
switch a := f.Elem().(type) {
|
||||||
|
case reflect.ArrayOrSliceValue:
|
||||||
|
p.addstr("&");
|
||||||
|
p.printField(a, plus, sharp, depth+1);
|
||||||
|
break BigSwitch;
|
||||||
|
case *reflect.StructValue:
|
||||||
|
p.addstr("&");
|
||||||
|
p.printField(a, plus, sharp, depth+1);
|
||||||
|
break BigSwitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sharp {
|
||||||
|
p.addstr("(");
|
||||||
|
p.addstr(field.Type().String());
|
||||||
|
p.addstr(")(");
|
||||||
|
if v == 0 {
|
||||||
|
p.addstr("nil");
|
||||||
|
} else {
|
||||||
|
p.fmt.sharp = true;
|
||||||
|
p.addstr(p.fmt.Fmt_ux64(uint64(v)).Str());
|
||||||
|
}
|
||||||
|
p.addstr(")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
s = "<nil>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p.fmt.sharp = true; // turn 0x on
|
||||||
|
s = p.fmt.Fmt_ux64(uint64(v)).Str();
|
||||||
|
case uintptrGetter:
|
||||||
|
v := f.Get();
|
||||||
|
if sharp {
|
||||||
|
p.addstr("(");
|
||||||
|
p.addstr(field.Type().String());
|
||||||
|
p.addstr(")(");
|
||||||
|
if v == 0 {
|
||||||
|
p.addstr("nil");
|
||||||
|
} else {
|
||||||
|
p.fmt.sharp = true;
|
||||||
|
p.addstr(p.fmt.Fmt_ux64(uint64(v)).Str());
|
||||||
|
}
|
||||||
|
p.addstr(")");
|
||||||
|
} else {
|
||||||
|
p.fmt.sharp = true; // turn 0x on
|
||||||
|
p.addstr(p.fmt.Fmt_ux64(uint64(f.Get())).Str());
|
||||||
}
|
}
|
||||||
case *reflect.UintptrValue:
|
|
||||||
p.fmt.sharp = !p.fmt.sharp; // turn 0x on by default
|
|
||||||
s = p.fmt.Fmt_ux64(uint64(f.Get())).Str();
|
|
||||||
default:
|
default:
|
||||||
v, signed, ok := getInt(field);
|
v, signed, ok := getInt(field);
|
||||||
if ok {
|
if ok {
|
||||||
if signed {
|
if signed {
|
||||||
s = p.fmt.Fmt_d64(v).Str();
|
s = p.fmt.Fmt_d64(v).Str();
|
||||||
} else {
|
} else {
|
||||||
s = p.fmt.Fmt_ud64(uint64(v)).Str();
|
if sharp {
|
||||||
|
p.fmt.sharp = true; // turn on 0x
|
||||||
|
s = p.fmt.Fmt_ux64(uint64(v)).Str();
|
||||||
|
} else {
|
||||||
|
s = p.fmt.Fmt_ud64(uint64(v)).Str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -548,13 +653,17 @@ func (p *pp) doprintf(format string, v *reflect.StructValue) {
|
||||||
}
|
}
|
||||||
field := getField(v, fieldnum);
|
field := getField(v, fieldnum);
|
||||||
fieldnum++;
|
fieldnum++;
|
||||||
|
|
||||||
|
// Try formatter except for %T,
|
||||||
|
// which is special and handled internally.
|
||||||
inter := field.Interface();
|
inter := field.Interface();
|
||||||
if inter != nil && c != 'T' { // don't want thing to describe itself if we're asking for its type
|
if inter != nil && c != 'T' {
|
||||||
if formatter, ok := inter.(Formatter); ok {
|
if formatter, ok := inter.(Formatter); ok {
|
||||||
formatter.Format(p, c);
|
formatter.Format(p, c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s := "";
|
s := "";
|
||||||
switch c {
|
switch c {
|
||||||
// bool
|
// bool
|
||||||
|
|
@ -640,6 +749,14 @@ func (p *pp) doprintf(format string, v *reflect.StructValue) {
|
||||||
} else {
|
} else {
|
||||||
goto badtype
|
goto badtype
|
||||||
}
|
}
|
||||||
|
case 'E':
|
||||||
|
if v, ok := getFloat32(field); ok {
|
||||||
|
s = p.fmt.Fmt_E32(v).Str()
|
||||||
|
} else if v, ok := getFloat64(field); ok {
|
||||||
|
s = p.fmt.Fmt_E64(v).Str()
|
||||||
|
} else {
|
||||||
|
goto badtype
|
||||||
|
}
|
||||||
case 'f':
|
case 'f':
|
||||||
if v, ok := getFloat32(field); ok {
|
if v, ok := getFloat32(field); ok {
|
||||||
s = p.fmt.Fmt_f32(v).Str()
|
s = p.fmt.Fmt_f32(v).Str()
|
||||||
|
|
@ -656,6 +773,14 @@ func (p *pp) doprintf(format string, v *reflect.StructValue) {
|
||||||
} else {
|
} else {
|
||||||
goto badtype
|
goto badtype
|
||||||
}
|
}
|
||||||
|
case 'G':
|
||||||
|
if v, ok := getFloat32(field); ok {
|
||||||
|
s = p.fmt.Fmt_G32(v).Str()
|
||||||
|
} else if v, ok := getFloat64(field); ok {
|
||||||
|
s = p.fmt.Fmt_G64(v).Str()
|
||||||
|
} else {
|
||||||
|
goto badtype
|
||||||
|
}
|
||||||
|
|
||||||
// string
|
// string
|
||||||
case 's':
|
case 's':
|
||||||
|
|
@ -692,7 +817,10 @@ func (p *pp) doprintf(format string, v *reflect.StructValue) {
|
||||||
|
|
||||||
// arbitrary value; do your best
|
// arbitrary value; do your best
|
||||||
case 'v':
|
case 'v':
|
||||||
p.printField(field);
|
plus, sharp := p.fmt.plus, p.fmt.sharp;
|
||||||
|
p.fmt.plus = false;
|
||||||
|
p.fmt.sharp = false;
|
||||||
|
p.printField(field, plus, sharp, 0);
|
||||||
|
|
||||||
// the value's type
|
// the value's type
|
||||||
case 'T':
|
case 'T':
|
||||||
|
|
@ -702,8 +830,8 @@ func (p *pp) doprintf(format string, v *reflect.StructValue) {
|
||||||
badtype:
|
badtype:
|
||||||
s = "%" + string(c) + "(" + field.Type().String() + "=";
|
s = "%" + string(c) + "(" + field.Type().String() + "=";
|
||||||
p.addstr(s);
|
p.addstr(s);
|
||||||
p.printField(field);
|
p.printField(field, false, false, 0);
|
||||||
s= ")%";
|
s = ")";
|
||||||
}
|
}
|
||||||
p.addstr(s);
|
p.addstr(s);
|
||||||
}
|
}
|
||||||
|
|
@ -713,7 +841,7 @@ func (p *pp) doprintf(format string, v *reflect.StructValue) {
|
||||||
field := getField(v, fieldnum);
|
field := getField(v, fieldnum);
|
||||||
p.addstr(field.Type().String());
|
p.addstr(field.Type().String());
|
||||||
p.addstr("=");
|
p.addstr("=");
|
||||||
p.printField(field);
|
p.printField(field, false, false, 0);
|
||||||
if fieldnum + 1 < v.NumField() {
|
if fieldnum + 1 < v.NumField() {
|
||||||
p.addstr(", ");
|
p.addstr(", ");
|
||||||
}
|
}
|
||||||
|
|
@ -733,7 +861,7 @@ func (p *pp) doprint(v *reflect.StructValue, addspace, addnewline bool) {
|
||||||
p.add(' ');
|
p.add(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prev_string = p.printField(field);
|
prev_string = p.printField(field, false, false, 0);
|
||||||
}
|
}
|
||||||
if addnewline {
|
if addnewline {
|
||||||
p.add('\n')
|
p.add('\n')
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
}
|
}
|
||||||
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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// %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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue