No other functional changes.
Change-Id: If0d9e6208d53478e70d991b6926ea196b2cccf2e
Reviewed-on: https://go-review.googlesource.com/3672
Reviewed-by: Alan Donovan <adonovan@google.com>
return
}
-func (x *Int) String() string {
- switch {
- case x == nil:
- return "<nil>"
- case x.neg:
- return "-" + x.abs.decimalString()
- }
- return x.abs.decimalString()
-}
-
-func charset(ch rune) string {
- switch ch {
- case 'b':
- return lowercaseDigits[0:2]
- case 'o':
- return lowercaseDigits[0:8]
- case 'd', 's', 'v':
- return lowercaseDigits[0:10]
- case 'x':
- return lowercaseDigits[0:16]
- case 'X':
- return uppercaseDigits[0:16]
- }
- return "" // unknown format
-}
-
-// write count copies of text to s
-func writeMultiple(s fmt.State, text string, count int) {
- if len(text) > 0 {
- b := []byte(text)
- for ; count > 0; count-- {
- s.Write(b)
- }
- }
-}
-
-// Format is a support routine for fmt.Formatter. It accepts
-// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
-// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
-// Also supported are the full suite of package fmt's format
-// verbs for integral types, including '+', '-', and ' '
-// for sign control, '#' for leading zero in octal and for
-// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
-// respectively, specification of minimum digits precision,
-// output field width, space or zero padding, and left or
-// right justification.
-//
-func (x *Int) Format(s fmt.State, ch rune) {
- cs := charset(ch)
-
- // special cases
- switch {
- case cs == "":
- // unknown format
- fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
- return
- case x == nil:
- fmt.Fprint(s, "<nil>")
- return
- }
-
- // determine sign character
- sign := ""
- switch {
- case x.neg:
- sign = "-"
- case s.Flag('+'): // supersedes ' ' when both specified
- sign = "+"
- case s.Flag(' '):
- sign = " "
- }
-
- // determine prefix characters for indicating output base
- prefix := ""
- if s.Flag('#') {
- switch ch {
- case 'o': // octal
- prefix = "0"
- case 'x': // hexadecimal
- prefix = "0x"
- case 'X':
- prefix = "0X"
- }
- }
-
- // determine digits with base set by len(cs) and digit characters from cs
- digits := x.abs.string(cs)
-
- // number of characters for the three classes of number padding
- var left int // space characters to left of digits for right justification ("%8d")
- var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
- var right int // space characters to right of digits for left justification ("%-8d")
-
- // determine number padding from precision: the least number of digits to output
- precision, precisionSet := s.Precision()
- if precisionSet {
- switch {
- case len(digits) < precision:
- zeroes = precision - len(digits) // count of zero padding
- case digits == "0" && precision == 0:
- return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
- }
- }
-
- // determine field pad from width: the least number of characters to output
- length := len(sign) + len(prefix) + zeroes + len(digits)
- if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
- switch d := width - length; {
- case s.Flag('-'):
- // pad on the right with spaces; supersedes '0' when both specified
- right = d
- case s.Flag('0') && !precisionSet:
- // pad with zeroes unless precision also specified
- zeroes = d
- default:
- // pad on the left with spaces
- left = d
- }
- }
-
- // print number as [left pad][sign][prefix][zero pad][digits][right pad]
- writeMultiple(s, " ", left)
- writeMultiple(s, sign, 1)
- writeMultiple(s, prefix, 1)
- writeMultiple(s, "0", zeroes)
- writeMultiple(s, digits, 1)
- writeMultiple(s, " ", right)
-}
-
-// scan sets z to the integer value corresponding to the longest possible prefix
-// read from r representing a signed integer number in a given conversion base.
-// It returns z, the actual conversion base used, and an error, if any. In the
-// error case, the value of z is undefined but the returned value is nil. The
-// syntax follows the syntax of integer literals in Go.
-//
-// The base argument must be 0 or a value from 2 through MaxBase. If the base
-// is 0, the string prefix determines the actual conversion base. A prefix of
-// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
-// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
-//
-func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) {
- // determine sign
- neg, err := scanSign(r)
- if err != nil {
- return nil, 0, err
- }
-
- // determine mantissa
- z.abs, base, _, err = z.abs.scan(r, base, false)
- if err != nil {
- return nil, base, err
- }
- z.neg = len(z.abs) > 0 && neg // 0 has no sign
-
- return z, base, nil
-}
-
-func scanSign(r io.ByteScanner) (neg bool, err error) {
- var ch byte
- if ch, err = r.ReadByte(); err != nil {
- return false, err
- }
- switch ch {
- case '-':
- neg = true
- case '+':
- // nothing to do
- default:
- r.UnreadByte()
- }
- return
-}
-
-// byteReader is a local wrapper around fmt.ScanState;
-// it implements the ByteReader interface.
-type byteReader struct {
- fmt.ScanState
-}
-
-func (r byteReader) ReadByte() (byte, error) {
- ch, size, err := r.ReadRune()
- if size != 1 && err == nil {
- err = fmt.Errorf("invalid rune %#U", ch)
- }
- return byte(ch), err
-}
-
-func (r byteReader) UnreadByte() error {
- return r.UnreadRune()
-}
-
-// Scan is a support routine for fmt.Scanner; it sets z to the value of
-// 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 rune) error {
- s.SkipSpace() // skip leading space characters
- base := 0
- switch ch {
- case 'b':
- base = 2
- case 'o':
- base = 8
- case 'd':
- base = 10
- case 'x', 'X':
- base = 16
- case 's', 'v':
- // let scan determine the base
- default:
- return errors.New("Int.Scan: invalid verb")
- }
- _, _, err := z.scan(byteReader{s}, base)
- return err
-}
-
// low32 returns the least significant 32 bits of z.
func low32(z nat) uint32 {
if len(z) == 0 {
}
}
-var stringTests = []struct {
- in string
- out string
- base int
- val int64
- ok bool
-}{
- {in: "", ok: false},
- {in: "a", ok: false},
- {in: "z", ok: false},
- {in: "+", ok: false},
- {in: "-", ok: false},
- {in: "0b", ok: false},
- {in: "0x", ok: false},
- {in: "2", base: 2, ok: false},
- {in: "0b2", base: 0, ok: false},
- {in: "08", ok: false},
- {in: "8", base: 8, ok: false},
- {in: "0xg", base: 0, ok: false},
- {in: "g", base: 16, ok: false},
- {"0", "0", 0, 0, true},
- {"0", "0", 10, 0, true},
- {"0", "0", 16, 0, true},
- {"+0", "0", 0, 0, true},
- {"-0", "0", 0, 0, true},
- {"10", "10", 0, 10, true},
- {"10", "10", 10, 10, true},
- {"10", "10", 16, 16, true},
- {"-10", "-10", 16, -16, true},
- {"+10", "10", 16, 16, true},
- {"0x10", "16", 0, 16, true},
- {in: "0x10", base: 16, ok: false},
- {"-0x10", "-16", 0, -16, true},
- {"+0x10", "16", 0, 16, true},
- {"00", "0", 0, 0, true},
- {"0", "0", 8, 0, true},
- {"07", "7", 0, 7, true},
- {"7", "7", 8, 7, true},
- {"023", "19", 0, 19, true},
- {"23", "23", 8, 19, true},
- {"cafebabe", "cafebabe", 16, 0xcafebabe, true},
- {"0b0", "0", 0, 0, true},
- {"-111", "-111", 2, -7, true},
- {"-0b111", "-7", 0, -7, true},
- {"0b1001010111", "599", 0, 0x257, true},
- {"1001010111", "1001010111", 2, 0x257, true},
-}
-
-func format(base int) string {
- switch base {
- case 2:
- return "%b"
- case 8:
- return "%o"
- case 16:
- return "%x"
- }
- return "%d"
-}
-
-func TestGetString(t *testing.T) {
- z := new(Int)
- for i, test := range stringTests {
- if !test.ok {
- continue
- }
- z.SetInt64(test.val)
-
- if test.base == 10 {
- s := z.String()
- if s != test.out {
- t.Errorf("#%da got %s; want %s", i, s, test.out)
- }
- }
-
- s := fmt.Sprintf(format(test.base), z)
- if s != test.out {
- t.Errorf("#%db got %s; want %s", i, s, test.out)
- }
- }
-}
-
-func TestSetString(t *testing.T) {
- tmp := new(Int)
- for i, test := range stringTests {
- // initialize to a non-zero value so that issues with parsing
- // 0 are detected
- tmp.SetInt64(1234567890)
- n1, ok1 := new(Int).SetString(test.in, test.base)
- n2, ok2 := tmp.SetString(test.in, test.base)
- expected := NewInt(test.val)
- if ok1 != test.ok || ok2 != test.ok {
- t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
- continue
- }
- if !ok1 {
- if n1 != nil {
- t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
- }
- continue
- }
- if !ok2 {
- if n2 != nil {
- t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
- }
- continue
- }
-
- if ok1 && !isNormalized(n1) {
- t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
- }
- if ok2 && !isNormalized(n2) {
- t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
- }
-
- if n1.Cmp(expected) != 0 {
- t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
- }
- if n2.Cmp(expected) != 0 {
- t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
- }
- }
-}
-
-var formatTests = []struct {
- input string
- format string
- output string
-}{
- {"<nil>", "%x", "<nil>"},
- {"<nil>", "%#x", "<nil>"},
- {"<nil>", "%#y", "%!y(big.Int=<nil>)"},
-
- {"10", "%b", "1010"},
- {"10", "%o", "12"},
- {"10", "%d", "10"},
- {"10", "%v", "10"},
- {"10", "%x", "a"},
- {"10", "%X", "A"},
- {"-10", "%X", "-A"},
- {"10", "%y", "%!y(big.Int=10)"},
- {"-10", "%y", "%!y(big.Int=-10)"},
-
- {"10", "%#b", "1010"},
- {"10", "%#o", "012"},
- {"10", "%#d", "10"},
- {"10", "%#v", "10"},
- {"10", "%#x", "0xa"},
- {"10", "%#X", "0XA"},
- {"-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", "%3x", "-4d2"},
- {"-1234", "%4x", "-4d2"},
- {"-1234", "%5x", " -4d2"},
- {"-1234", "%-5x", "-4d2 "},
- {"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", "1234 "},
- {"-1234", "%-06d", "-1234 "},
-
- {"1234", "%.3d", "1234"},
- {"1234", "%.4d", "1234"},
- {"1234", "%.5d", "01234"},
- {"1234", "%.6d", "001234"},
- {"-1234", "%.3d", "-1234"},
- {"-1234", "%.4d", "-1234"},
- {"-1234", "%.5d", "-01234"},
- {"-1234", "%.6d", "-001234"},
-
- {"1234", "%8.3d", " 1234"},
- {"1234", "%8.4d", " 1234"},
- {"1234", "%8.5d", " 01234"},
- {"1234", "%8.6d", " 001234"},
- {"-1234", "%8.3d", " -1234"},
- {"-1234", "%8.4d", " -1234"},
- {"-1234", "%8.5d", " -01234"},
- {"-1234", "%8.6d", " -001234"},
-
- {"1234", "%+8.3d", " +1234"},
- {"1234", "%+8.4d", " +1234"},
- {"1234", "%+8.5d", " +01234"},
- {"1234", "%+8.6d", " +001234"},
- {"-1234", "%+8.3d", " -1234"},
- {"-1234", "%+8.4d", " -1234"},
- {"-1234", "%+8.5d", " -01234"},
- {"-1234", "%+8.6d", " -001234"},
-
- {"1234", "% 8.3d", " 1234"},
- {"1234", "% 8.4d", " 1234"},
- {"1234", "% 8.5d", " 01234"},
- {"1234", "% 8.6d", " 001234"},
- {"-1234", "% 8.3d", " -1234"},
- {"-1234", "% 8.4d", " -1234"},
- {"-1234", "% 8.5d", " -01234"},
- {"-1234", "% 8.6d", " -001234"},
-
- {"1234", "%.3x", "4d2"},
- {"1234", "%.4x", "04d2"},
- {"1234", "%.5x", "004d2"},
- {"1234", "%.6x", "0004d2"},
- {"-1234", "%.3x", "-4d2"},
- {"-1234", "%.4x", "-04d2"},
- {"-1234", "%.5x", "-004d2"},
- {"-1234", "%.6x", "-0004d2"},
-
- {"1234", "%8.3x", " 4d2"},
- {"1234", "%8.4x", " 04d2"},
- {"1234", "%8.5x", " 004d2"},
- {"1234", "%8.6x", " 0004d2"},
- {"-1234", "%8.3x", " -4d2"},
- {"-1234", "%8.4x", " -04d2"},
- {"-1234", "%8.5x", " -004d2"},
- {"-1234", "%8.6x", " -0004d2"},
-
- {"1234", "%+8.3x", " +4d2"},
- {"1234", "%+8.4x", " +04d2"},
- {"1234", "%+8.5x", " +004d2"},
- {"1234", "%+8.6x", " +0004d2"},
- {"-1234", "%+8.3x", " -4d2"},
- {"-1234", "%+8.4x", " -04d2"},
- {"-1234", "%+8.5x", " -004d2"},
- {"-1234", "%+8.6x", " -0004d2"},
-
- {"1234", "% 8.3x", " 4d2"},
- {"1234", "% 8.4x", " 04d2"},
- {"1234", "% 8.5x", " 004d2"},
- {"1234", "% 8.6x", " 0004d2"},
- {"1234", "% 8.7x", " 00004d2"},
- {"1234", "% 8.8x", " 000004d2"},
- {"-1234", "% 8.3x", " -4d2"},
- {"-1234", "% 8.4x", " -04d2"},
- {"-1234", "% 8.5x", " -004d2"},
- {"-1234", "% 8.6x", " -0004d2"},
- {"-1234", "% 8.7x", "-00004d2"},
- {"-1234", "% 8.8x", "-000004d2"},
-
- {"1234", "%-8.3d", "1234 "},
- {"1234", "%-8.4d", "1234 "},
- {"1234", "%-8.5d", "01234 "},
- {"1234", "%-8.6d", "001234 "},
- {"1234", "%-8.7d", "0001234 "},
- {"1234", "%-8.8d", "00001234"},
- {"-1234", "%-8.3d", "-1234 "},
- {"-1234", "%-8.4d", "-1234 "},
- {"-1234", "%-8.5d", "-01234 "},
- {"-1234", "%-8.6d", "-001234 "},
- {"-1234", "%-8.7d", "-0001234"},
- {"-1234", "%-8.8d", "-00001234"},
-
- {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
-
- {"0", "%.d", ""},
- {"0", "%.0d", ""},
- {"0", "%3.d", ""},
-}
-
-func TestFormat(t *testing.T) {
- for i, test := range formatTests {
- var x *Int
- if test.input != "<nil>" {
- var ok bool
- x, ok = new(Int).SetString(test.input, 0)
- if !ok {
- t.Errorf("#%d failed reading input %s", i, test.input)
- }
- }
- output := fmt.Sprintf(test.format, x)
- if output != test.output {
- t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
- }
- }
-}
-
-var scanTests = []struct {
- input string
- format string
- output string
- remaining int
-}{
- {"1010", "%b", "10", 0},
- {"0b1010", "%v", "10", 0},
- {"12", "%o", "10", 0},
- {"012", "%v", "10", 0},
- {"10", "%d", "10", 0},
- {"10", "%v", "10", 0},
- {"a", "%x", "10", 0},
- {"0xa", "%v", "10", 0},
- {"A", "%X", "10", 0},
- {"-A", "%X", "-10", 0},
- {"+0b1011001", "%v", "89", 0},
- {"0xA", "%v", "10", 0},
- {"0 ", "%v", "0", 1},
- {"2+3", "%v", "2", 2},
- {"0XABC 12", "%v", "2748", 3},
-}
-
-func TestScan(t *testing.T) {
- var buf bytes.Buffer
- for i, test := range scanTests {
- x := new(Int)
- buf.Reset()
- buf.WriteString(test.input)
- if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
- t.Errorf("#%d error: %s", i, err)
- }
- if x.String() != test.output {
- t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
- }
- if buf.Len() != test.remaining {
- t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
- }
- }
-}
-
// Examples from the Go Language Spec, section "Arithmetic operators"
var divisionSignsTests = []struct {
x, y int64
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements int-to-string conversion functions.
+
+package big
+
+import (
+ "errors"
+ "fmt"
+ "io"
+)
+
+func (x *Int) String() string {
+ switch {
+ case x == nil:
+ return "<nil>"
+ case x.neg:
+ return "-" + x.abs.decimalString()
+ }
+ return x.abs.decimalString()
+}
+
+func charset(ch rune) string {
+ switch ch {
+ case 'b':
+ return lowercaseDigits[0:2]
+ case 'o':
+ return lowercaseDigits[0:8]
+ case 'd', 's', 'v':
+ return lowercaseDigits[0:10]
+ case 'x':
+ return lowercaseDigits[0:16]
+ case 'X':
+ return uppercaseDigits[0:16]
+ }
+ return "" // unknown format
+}
+
+// write count copies of text to s
+func writeMultiple(s fmt.State, text string, count int) {
+ if len(text) > 0 {
+ b := []byte(text)
+ for ; count > 0; count-- {
+ s.Write(b)
+ }
+ }
+}
+
+// Format is a support routine for fmt.Formatter. It accepts
+// the formats 'b' (binary), 'o' (octal), 'd' (decimal), 'x'
+// (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
+// Also supported are the full suite of package fmt's format
+// verbs for integral types, including '+', '-', and ' '
+// for sign control, '#' for leading zero in octal and for
+// hexadecimal, a leading "0x" or "0X" for "%#x" and "%#X"
+// respectively, specification of minimum digits precision,
+// output field width, space or zero padding, and left or
+// right justification.
+//
+func (x *Int) Format(s fmt.State, ch rune) {
+ cs := charset(ch)
+
+ // special cases
+ switch {
+ case cs == "":
+ // unknown format
+ fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
+ return
+ case x == nil:
+ fmt.Fprint(s, "<nil>")
+ return
+ }
+
+ // determine sign character
+ sign := ""
+ switch {
+ case x.neg:
+ sign = "-"
+ case s.Flag('+'): // supersedes ' ' when both specified
+ sign = "+"
+ case s.Flag(' '):
+ sign = " "
+ }
+
+ // determine prefix characters for indicating output base
+ prefix := ""
+ if s.Flag('#') {
+ switch ch {
+ case 'o': // octal
+ prefix = "0"
+ case 'x': // hexadecimal
+ prefix = "0x"
+ case 'X':
+ prefix = "0X"
+ }
+ }
+
+ // determine digits with base set by len(cs) and digit characters from cs
+ digits := x.abs.string(cs)
+
+ // number of characters for the three classes of number padding
+ var left int // space characters to left of digits for right justification ("%8d")
+ var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
+ var right int // space characters to right of digits for left justification ("%-8d")
+
+ // determine number padding from precision: the least number of digits to output
+ precision, precisionSet := s.Precision()
+ if precisionSet {
+ switch {
+ case len(digits) < precision:
+ zeroes = precision - len(digits) // count of zero padding
+ case digits == "0" && precision == 0:
+ return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
+ }
+ }
+
+ // determine field pad from width: the least number of characters to output
+ length := len(sign) + len(prefix) + zeroes + len(digits)
+ if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
+ switch d := width - length; {
+ case s.Flag('-'):
+ // pad on the right with spaces; supersedes '0' when both specified
+ right = d
+ case s.Flag('0') && !precisionSet:
+ // pad with zeroes unless precision also specified
+ zeroes = d
+ default:
+ // pad on the left with spaces
+ left = d
+ }
+ }
+
+ // print number as [left pad][sign][prefix][zero pad][digits][right pad]
+ writeMultiple(s, " ", left)
+ writeMultiple(s, sign, 1)
+ writeMultiple(s, prefix, 1)
+ writeMultiple(s, "0", zeroes)
+ writeMultiple(s, digits, 1)
+ writeMultiple(s, " ", right)
+}
+
+// scan sets z to the integer value corresponding to the longest possible prefix
+// read from r representing a signed integer number in a given conversion base.
+// It returns z, the actual conversion base used, and an error, if any. In the
+// error case, the value of z is undefined but the returned value is nil. The
+// syntax follows the syntax of integer literals in Go.
+//
+// The base argument must be 0 or a value from 2 through MaxBase. If the base
+// is 0, the string prefix determines the actual conversion base. A prefix of
+// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
+// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
+//
+func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) {
+ // determine sign
+ neg, err := scanSign(r)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ // determine mantissa
+ z.abs, base, _, err = z.abs.scan(r, base, false)
+ if err != nil {
+ return nil, base, err
+ }
+ z.neg = len(z.abs) > 0 && neg // 0 has no sign
+
+ return z, base, nil
+}
+
+func scanSign(r io.ByteScanner) (neg bool, err error) {
+ var ch byte
+ if ch, err = r.ReadByte(); err != nil {
+ return false, err
+ }
+ switch ch {
+ case '-':
+ neg = true
+ case '+':
+ // nothing to do
+ default:
+ r.UnreadByte()
+ }
+ return
+}
+
+// byteReader is a local wrapper around fmt.ScanState;
+// it implements the ByteReader interface.
+type byteReader struct {
+ fmt.ScanState
+}
+
+func (r byteReader) ReadByte() (byte, error) {
+ ch, size, err := r.ReadRune()
+ if size != 1 && err == nil {
+ err = fmt.Errorf("invalid rune %#U", ch)
+ }
+ return byte(ch), err
+}
+
+func (r byteReader) UnreadByte() error {
+ return r.UnreadRune()
+}
+
+// Scan is a support routine for fmt.Scanner; it sets z to the value of
+// 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 rune) error {
+ s.SkipSpace() // skip leading space characters
+ base := 0
+ switch ch {
+ case 'b':
+ base = 2
+ case 'o':
+ base = 8
+ case 'd':
+ base = 10
+ case 'x', 'X':
+ base = 16
+ case 's', 'v':
+ // let scan determine the base
+ default:
+ return errors.New("Int.Scan: invalid verb")
+ }
+ _, _, err := z.scan(byteReader{s}, base)
+ return err
+}
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+var stringTests = []struct {
+ in string
+ out string
+ base int
+ val int64
+ ok bool
+}{
+ {in: "", ok: false},
+ {in: "a", ok: false},
+ {in: "z", ok: false},
+ {in: "+", ok: false},
+ {in: "-", ok: false},
+ {in: "0b", ok: false},
+ {in: "0x", ok: false},
+ {in: "2", base: 2, ok: false},
+ {in: "0b2", base: 0, ok: false},
+ {in: "08", ok: false},
+ {in: "8", base: 8, ok: false},
+ {in: "0xg", base: 0, ok: false},
+ {in: "g", base: 16, ok: false},
+ {"0", "0", 0, 0, true},
+ {"0", "0", 10, 0, true},
+ {"0", "0", 16, 0, true},
+ {"+0", "0", 0, 0, true},
+ {"-0", "0", 0, 0, true},
+ {"10", "10", 0, 10, true},
+ {"10", "10", 10, 10, true},
+ {"10", "10", 16, 16, true},
+ {"-10", "-10", 16, -16, true},
+ {"+10", "10", 16, 16, true},
+ {"0x10", "16", 0, 16, true},
+ {in: "0x10", base: 16, ok: false},
+ {"-0x10", "-16", 0, -16, true},
+ {"+0x10", "16", 0, 16, true},
+ {"00", "0", 0, 0, true},
+ {"0", "0", 8, 0, true},
+ {"07", "7", 0, 7, true},
+ {"7", "7", 8, 7, true},
+ {"023", "19", 0, 19, true},
+ {"23", "23", 8, 19, true},
+ {"cafebabe", "cafebabe", 16, 0xcafebabe, true},
+ {"0b0", "0", 0, 0, true},
+ {"-111", "-111", 2, -7, true},
+ {"-0b111", "-7", 0, -7, true},
+ {"0b1001010111", "599", 0, 0x257, true},
+ {"1001010111", "1001010111", 2, 0x257, true},
+}
+
+func format(base int) string {
+ switch base {
+ case 2:
+ return "%b"
+ case 8:
+ return "%o"
+ case 16:
+ return "%x"
+ }
+ return "%d"
+}
+
+func TestGetString(t *testing.T) {
+ z := new(Int)
+ for i, test := range stringTests {
+ if !test.ok {
+ continue
+ }
+ z.SetInt64(test.val)
+
+ if test.base == 10 {
+ s := z.String()
+ if s != test.out {
+ t.Errorf("#%da got %s; want %s", i, s, test.out)
+ }
+ }
+
+ s := fmt.Sprintf(format(test.base), z)
+ if s != test.out {
+ t.Errorf("#%db got %s; want %s", i, s, test.out)
+ }
+ }
+}
+
+func TestSetString(t *testing.T) {
+ tmp := new(Int)
+ for i, test := range stringTests {
+ // initialize to a non-zero value so that issues with parsing
+ // 0 are detected
+ tmp.SetInt64(1234567890)
+ n1, ok1 := new(Int).SetString(test.in, test.base)
+ n2, ok2 := tmp.SetString(test.in, test.base)
+ expected := NewInt(test.val)
+ if ok1 != test.ok || ok2 != test.ok {
+ t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
+ continue
+ }
+ if !ok1 {
+ if n1 != nil {
+ t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
+ }
+ continue
+ }
+ if !ok2 {
+ if n2 != nil {
+ t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
+ }
+ continue
+ }
+
+ if ok1 && !isNormalized(n1) {
+ t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
+ }
+ if ok2 && !isNormalized(n2) {
+ t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
+ }
+
+ if n1.Cmp(expected) != 0 {
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
+ }
+ if n2.Cmp(expected) != 0 {
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
+ }
+ }
+}
+
+var formatTests = []struct {
+ input string
+ format string
+ output string
+}{
+ {"<nil>", "%x", "<nil>"},
+ {"<nil>", "%#x", "<nil>"},
+ {"<nil>", "%#y", "%!y(big.Int=<nil>)"},
+
+ {"10", "%b", "1010"},
+ {"10", "%o", "12"},
+ {"10", "%d", "10"},
+ {"10", "%v", "10"},
+ {"10", "%x", "a"},
+ {"10", "%X", "A"},
+ {"-10", "%X", "-A"},
+ {"10", "%y", "%!y(big.Int=10)"},
+ {"-10", "%y", "%!y(big.Int=-10)"},
+
+ {"10", "%#b", "1010"},
+ {"10", "%#o", "012"},
+ {"10", "%#d", "10"},
+ {"10", "%#v", "10"},
+ {"10", "%#x", "0xa"},
+ {"10", "%#X", "0XA"},
+ {"-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", "%3x", "-4d2"},
+ {"-1234", "%4x", "-4d2"},
+ {"-1234", "%5x", " -4d2"},
+ {"-1234", "%-5x", "-4d2 "},
+ {"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", "1234 "},
+ {"-1234", "%-06d", "-1234 "},
+
+ {"1234", "%.3d", "1234"},
+ {"1234", "%.4d", "1234"},
+ {"1234", "%.5d", "01234"},
+ {"1234", "%.6d", "001234"},
+ {"-1234", "%.3d", "-1234"},
+ {"-1234", "%.4d", "-1234"},
+ {"-1234", "%.5d", "-01234"},
+ {"-1234", "%.6d", "-001234"},
+
+ {"1234", "%8.3d", " 1234"},
+ {"1234", "%8.4d", " 1234"},
+ {"1234", "%8.5d", " 01234"},
+ {"1234", "%8.6d", " 001234"},
+ {"-1234", "%8.3d", " -1234"},
+ {"-1234", "%8.4d", " -1234"},
+ {"-1234", "%8.5d", " -01234"},
+ {"-1234", "%8.6d", " -001234"},
+
+ {"1234", "%+8.3d", " +1234"},
+ {"1234", "%+8.4d", " +1234"},
+ {"1234", "%+8.5d", " +01234"},
+ {"1234", "%+8.6d", " +001234"},
+ {"-1234", "%+8.3d", " -1234"},
+ {"-1234", "%+8.4d", " -1234"},
+ {"-1234", "%+8.5d", " -01234"},
+ {"-1234", "%+8.6d", " -001234"},
+
+ {"1234", "% 8.3d", " 1234"},
+ {"1234", "% 8.4d", " 1234"},
+ {"1234", "% 8.5d", " 01234"},
+ {"1234", "% 8.6d", " 001234"},
+ {"-1234", "% 8.3d", " -1234"},
+ {"-1234", "% 8.4d", " -1234"},
+ {"-1234", "% 8.5d", " -01234"},
+ {"-1234", "% 8.6d", " -001234"},
+
+ {"1234", "%.3x", "4d2"},
+ {"1234", "%.4x", "04d2"},
+ {"1234", "%.5x", "004d2"},
+ {"1234", "%.6x", "0004d2"},
+ {"-1234", "%.3x", "-4d2"},
+ {"-1234", "%.4x", "-04d2"},
+ {"-1234", "%.5x", "-004d2"},
+ {"-1234", "%.6x", "-0004d2"},
+
+ {"1234", "%8.3x", " 4d2"},
+ {"1234", "%8.4x", " 04d2"},
+ {"1234", "%8.5x", " 004d2"},
+ {"1234", "%8.6x", " 0004d2"},
+ {"-1234", "%8.3x", " -4d2"},
+ {"-1234", "%8.4x", " -04d2"},
+ {"-1234", "%8.5x", " -004d2"},
+ {"-1234", "%8.6x", " -0004d2"},
+
+ {"1234", "%+8.3x", " +4d2"},
+ {"1234", "%+8.4x", " +04d2"},
+ {"1234", "%+8.5x", " +004d2"},
+ {"1234", "%+8.6x", " +0004d2"},
+ {"-1234", "%+8.3x", " -4d2"},
+ {"-1234", "%+8.4x", " -04d2"},
+ {"-1234", "%+8.5x", " -004d2"},
+ {"-1234", "%+8.6x", " -0004d2"},
+
+ {"1234", "% 8.3x", " 4d2"},
+ {"1234", "% 8.4x", " 04d2"},
+ {"1234", "% 8.5x", " 004d2"},
+ {"1234", "% 8.6x", " 0004d2"},
+ {"1234", "% 8.7x", " 00004d2"},
+ {"1234", "% 8.8x", " 000004d2"},
+ {"-1234", "% 8.3x", " -4d2"},
+ {"-1234", "% 8.4x", " -04d2"},
+ {"-1234", "% 8.5x", " -004d2"},
+ {"-1234", "% 8.6x", " -0004d2"},
+ {"-1234", "% 8.7x", "-00004d2"},
+ {"-1234", "% 8.8x", "-000004d2"},
+
+ {"1234", "%-8.3d", "1234 "},
+ {"1234", "%-8.4d", "1234 "},
+ {"1234", "%-8.5d", "01234 "},
+ {"1234", "%-8.6d", "001234 "},
+ {"1234", "%-8.7d", "0001234 "},
+ {"1234", "%-8.8d", "00001234"},
+ {"-1234", "%-8.3d", "-1234 "},
+ {"-1234", "%-8.4d", "-1234 "},
+ {"-1234", "%-8.5d", "-01234 "},
+ {"-1234", "%-8.6d", "-001234 "},
+ {"-1234", "%-8.7d", "-0001234"},
+ {"-1234", "%-8.8d", "-00001234"},
+
+ {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1
+
+ {"0", "%.d", ""},
+ {"0", "%.0d", ""},
+ {"0", "%3.d", ""},
+}
+
+func TestFormat(t *testing.T) {
+ for i, test := range formatTests {
+ var x *Int
+ if test.input != "<nil>" {
+ var ok bool
+ x, ok = new(Int).SetString(test.input, 0)
+ if !ok {
+ t.Errorf("#%d failed reading input %s", i, test.input)
+ }
+ }
+ output := fmt.Sprintf(test.format, x)
+ if output != test.output {
+ t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
+ }
+ }
+}
+
+var scanTests = []struct {
+ input string
+ format string
+ output string
+ remaining int
+}{
+ {"1010", "%b", "10", 0},
+ {"0b1010", "%v", "10", 0},
+ {"12", "%o", "10", 0},
+ {"012", "%v", "10", 0},
+ {"10", "%d", "10", 0},
+ {"10", "%v", "10", 0},
+ {"a", "%x", "10", 0},
+ {"0xa", "%v", "10", 0},
+ {"A", "%X", "10", 0},
+ {"-A", "%X", "-10", 0},
+ {"+0b1011001", "%v", "89", 0},
+ {"0xA", "%v", "10", 0},
+ {"0 ", "%v", "0", 1},
+ {"2+3", "%v", "2", 2},
+ {"0XABC 12", "%v", "2748", 3},
+}
+
+func TestScan(t *testing.T) {
+ var buf bytes.Buffer
+ for i, test := range scanTests {
+ x := new(Int)
+ buf.Reset()
+ buf.WriteString(test.input)
+ if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
+ t.Errorf("#%d error: %s", i, err)
+ }
+ if x.String() != test.output {
+ t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
+ }
+ if buf.Len() != test.remaining {
+ t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
+ }
+ }
+}