mirror of
https://github.com/golang/go
synced 2024-11-21 19:54:41 -07:00
fmt: Added SkipSpace() function to fmt's ScanState interface.
Users of the Scan() infrastructure that employ ReadRune() rather than Token() need a way to skip leading spaces and newlines as set by the the parent, Fscan(), Fscanln, or Fscanf(). As the internal methods and boolean flags are not exported, this new function was added here and in the Int and Nat Scan() functions of the big package. (fmt.Rat did not need change since it uses Token()) Also added Printf style format code support to int types and tests for same to int_test.go R=r, r, gri, mtj CC=golang-dev https://golang.org/cl/4634074
This commit is contained in:
parent
5d4eea6a2f
commit
d94e350f48
@ -368,11 +368,60 @@ func (x *Int) Format(s fmt.State, ch int) {
|
||||
format = "0X%s"
|
||||
}
|
||||
}
|
||||
if x.neg {
|
||||
format = "-" + format
|
||||
t := fmt.Sprintf(format, x.abs.string(cs))
|
||||
|
||||
// insert spaces in hexadecimal formats if needed
|
||||
if len(t) > 0 && s.Flag(' ') && (ch == 'x' || ch == 'X') {
|
||||
spaces := (len(t)+1)/2 - 1
|
||||
spaced := make([]byte, len(t)+spaces)
|
||||
var i, j int
|
||||
spaced[i] = t[j]
|
||||
i++
|
||||
j++
|
||||
if len(t)&1 == 0 {
|
||||
spaced[i] = t[j]
|
||||
i++
|
||||
j++
|
||||
}
|
||||
for j < len(t) {
|
||||
spaced[i] = ' '
|
||||
i++
|
||||
spaced[i] = t[j]
|
||||
i++
|
||||
j++
|
||||
spaced[i] = t[j]
|
||||
i++
|
||||
j++
|
||||
}
|
||||
t = string(spaced)
|
||||
}
|
||||
|
||||
fmt.Fprintf(s, format, x.abs.string(cs))
|
||||
// determine sign prefix
|
||||
prefix := ""
|
||||
switch {
|
||||
case x.neg:
|
||||
prefix = "-"
|
||||
case s.Flag('+'):
|
||||
prefix = "+"
|
||||
case s.Flag(' ') && ch != 'x' && ch != 'X':
|
||||
prefix = " "
|
||||
}
|
||||
|
||||
// fill to minimum width and prepend sign prefix
|
||||
if width, ok := s.Width(); ok && len(t)+len(prefix) < width {
|
||||
if s.Flag('0') {
|
||||
t = fmt.Sprintf("%s%0*d%s", prefix, width-len(t)-len(prefix), 0, t)
|
||||
} else {
|
||||
if s.Flag('-') {
|
||||
width = -width
|
||||
}
|
||||
t = fmt.Sprintf("%*s", width, prefix+t)
|
||||
}
|
||||
} else if prefix != "" {
|
||||
t = prefix + t
|
||||
}
|
||||
|
||||
fmt.Fprint(s, t)
|
||||
}
|
||||
|
||||
|
||||
@ -417,6 +466,7 @@ func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, os.Error) {
|
||||
// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
|
||||
// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
|
||||
func (z *Int) Scan(s fmt.ScanState, ch int) os.Error {
|
||||
s.SkipSpace() // skip leading space characters
|
||||
base := 0
|
||||
switch ch {
|
||||
case 'b':
|
||||
@ -585,7 +635,7 @@ func ProbablyPrime(z *Int, n int) bool {
|
||||
}
|
||||
|
||||
|
||||
// Rand sets z to a pseudo-random number in [0, n) and returns z.
|
||||
// Rand sets z to a pseudo-random number in [0, n) and returns z.
|
||||
func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
|
||||
z.neg = false
|
||||
if n.neg == true || len(n.abs) == 0 {
|
||||
|
@ -376,6 +376,35 @@ var formatTests = []struct {
|
||||
{"-10", "%#X", "-0XA"},
|
||||
{"10", "%#y", "%!y(big.Int=10)"},
|
||||
{"-10", "%#y", "%!y(big.Int=-10)"},
|
||||
|
||||
{"1234", "%d", "1234"},
|
||||
{"1234", "%3d", "1234"},
|
||||
{"1234", "%4d", "1234"},
|
||||
{"-1234", "%d", "-1234"},
|
||||
{"1234", "% 5d", " 1234"},
|
||||
{"1234", "%+5d", "+1234"},
|
||||
{"1234", "%-5d", "1234 "},
|
||||
{"1234", "%x", "4d2"},
|
||||
{"1234", "%X", "4D2"},
|
||||
{"1234", "% x", "4 d2"},
|
||||
{"-1234", "%3x", "-4d2"},
|
||||
{"-1234", "%4x", "-4d2"},
|
||||
{"-1234", "%5x", " -4d2"},
|
||||
{"-1234", "%-5x", "-4d2 "},
|
||||
{"-1234", "% x", "-4 d2"},
|
||||
{"1234", "%03d", "1234"},
|
||||
{"1234", "%04d", "1234"},
|
||||
{"1234", "%05d", "01234"},
|
||||
{"1234", "%06d", "001234"},
|
||||
{"-1234", "%06d", "-01234"},
|
||||
{"1234", "%+06d", "+01234"},
|
||||
{"1234", "% 06d", " 01234"},
|
||||
{"1234", "%-6d", "1234 "},
|
||||
{"1234", "%-06d", "001234"},
|
||||
{"-1234", "%-06d", "-01234"},
|
||||
{"10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", // 10**100
|
||||
"% x",
|
||||
"12 49 ad 25 94 c3 7c eb 0b 27 84 c4 ce 0b f3 8a ce 40 8e 21 1a 7c aa b2 43 08 a8 2e 8f 10 00 00 00 00 00 00 00 00 00 00 00 00"},
|
||||
}
|
||||
|
||||
|
||||
@ -391,7 +420,7 @@ func TestFormat(t *testing.T) {
|
||||
}
|
||||
output := fmt.Sprintf(test.format, x)
|
||||
if output != test.output {
|
||||
t.Errorf("#%d got %s; want %s", i, output, test.output)
|
||||
t.Errorf("#%d got %q; want %q", i, output, test.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,10 @@ type ScanState interface {
|
||||
ReadRune() (rune int, size int, err os.Error)
|
||||
// UnreadRune causes the next call to ReadRune to return the same rune.
|
||||
UnreadRune() os.Error
|
||||
// SkipSpace skips space in the input. Newlines are treated as space
|
||||
// unless the scan operation is Scanln, Fscanln or Sscanln, in which case
|
||||
// a newline is treated as EOF.
|
||||
SkipSpace()
|
||||
// Token skips space in the input if skipSpace is true, then returns the
|
||||
// run of Unicode code points c satisfying f(c). If f is nil,
|
||||
// !unicode.IsSpace(c) is used; that is, the token will hold non-space
|
||||
@ -267,6 +271,14 @@ func notSpace(r int) bool {
|
||||
return !unicode.IsSpace(r)
|
||||
}
|
||||
|
||||
|
||||
// skipSpace provides Scan() methods the ability to skip space and newline characters
|
||||
// in keeping with the current scanning mode set by format strings and Scan()/Scanln().
|
||||
func (s *ss) SkipSpace() {
|
||||
s.skipSpace(false)
|
||||
}
|
||||
|
||||
|
||||
// readRune is a structure to enable reading UTF-8 encoded code points
|
||||
// from an io.Reader. It is used if the Reader given to the scanner does
|
||||
// not already implement io.RuneReader.
|
||||
|
Loading…
Reference in New Issue
Block a user