mirror of
https://github.com/golang/go
synced 2024-11-26 13:48:05 -07:00
Polymorphic printing.
R=rsc DELTA=100 (70 added, 10 deleted, 20 changed) OCL=18663 CL=18669
This commit is contained in:
parent
79fbbe37a7
commit
f15dfa7802
@ -15,6 +15,23 @@ import (
|
|||||||
"os";
|
"os";
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export type Writer interface {
|
||||||
|
Write(b *[]byte) (ret int, err *os.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Representation of printer state passed to custom formatters.
|
||||||
|
// Provides access to the Writer interface plus information about
|
||||||
|
// the active formatting verb.
|
||||||
|
export type FormatHelper interface {
|
||||||
|
Write(b *[]byte) (ret int, err *os.Error);
|
||||||
|
Width() (wid int, ok bool);
|
||||||
|
Precision() (prec int, ok bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Formatter interface {
|
||||||
|
Format(f FormatHelper, c int);
|
||||||
|
}
|
||||||
|
|
||||||
const Runeself = 0x80
|
const Runeself = 0x80
|
||||||
const AllocSize = 32
|
const AllocSize = 32
|
||||||
|
|
||||||
@ -22,6 +39,10 @@ type P struct {
|
|||||||
n int;
|
n int;
|
||||||
buf *[]byte;
|
buf *[]byte;
|
||||||
fmt *Fmt;
|
fmt *Fmt;
|
||||||
|
wid int;
|
||||||
|
wid_ok bool;
|
||||||
|
prec int;
|
||||||
|
prec_ok bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
func Printer() *P {
|
func Printer() *P {
|
||||||
@ -30,6 +51,14 @@ func Printer() *P {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *P) Width() (wid int, ok bool) {
|
||||||
|
return p.wid, p.wid_ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *P) Precision() (prec int, ok bool) {
|
||||||
|
return p.prec, p.prec_ok
|
||||||
|
}
|
||||||
|
|
||||||
func (p *P) ensure(n int) {
|
func (p *P) ensure(n int) {
|
||||||
if p.buf == nil || len(p.buf) < n {
|
if p.buf == nil || len(p.buf) < n {
|
||||||
newn := AllocSize;
|
newn := AllocSize;
|
||||||
@ -81,10 +110,6 @@ func (p *P) Write(b *[]byte) (ret int, err *os.Error) {
|
|||||||
return len(b), nil;
|
return len(b), nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Writer interface {
|
|
||||||
Write(b *[]byte) (ret int, err *os.Error);
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *P) doprintf(format string, v reflect.StructValue);
|
func (p *P) doprintf(format string, v reflect.StructValue);
|
||||||
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);
|
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);
|
||||||
|
|
||||||
@ -159,6 +184,14 @@ export func sprintln(v ...) string {
|
|||||||
|
|
||||||
// Getters for the fields of the argument structure.
|
// Getters for the fields of the argument structure.
|
||||||
|
|
||||||
|
func getBool(v reflect.Value) (val bool, ok bool) {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.BoolKind:
|
||||||
|
return v.(reflect.BoolValue).Get(), true;
|
||||||
|
}
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
func getInt(v reflect.Value) (val int64, signed, ok bool) {
|
func getInt(v reflect.Value) (val int64, signed, ok bool) {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case reflect.IntKind:
|
case reflect.IntKind:
|
||||||
@ -215,7 +248,7 @@ func getPtr(v reflect.Value) (val uint64, ok bool) {
|
|||||||
return 0, false;
|
return 0, false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert ASCII to integer.
|
// Convert ASCII to integer. n is 0 (and got is false) if no number present.
|
||||||
|
|
||||||
func parsenum(s string, start, end int) (n int, got bool, newi int) {
|
func parsenum(s string, start, end int) (n int, got bool, newi int) {
|
||||||
if start >= end {
|
if start >= end {
|
||||||
@ -248,18 +281,12 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
i += w;
|
i += w;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var got bool;
|
|
||||||
// saw % - do we have %20 (width)?
|
// saw % - do we have %20 (width)?
|
||||||
w, got, i = parsenum(format, i+1, end);
|
p.wid, p.wid_ok, i = parsenum(format, i+1, end);
|
||||||
if got {
|
p.prec_ok = false;
|
||||||
p.fmt.w(w);
|
|
||||||
}
|
|
||||||
// do we have %.20 (precision)?
|
// do we have %.20 (precision)?
|
||||||
if i < end && format[i] == '.' {
|
if i < end && format[i] == '.' {
|
||||||
w, got, i = parsenum(format, i+1, end);
|
p.prec, p.prec_ok, i = parsenum(format, i+1, end);
|
||||||
if got {
|
|
||||||
p.fmt.p(w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c, w = sys.stringtorune(format, i);
|
c, w = sys.stringtorune(format, i);
|
||||||
i += w;
|
i += w;
|
||||||
@ -269,19 +296,35 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if fieldnum >= v.Len() { // out of operands
|
if fieldnum >= v.Len() { // out of operands
|
||||||
p.addstr("???");
|
p.add('%');
|
||||||
|
p.add(c);
|
||||||
|
p.addstr("(missing)");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
field := v.Field(fieldnum);
|
field := v.Field(fieldnum);
|
||||||
fieldnum++;
|
fieldnum++;
|
||||||
|
if formatter, ok := field.Interface().(Formatter); ok {
|
||||||
|
formatter.Format(p, c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
s := "";
|
s := "";
|
||||||
|
if p.wid_ok {
|
||||||
|
p.fmt.w(p.wid);
|
||||||
|
}
|
||||||
|
if p.prec_ok {
|
||||||
|
p.fmt.p(p.prec);
|
||||||
|
}
|
||||||
switch c {
|
switch c {
|
||||||
// bool
|
// bool
|
||||||
case 't':
|
case 't':
|
||||||
if field.(reflect.BoolValue).Get() {
|
if v, ok := getBool(field); ok {
|
||||||
s = "true";
|
if v {
|
||||||
|
s = "true";
|
||||||
|
} else {
|
||||||
|
s = "false";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s = "false";
|
goto badtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int
|
// int
|
||||||
@ -289,7 +332,13 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
if v, signed, ok := getInt(field); ok {
|
if v, signed, ok := getInt(field); ok {
|
||||||
s = p.fmt.b64(uint64(v)).str() // always unsigned
|
s = p.fmt.b64(uint64(v)).str() // always unsigned
|
||||||
} else {
|
} else {
|
||||||
s = "%b%"
|
goto badtype
|
||||||
|
}
|
||||||
|
case 'c':
|
||||||
|
if v, signed, ok := getInt(field); ok {
|
||||||
|
s = p.fmt.c(int(v)).str()
|
||||||
|
} else {
|
||||||
|
goto badtype
|
||||||
}
|
}
|
||||||
case 'd':
|
case 'd':
|
||||||
if v, signed, ok := getInt(field); ok {
|
if v, signed, ok := getInt(field); ok {
|
||||||
@ -299,7 +348,7 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
s = p.fmt.ud64(uint64(v)).str()
|
s = p.fmt.ud64(uint64(v)).str()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s = "%d%"
|
goto badtype
|
||||||
}
|
}
|
||||||
case 'o':
|
case 'o':
|
||||||
if v, signed, ok := getInt(field); ok {
|
if v, signed, ok := getInt(field); ok {
|
||||||
@ -309,7 +358,7 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
s = p.fmt.uo64(uint64(v)).str()
|
s = p.fmt.uo64(uint64(v)).str()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s= "%o%"
|
goto badtype
|
||||||
}
|
}
|
||||||
case 'x':
|
case 'x':
|
||||||
if v, signed, ok := getInt(field); ok {
|
if v, signed, ok := getInt(field); ok {
|
||||||
@ -319,7 +368,7 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
s = p.fmt.ux64(uint64(v)).str()
|
s = p.fmt.ux64(uint64(v)).str()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s = "%x%"
|
goto badtype
|
||||||
}
|
}
|
||||||
|
|
||||||
// float
|
// float
|
||||||
@ -327,19 +376,19 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
if v, ok := getFloat(field); ok {
|
if v, ok := getFloat(field); ok {
|
||||||
s = p.fmt.e64(v).str()
|
s = p.fmt.e64(v).str()
|
||||||
} else {
|
} else {
|
||||||
s = "%e%"
|
goto badtype
|
||||||
}
|
}
|
||||||
case 'f':
|
case 'f':
|
||||||
if v, ok := getFloat(field); ok {
|
if v, ok := getFloat(field); ok {
|
||||||
s = p.fmt.f64(v).str()
|
s = p.fmt.f64(v).str()
|
||||||
} else {
|
} else {
|
||||||
s = "%f%";
|
goto badtype
|
||||||
}
|
}
|
||||||
case 'g':
|
case 'g':
|
||||||
if v, ok := getFloat(field); ok {
|
if v, ok := getFloat(field); ok {
|
||||||
s = p.fmt.g64(v).str()
|
s = p.fmt.g64(v).str()
|
||||||
} else {
|
} else {
|
||||||
s = "%g%"
|
goto badtype
|
||||||
}
|
}
|
||||||
|
|
||||||
// string
|
// string
|
||||||
@ -347,7 +396,7 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
if v, ok := getString(field); ok {
|
if v, ok := getString(field); ok {
|
||||||
s = p.fmt.s(v).str()
|
s = p.fmt.s(v).str()
|
||||||
} else {
|
} else {
|
||||||
s = "%s%"
|
goto badtype
|
||||||
}
|
}
|
||||||
|
|
||||||
// pointer
|
// pointer
|
||||||
@ -355,14 +404,25 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
|
|||||||
if v, ok := getPtr(field); ok {
|
if v, ok := getPtr(field); ok {
|
||||||
s = "0x" + p.fmt.uX64(v).str()
|
s = "0x" + p.fmt.uX64(v).str()
|
||||||
} else {
|
} else {
|
||||||
s = "%p%"
|
goto badtype
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
s = "?" + string(c) + "?";
|
badtype:
|
||||||
|
s = "%" + string(c) + "(" + field.Type().String() + ")%";
|
||||||
}
|
}
|
||||||
p.addstr(s);
|
p.addstr(s);
|
||||||
}
|
}
|
||||||
|
if fieldnum < v.Len() {
|
||||||
|
p.addstr("?(extra ");
|
||||||
|
for ; fieldnum < v.Len(); fieldnum++ {
|
||||||
|
p.addstr(v.Field(fieldnum).Type().String());
|
||||||
|
if fieldnum + 1 < v.Len() {
|
||||||
|
p.addstr(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.addstr(")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
|
func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
|
||||||
@ -404,7 +464,7 @@ func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
|
|||||||
p.doprint(field, true, false);
|
p.doprint(field, true, false);
|
||||||
p.add('}');
|
p.add('}');
|
||||||
default:
|
default:
|
||||||
s = "???";
|
s = "?" + field.Type().String() + "?";
|
||||||
}
|
}
|
||||||
p.addstr(s);
|
p.addstr(s);
|
||||||
prev_string = field.Kind() == reflect.StringKind;
|
prev_string = field.Kind() == reflect.StringKind;
|
||||||
|
Loading…
Reference in New Issue
Block a user