diff --git a/src/pkg/big/int.go b/src/pkg/big/int.go index 4d47a82d5fc..0948919cdad 100755 --- a/src/pkg/big/int.go +++ b/src/pkg/big/int.go @@ -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 { diff --git a/src/pkg/big/int_test.go b/src/pkg/big/int_test.go index 58a55030d53..7f33c9522aa 100755 --- a/src/pkg/big/int_test.go +++ b/src/pkg/big/int_test.go @@ -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) } } } diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go index f48fcbb4488..d93a8c1da5c 100644 --- a/src/pkg/fmt/scan.go +++ b/src/pkg/fmt/scan.go @@ -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.