Пример #1
0
// 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
}
Пример #2
0
// 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
}
Пример #3
0
Файл: int.go Проект: locusf/gmp
// 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
}
Пример #4
0
Файл: int.go Проект: locusf/gmp
// 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
}