]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: Added SkipSpace() function to fmt's ScanState interface.
authorMichael T. Jones <mtj@google.com>
Sat, 25 Jun 2011 00:26:45 +0000 (17:26 -0700)
committerRobert Griesemer <gri@golang.org>
Sat, 25 Jun 2011 00:26:45 +0000 (17:26 -0700)
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

src/pkg/big/int.go
src/pkg/big/int_test.go
src/pkg/fmt/scan.go

index 4d47a82d5fcd749d564d599a01c8ad8344451c8c..0948919cdad76bcb73c231f6562e4cfb77d67fdc 100755 (executable)
@@ -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)
+       }
+
+       // 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.Fprintf(s, format, x.abs.string(cs))
+       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 {
index 58a55030d5345b1ecc449a72f3046edf9a133820..7f33c9522aa2dcb65be12e7c33f755b1aeac40f3 100755 (executable)
@@ -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)
                }
        }
 }
index f48fcbb4488b034d7d2edf2da4db27408496140a..d93a8c1da5c25ba462b7be45b1b51b6e4a5f732c 100644 (file)
@@ -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.