123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- // 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"
- )
- // Text returns the string representation of x in the given base.
- // Base must be between 2 and 62, inclusive. The result uses the
- // lower-case letters 'a' to 'z' for digit values 10 to 35, and
- // the upper-case letters 'A' to 'Z' for digit values 36 to 61.
- // No prefix (such as "0x") is added to the string. If x is a nil
- // pointer it returns "<nil>".
- func (x *Int) Text(base int) string {
- if x == nil {
- return "<nil>"
- }
- return string(x.abs.itoa(x.neg, base))
- }
- // Append appends the string representation of x, as generated by
- // x.Text(base), to buf and returns the extended buffer.
- func (x *Int) Append(buf []byte, base int) []byte {
- if x == nil {
- return append(buf, "<nil>"...)
- }
- return append(buf, x.abs.itoa(x.neg, base)...)
- }
- // String returns the decimal representation of x as generated by
- // x.Text(10).
- func (x *Int) String() string {
- return x.Text(10)
- }
- // 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)
- }
- }
- }
- var _ fmt.Formatter = intOne // *Int must implement fmt.Formatter
- // Format implements fmt.Formatter. It accepts the formats
- // 'b' (binary), 'o' (octal with 0 prefix), 'O' (octal with 0o prefix),
- // 'd' (decimal), 'x' (lowercase hexadecimal), and
- // 'X' (uppercase hexadecimal).
- // Also supported are the full suite of package fmt's format
- // flags 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 '-' for left or right
- // justification.
- //
- func (x *Int) Format(s fmt.State, ch rune) {
- // determine base
- var base int
- switch ch {
- case 'b':
- base = 2
- case 'o', 'O':
- base = 8
- case 'd', 's', 'v':
- base = 10
- case 'x', 'X':
- base = 16
- default:
- // unknown format
- fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
- return
- }
- if 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 'b': // binary
- prefix = "0b"
- case 'o': // octal
- prefix = "0"
- case 'x': // hexadecimal
- prefix = "0x"
- case 'X':
- prefix = "0X"
- }
- }
- if ch == 'O' {
- prefix = "0o"
- }
- digits := x.abs.utoa(base)
- if ch == 'X' {
- // faster than bytes.ToUpper
- for i, d := range digits {
- if 'a' <= d && d <= 'z' {
- digits[i] = 'A' + (d - 'a')
- }
- }
- }
- // number of characters for the three classes of number padding
- var left int // space characters to left of digits for right justification ("%8d")
- var zeros 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:
- zeros = precision - len(digits) // count of zero padding
- case len(digits) == 1 && digits[0] == '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) + zeros + 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 zeros unless precision also specified
- zeros = 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", zeros)
- s.Write(digits)
- 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
- // ``0b'' or ``0B'' selects base 2; a ``0'', ``0o'', or ``0O'' prefix selects
- // base 8, and a ``0x'' or ``0X'' prefix selects base 16. 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()
- }
- var _ fmt.Scanner = intOne // *Int must implement fmt.Scanner
- // 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
- }
|