Commit 2d4f7ba0 authored by Rob Pike's avatar Rob Pike

printf as we know and love it.

Plus print[ln] with the ability to print struct values.

Note for language mavens: if a "..." function passes its argument
to another "..." function, the argument is not wrapped again.  This
allows printf to call fprintf without extra manipulation. It's good
but needs to go in the spec.

This code works:
///
package main

import fmt "fmt"
import os "os"

type T struct { s string; a, b int }

func main() {
	P := fmt.Printer();
	P.printf("%s = %d with float value %.4f\n", "hi there", 7, 123.456);
	P.println("hi there", 7, 123.456);
	P.fprintf(os.Stdout, "%s = %d with float value %.4f\n", "hi there", 7, 123.456);
	P.println(T{"x", 7, 234}, "end of struct", 8, 9);
}

R=rsc
DELTA=28  (7 added, 3 deleted, 18 changed)
OCL=18321
CL=18324
parent 178e37e7
...@@ -83,11 +83,11 @@ export type Writer interface { ...@@ -83,11 +83,11 @@ export type Writer interface {
} }
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 bool); func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool);
// These routines end in 'f' and take a format string. // These routines end in 'f' and take a format string.
func (p *P) fprintf(w Writer, format string, a reflect.Empty) (n int, error *os.Error) { func (p *P) fprintf(w Writer, format string, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue); v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p.doprintf(format, v); p.doprintf(format, v);
n, error = w.Write(p.buf[0:p.n]); n, error = w.Write(p.buf[0:p.n]);
...@@ -95,12 +95,12 @@ func (p *P) fprintf(w Writer, format string, a reflect.Empty) (n int, error *os. ...@@ -95,12 +95,12 @@ func (p *P) fprintf(w Writer, format string, a reflect.Empty) (n int, error *os.
return n, error; return n, error;
} }
func (p *P) printf(format string, v reflect.Empty) (n int, errno *os.Error) { func (p *P) printf(format string, v ...) (n int, errno *os.Error) {
n, errno = p.fprintf(os.Stdout, format, v); n, errno = p.fprintf(os.Stdout, format, v);
return n, errno; return n, errno;
} }
func (p *P) sprintf(format string, v reflect.Empty) string { func (p *P) sprintf(format string, v ...) string {
p.doprintf(format, reflect.NewValue(v).(reflect.StructValue)); p.doprintf(format, reflect.NewValue(v).(reflect.StructValue));
s := string(p.buf)[0 : p.n]; s := string(p.buf)[0 : p.n];
p.reset(); p.reset();
...@@ -110,21 +110,21 @@ func (p *P) sprintf(format string, v reflect.Empty) string { ...@@ -110,21 +110,21 @@ func (p *P) sprintf(format string, v reflect.Empty) string {
// These routines do not take a format string and add spaces only // These routines do not take a format string and add spaces only
// when the operand on neither side is a string. // when the operand on neither side is a string.
func (p *P) fprint(w Writer, a reflect.Empty) (n int, error *os.Error) { func (p *P) fprint(w Writer, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue); v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p.doprint(v, false); p.doprint(v, false, false);
n, error = w.Write(p.buf[0:p.n]); n, error = w.Write(p.buf[0:p.n]);
p.reset(); p.reset();
return n, error; return n, error;
} }
func (p *P) print(v reflect.Empty) (n int, errno *os.Error) { func (p *P) print(v ...) (n int, errno *os.Error) {
n, errno = p.fprint(os.Stdout, v); n, errno = p.fprint(os.Stdout, v);
return n, errno; return n, errno;
} }
func (p *P) sprint(v reflect.Empty) string { func (p *P) sprint(v ...) string {
p.doprint(reflect.NewValue(v).(reflect.StructValue), false); p.doprint(reflect.NewValue(v).(reflect.StructValue), false, false);
s := string(p.buf)[0 : p.n]; s := string(p.buf)[0 : p.n];
p.reset(); p.reset();
return s; return s;
...@@ -134,21 +134,21 @@ func (p *P) sprint(v reflect.Empty) string { ...@@ -134,21 +134,21 @@ func (p *P) sprint(v reflect.Empty) string {
// always add spaces between operands, and add a newline // always add spaces between operands, and add a newline
// after the last operand. // after the last operand.
func (p *P) fprintln(w Writer, a reflect.Empty) (n int, error *os.Error) { func (p *P) fprintln(w Writer, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue); v := reflect.NewValue(a).(reflect.PtrValue).Sub().(reflect.StructValue);
p.doprint(v, true); p.doprint(v, true, true);
n, error = w.Write(p.buf[0:p.n]); n, error = w.Write(p.buf[0:p.n]);
p.reset(); p.reset();
return n, error; return n, error;
} }
func (p *P) println(v reflect.Empty) (n int, errno *os.Error) { func (p *P) println(v ...) (n int, errno *os.Error) {
n, errno = p.fprintln(os.Stdout, v); n, errno = p.fprintln(os.Stdout, v);
return n, errno; return n, errno;
} }
func (p *P) sprintln(v reflect.Empty) string { func (p *P) sprintln(v ...) string {
p.doprint(reflect.NewValue(v).(reflect.StructValue), true); p.doprint(reflect.NewValue(v).(reflect.StructValue), true, true);
s := string(p.buf)[0 : p.n]; s := string(p.buf)[0 : p.n];
p.reset(); p.reset();
return s; return s;
...@@ -362,20 +362,20 @@ func (p *P) doprintf(format string, v reflect.StructValue) { ...@@ -362,20 +362,20 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
} }
} }
func (p *P) doprint(v reflect.StructValue, is_println bool) { func (p *P) doprint(v reflect.StructValue, addspace, addnewline bool) {
prev_string := false; prev_string := false;
for fieldnum := 0; fieldnum < v.Len(); fieldnum++ { for fieldnum := 0; fieldnum < v.Len(); fieldnum++ {
// always add spaces if we're doing println // always add spaces if we're doing println
field := v.Field(fieldnum); field := v.Field(fieldnum);
s := ""; s := "";
if is_println {
if fieldnum > 0 { if fieldnum > 0 {
if addspace {
p.add(' ') p.add(' ')
}
} else if field.Kind() != reflect.StringKind && !prev_string{ } else if field.Kind() != reflect.StringKind && !prev_string{
// if not doing println, add spaces if neither side is a string // if not doing println, add spaces if neither side is a string
p.add(' ') p.add(' ')
} }
}
switch field.Kind() { switch field.Kind() {
case reflect.BoolKind: case reflect.BoolKind:
s = p.fmt.boolean(field.(reflect.BoolValue).Get()).str(); s = p.fmt.boolean(field.(reflect.BoolValue).Get()).str();
...@@ -396,13 +396,17 @@ func (p *P) doprint(v reflect.StructValue, is_println bool) { ...@@ -396,13 +396,17 @@ func (p *P) doprint(v reflect.StructValue, is_println bool) {
p.add('0'); p.add('0');
p.add('x'); p.add('x');
s = p.fmt.uX64(v).str(); s = p.fmt.uX64(v).str();
case reflect.StructKind:
p.add('{');
p.doprint(field, true, false);
p.add('}');
default: default:
s = "???"; s = "???";
} }
p.addstr(s); p.addstr(s);
prev_string = field.Kind() == reflect.StringKind; prev_string = field.Kind() == reflect.StringKind;
} }
if is_println { if addnewline {
p.add('\n') p.add('\n')
} }
} }
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