mirror of
https://github.com/golang/go
synced 2024-10-01 01:08:33 -06:00
math/big: Rat.SetString to report error if input is not consumed entirely
Also, document behavior explicitly for all SetString implementations. Fixes #17001. Change-Id: Iccc882b4bc7f8b61b6092f330e405c146a80dc98 Reviewed-on: https://go-review.googlesource.com/30472 Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
4103fedf19
commit
95a6572b2b
@ -14,7 +14,9 @@ import (
|
|||||||
|
|
||||||
// SetString sets z to the value of s and returns z and a boolean indicating
|
// SetString sets z to the value of s and returns z and a boolean indicating
|
||||||
// success. s must be a floating-point number of the same format as accepted
|
// success. s must be a floating-point number of the same format as accepted
|
||||||
// by Parse, with base argument 0.
|
// by Parse, with base argument 0. The entire string (not just a prefix) must
|
||||||
|
// be valid for success. If the operation failed, the value of z is undefined
|
||||||
|
// but the returned value is nil.
|
||||||
func (z *Float) SetString(s string) (*Float, bool) {
|
func (z *Float) SetString(s string) (*Float, bool) {
|
||||||
if f, _, err := z.Parse(s, 0); err == nil {
|
if f, _, err := z.Parse(s, 0); err == nil {
|
||||||
return f, true
|
return f, true
|
||||||
@ -212,6 +214,7 @@ func (z *Float) pow5(n uint64) *Float {
|
|||||||
//
|
//
|
||||||
// It sets z to the (possibly rounded) value of the corresponding floating-
|
// It sets z to the (possibly rounded) value of the corresponding floating-
|
||||||
// point value, and returns z, the actual base b, and an error err, if any.
|
// point value, and returns z, the actual base b, and an error err, if any.
|
||||||
|
// The entire string (not just a prefix) must be consumed for success.
|
||||||
// If z's precision is 0, it is changed to 64 before rounding takes effect.
|
// If z's precision is 0, it is changed to 64 before rounding takes effect.
|
||||||
// The number must be of the form:
|
// The number must be of the form:
|
||||||
//
|
//
|
||||||
|
@ -361,7 +361,8 @@ func (x *Int) Uint64() uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetString sets z to the value of s, interpreted in the given base,
|
// SetString sets z to the value of s, interpreted in the given base,
|
||||||
// and returns z and a boolean indicating success. If SetString fails,
|
// and returns z and a boolean indicating success. The entire string
|
||||||
|
// (not just a prefix) must be valid for success. If SetString fails,
|
||||||
// the value of z is undefined but the returned value is nil.
|
// the value of z is undefined but the returned value is nil.
|
||||||
//
|
//
|
||||||
// The base argument must be 0 or a value between 2 and MaxBase. If the base
|
// The base argument must be 0 or a value between 2 and MaxBase. If the base
|
||||||
@ -371,12 +372,11 @@ func (x *Int) Uint64() uint64 {
|
|||||||
//
|
//
|
||||||
func (z *Int) SetString(s string, base int) (*Int, bool) {
|
func (z *Int) SetString(s string, base int) (*Int, bool) {
|
||||||
r := strings.NewReader(s)
|
r := strings.NewReader(s)
|
||||||
_, _, err := z.scan(r, base)
|
if _, _, err := z.scan(r, base); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
_, err = r.ReadByte()
|
// entire string must have been consumed
|
||||||
if err != io.EOF {
|
if _, err := r.ReadByte(); err != io.EOF {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return z, true // err == io.EOF => scan consumed all of s
|
return z, true // err == io.EOF => scan consumed all of s
|
||||||
|
@ -36,8 +36,9 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
|
|||||||
|
|
||||||
// SetString sets z to the value of s and returns z and a boolean indicating
|
// SetString sets z to the value of s and returns z and a boolean indicating
|
||||||
// success. s can be given as a fraction "a/b" or as a floating-point number
|
// success. s can be given as a fraction "a/b" or as a floating-point number
|
||||||
// optionally followed by an exponent. If the operation failed, the value of
|
// optionally followed by an exponent. The entire string (not just a prefix)
|
||||||
// z is undefined but the returned value is nil.
|
// must be valid for success. If the operation failed, the value of z is un-
|
||||||
|
// defined but the returned value is nil.
|
||||||
func (z *Rat) SetString(s string) (*Rat, bool) {
|
func (z *Rat) SetString(s string) (*Rat, bool) {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -49,9 +50,13 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
|
|||||||
if _, ok := z.a.SetString(s[:sep], 0); !ok {
|
if _, ok := z.a.SetString(s[:sep], 0); !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
s = s[sep+1:]
|
r := strings.NewReader(s[sep+1:])
|
||||||
var err error
|
var err error
|
||||||
if z.b.abs, _, _, err = z.b.abs.scan(strings.NewReader(s), 0, false); err != nil {
|
if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
// entire string must have been consumed
|
||||||
|
if _, err = r.ReadByte(); err != io.EOF {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
if len(z.b.abs) == 0 {
|
if len(z.b.abs) == 0 {
|
||||||
|
@ -50,6 +50,10 @@ var setStringTests = []StringTest{
|
|||||||
{"204211327800791583.81095", "4084226556015831676219/20000", true},
|
{"204211327800791583.81095", "4084226556015831676219/20000", true},
|
||||||
{"0e9999999999", "0", true}, // issue #16176
|
{"0e9999999999", "0", true}, // issue #16176
|
||||||
{in: "1/0"},
|
{in: "1/0"},
|
||||||
|
{in: "4/3/2"}, // issue 17001
|
||||||
|
{in: "4/3/"},
|
||||||
|
{in: "4/3."},
|
||||||
|
{in: "4/"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are not supported by fmt.Fscanf.
|
// These are not supported by fmt.Fscanf.
|
||||||
@ -59,6 +63,7 @@ var setStringTests2 = []StringTest{
|
|||||||
{"-010.", "-10", true},
|
{"-010.", "-10", true},
|
||||||
{"0x10/0x20", "1/2", true},
|
{"0x10/0x20", "1/2", true},
|
||||||
{"0b1000/3", "8/3", true},
|
{"0b1000/3", "8/3", true},
|
||||||
|
{in: "4/3x"},
|
||||||
// TODO(gri) add more tests
|
// TODO(gri) add more tests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user