1
0
mirror of https://github.com/golang/go synced 2024-11-20 07:44:41 -07:00

math/big: remove []byte/string conversions

This removes some of the []byte/string conversions currently
existing in the (un)marshaling methods of Int and Rat.

For Int we introduce a new function (*Int).setFromScanner() essentially
implementing the SetString method being given an io.ByteScanner instead
of a string. So we can handle the string case in (*Int).SetString with
a *strings.Reader and the []byte case in (*Int).UnmarshalText() with a
*bytes.Reader now avoiding the []byte/string conversion here.

For Rat we introduce a new function (*Rat).marshal() essentially
implementing the String method outputting []byte instead of string.
Using this new function and the same formatting rules as in
(*Rat).RatString we can implement (*Rat).MarshalText() without
the []byte/string conversion it used to have.

Change-Id: Ic5ef246c1582c428a40f214b95a16671ef0a06d9
Reviewed-on: https://go-review.googlesource.com/65950
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Marvin Stenger 2017-09-21 18:48:12 +02:00 committed by Robert Griesemer
parent 3a35e0253c
commit aa00c607e1
4 changed files with 23 additions and 9 deletions

View File

@ -390,15 +390,20 @@ func (x *Int) IsUint64() bool {
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. // ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
// //
func (z *Int) SetString(s string, base int) (*Int, bool) { func (z *Int) SetString(s string, base int) (*Int, bool) {
r := strings.NewReader(s) return z.setFromScanner(strings.NewReader(s), base)
}
// setFromScanner implements SetString given an io.BytesScanner.
// For documentation see comments of SetString.
func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) {
if _, _, err := z.scan(r, base); err != nil { if _, _, err := z.scan(r, base); err != nil {
return nil, false return nil, false
} }
// entire string must have been consumed // entire content must have been consumed
if _, err := r.ReadByte(); 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 content of r
} }
// SetBytes interprets buf as the bytes of a big-endian unsigned // SetBytes interprets buf as the bytes of a big-endian unsigned

View File

@ -6,7 +6,10 @@
package big package big
import "fmt" import (
"bytes"
"fmt"
)
// Gob codec version. Permits backward-compatible changes to the encoding. // Gob codec version. Permits backward-compatible changes to the encoding.
const intGobVersion byte = 1 const intGobVersion byte = 1
@ -52,8 +55,7 @@ func (x *Int) MarshalText() (text []byte, err error) {
// UnmarshalText implements the encoding.TextUnmarshaler interface. // UnmarshalText implements the encoding.TextUnmarshaler interface.
func (z *Int) UnmarshalText(text []byte) error { func (z *Int) UnmarshalText(text []byte) error {
// TODO(gri): get rid of the []byte/string conversion if _, ok := z.setFromScanner(bytes.NewReader(text), 0); !ok {
if _, ok := z.SetString(string(text), 0); !ok {
return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text) return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
} }
return nil return nil

View File

@ -202,6 +202,11 @@ func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err err
// String returns a string representation of x in the form "a/b" (even if b == 1). // String returns a string representation of x in the form "a/b" (even if b == 1).
func (x *Rat) String() string { func (x *Rat) String() string {
return string(x.marshal())
}
// marshal implements String returning a slice of bytes
func (x *Rat) marshal() []byte {
var buf []byte var buf []byte
buf = x.a.Append(buf, 10) buf = x.a.Append(buf, 10)
buf = append(buf, '/') buf = append(buf, '/')
@ -210,7 +215,7 @@ func (x *Rat) String() string {
} else { } else {
buf = append(buf, '1') buf = append(buf, '1')
} }
return string(buf) return buf
} }
// RatString returns a string representation of x in the form "a/b" if b != 1, // RatString returns a string representation of x in the form "a/b" if b != 1,

View File

@ -59,8 +59,10 @@ func (z *Rat) GobDecode(buf []byte) error {
// MarshalText implements the encoding.TextMarshaler interface. // MarshalText implements the encoding.TextMarshaler interface.
func (x *Rat) MarshalText() (text []byte, err error) { func (x *Rat) MarshalText() (text []byte, err error) {
// TODO(gri): get rid of the []byte/string conversion if x.IsInt() {
return []byte(x.RatString()), nil return x.a.MarshalText()
}
return x.marshal(), nil
} }
// UnmarshalText implements the encoding.TextUnmarshaler interface. // UnmarshalText implements the encoding.TextUnmarshaler interface.