Commit 85647c94 authored by Rob Pike's avatar Rob Pike

document fmt.

the description of the format verbs still needs to be done.

R=rsc
DELTA=288  (88 added, 12 deleted, 188 changed)
OCL=25814
CL=25833
parent b18e4184
This diff is collapsed.
...@@ -2,12 +2,21 @@ ...@@ -2,12 +2,21 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package fmt implements formatted I/O with functions analogous
// to C's printf. Because of reflection knowledge it does not need
// to be told about sizes and signedness (no %llud etc. - just %d).
// Still to do: document the formats properly. For now, like C but:
// - don't need l or u flags - type of integer tells that.
// - %v prints any value using its native format.
// - for each Printf-like fn, there is also a Print fn that takes no format
// and is equivalent to saying %v for every operand.
// - another variant Println inserts blanks and appends a newline.
// - if an operand implements method String() that method will
// be used for %v, %s, or Print etc.
// - if an operand implements interface Formatter, that interface can
// be used for fine control of formatting.
package fmt package fmt
/*
C-like printf, but because of reflection knowledge does not need
to be told about sizes and signedness (no %llud etc. - just %d).
*/
import ( import (
"fmt"; "fmt";
...@@ -17,27 +26,37 @@ import ( ...@@ -17,27 +26,37 @@ import (
"utf8"; "utf8";
) )
// Representation of printer state passed to custom formatters. // Formatter represents the printer state passed to custom formatters.
// Provides access to the io.Write interface plus information about // It provides access to the io.Write interface plus information about
// the active formatting verb. // the flags and options for the operand's format specifier.
type Formatter interface { type Formatter interface {
// Write is the function to call to emit formatted output to be printed.
Write(b []byte) (ret int, err *os.Error); Write(b []byte) (ret int, err *os.Error);
// Width returns the value of the width option and whether it has been set.
Width() (wid int, ok bool); Width() (wid int, ok bool);
// Precision returns the value of the precision option and whether it has been set.
Precision() (prec int, ok bool); Precision() (prec int, ok bool);
// flags // Flag returns whether the flag c, a character, has been set.
Flag(int) bool; Flag(int) bool;
} }
// Format is the interface implemented by objects with a custom formatter.
// The implementation of Format may call Sprintf or Fprintf(f) etc.
// to generate its output.
type Format interface { type Format interface {
Format(f Formatter, c int); Format(f Formatter, c int);
} }
// String represents any object being printed that has a String() method that
// returns a string, which defines the ``native'' format for that object.
// Any such object will be printed using that method if passed
// as operand to a %s or %v format or to an unformatted printer such as Print.
type String interface { type String interface {
String() string String() string
} }
const runeSelf = 0x80 const runeSelf = utf8.RuneSelf
const allocSize = 32 const allocSize = 32
type pp struct { type pp struct {
...@@ -129,6 +148,7 @@ func (p *pp) doprint(v reflect.StructValue, addspace, addnewline bool); ...@@ -129,6 +148,7 @@ func (p *pp) 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.
// Fprintf formats according to a format specifier and writes to w.
func Fprintf(w io.Write, format string, a ...) (n int, error *os.Error) { func Fprintf(w io.Write, format string, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.StructValue); v := reflect.NewValue(a).(reflect.StructValue);
p := newPrinter(); p := newPrinter();
...@@ -137,11 +157,13 @@ func Fprintf(w io.Write, format string, a ...) (n int, error *os.Error) { ...@@ -137,11 +157,13 @@ func Fprintf(w io.Write, format string, a ...) (n int, error *os.Error) {
return n, error; return n, error;
} }
// Printf formats according to a format specifier and writes to standard output.
func Printf(format string, v ...) (n int, errno *os.Error) { func Printf(format string, v ...) (n int, errno *os.Error) {
n, errno = Fprintf(os.Stdout, format, v); n, errno = Fprintf(os.Stdout, format, v);
return n, errno; return n, errno;
} }
// Sprintf formats according to a format specifier and returns the resulting string.
func Sprintf(format string, a ...) string { func Sprintf(format string, a ...) string {
v := reflect.NewValue(a).(reflect.StructValue); v := reflect.NewValue(a).(reflect.StructValue);
p := newPrinter(); p := newPrinter();
...@@ -150,9 +172,10 @@ func Sprintf(format string, a ...) string { ...@@ -150,9 +172,10 @@ func Sprintf(format string, a ...) string {
return s; return s;
} }
// These routines do not take a format string and add spaces only // These routines do not take a format string
// when the operand on neither side is a string.
// Fprint formats using the default formats for its operands and writes to w.
// Spaces are added between operands when neither is a string.
func Fprint(w io.Write, a ...) (n int, error *os.Error) { func Fprint(w io.Write, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.StructValue); v := reflect.NewValue(a).(reflect.StructValue);
p := newPrinter(); p := newPrinter();
...@@ -161,11 +184,15 @@ func Fprint(w io.Write, a ...) (n int, error *os.Error) { ...@@ -161,11 +184,15 @@ func Fprint(w io.Write, a ...) (n int, error *os.Error) {
return n, error; return n, error;
} }
// Print formats using the default formats for its operands and writes to standard output.
// Spaces are added between operands when neither is a string.
func Print(v ...) (n int, errno *os.Error) { func Print(v ...) (n int, errno *os.Error) {
n, errno = Fprint(os.Stdout, v); n, errno = Fprint(os.Stdout, v);
return n, errno; return n, errno;
} }
// Sprint formats using the default formats for its operands and returns the resulting string.
// Spaces are added between operands when neither is a string.
func Sprint(a ...) string { func Sprint(a ...) string {
v := reflect.NewValue(a).(reflect.StructValue); v := reflect.NewValue(a).(reflect.StructValue);
p := newPrinter(); p := newPrinter();
...@@ -178,6 +205,8 @@ func Sprint(a ...) string { ...@@ -178,6 +205,8 @@ func Sprint(a ...) 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.
// Fprintln formats using the default formats for its operands and writes to w.
// Spaces are always added between operands and a newline is appended.
func Fprintln(w io.Write, a ...) (n int, error *os.Error) { func Fprintln(w io.Write, a ...) (n int, error *os.Error) {
v := reflect.NewValue(a).(reflect.StructValue); v := reflect.NewValue(a).(reflect.StructValue);
p := newPrinter(); p := newPrinter();
...@@ -186,11 +215,15 @@ func Fprintln(w io.Write, a ...) (n int, error *os.Error) { ...@@ -186,11 +215,15 @@ func Fprintln(w io.Write, a ...) (n int, error *os.Error) {
return n, error; return n, error;
} }
// Println formats using the default formats for its operands and writes to standard output.
// Spaces are always added between operands and a newline is appended.
func Println(v ...) (n int, errno *os.Error) { func Println(v ...) (n int, errno *os.Error) {
n, errno = Fprintln(os.Stdout, v); n, errno = Fprintln(os.Stdout, v);
return n, errno; return n, errno;
} }
// Sprintln formats using the default formats for its operands and returns the resulting string.
// Spaces are always added between operands and a newline is appended.
func Sprintln(a ...) string { func Sprintln(a ...) string {
v := reflect.NewValue(a).(reflect.StructValue); v := reflect.NewValue(a).(reflect.StructValue);
p := newPrinter(); p := newPrinter();
...@@ -596,6 +629,13 @@ func (p *pp) doprintf(format string, v reflect.StructValue) { ...@@ -596,6 +629,13 @@ func (p *pp) doprintf(format string, v reflect.StructValue) {
// string // string
case 's': case 's':
if inter != nil {
// if object implements String, use the result.
if stringer, ok := inter.(String); ok {
s = p.fmt.Fmt_s(stringer.String()).Str();
break;
}
}
if v, ok := getString(field); ok { if v, ok := getString(field); ok {
s = p.fmt.Fmt_s(v).Str() s = p.fmt.Fmt_s(v).Str()
} else { } else {
......
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