// The base argument must be 0 or a value from 2 through 36. 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) SetString(s string, base int) (*Int, bool) { z.doinit() if base < 0 || base == 1 || base > 36 { return nil, false } // no need to call mpz_set_str here. if len(s) == 0 { return nil, false } // positive signs should be ignored if s[0] == '+' { s = s[1:] } // attempting to set "0x" and "0b" should return nil like math/big if len(s) == 2 { switch s { case "0x", "0X", "0b", "0B": return nil, false } } p := C.CString(s) defer C.free(unsafe.Pointer(p)) if C.mpz_set_str(z.ptr, p, C.int(base)) < 0 { return nil, false } return z, true }
// SetString interprets s as a number in the given base // and sets z to that value. The base must be in the range [2,36]. // SetString returns an error if s cannot be parsed or the base is invalid. func (z *Int) SetString(s string, base int) os.Error { z.doinit() if base < 2 || base > 36 { return os.EINVAL } p := C.CString(s) defer C.free(unsafe.Pointer(p)) if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 { return os.EINVAL } return z }
// SetString sets z to the value of s, interpreted in the given base, // and returns z and a boolean indicating success. If SetString fails, // the value of z is undefined but the returned value is nil. // // 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) SetString(s string, base int) (*Int, bool) { z.doinit() if base != 0 && (base < 2 || base > 36) { return nil, false } // Skip leading + as mpz_set_str doesn't understand them if len(s) > 1 && s[0] == '+' { s = s[1:] } // mpz_set_str incorrectly parses "0x" and "0b" as valid if base == 0 && len(s) == 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X' || s[1] == 'b' || s[1] == 'B') { return nil, false } p := C.CString(s) defer C.free(unsafe.Pointer(p)) if C.mpz_set_str(&z.i[0], p, C.int(base)) < 0 { return nil, false } return z, true // err == io.EOF => scan consumed all of s }
// 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 case 'z': base = 60 default: return errors.New("Int.Scan: invalid verb") } charset := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz." if base != 0 { charset = charset[:base] } // Read the number into in in := make([]byte, 0, 16) var err error var n int for { ch, n, err = s.ReadRune() if err == io.EOF { break } if err != nil { return err } if n > 1 { // Wide character - must be the end s.UnreadRune() break } if len(in) == 0 { if ch == '+' { // Skip leading + as gmp doesn't understand them continue } if ch == '-' { goto ok } } if len(in) == 1 && base == 0 { if ch == 'b' || ch == 'x' { goto ok } } if !strings.ContainsRune(charset, ch) { // Bad character - end s.UnreadRune() break } ok: in = append(in, byte(ch)) } // Use GMP to convert it as it is very efficient for large numbers z.doinit() // null terminate for C in = append(in, 0) if C.mpz_set_str(&z.i[0], (*C.char)(unsafe.Pointer(&in[0])), C.int(base)) < 0 { return errors.New("Int.Scan: failed") } return nil }