...
Run Format

Source file src/math/big/intconv.go

  // 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"
  )
  
  // TODO(gri) Should rename itoa to utoa (there's no sign). That
  // would permit the introduction of itoa which is like utoa but
  // reserves a byte for a possible sign that's passed in. That
  // would permit Int.Text to be implemented w/o the need for
  // string copy if the number is negative.
  
  // Text returns the string representation of x in the given base.
  // Base must be between 2 and 36, inclusive. The result uses the
  // lower-case letters 'a' to 'z' for digit values >= 10. No base
  // prefix (such as "0x") is added to the string.
  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)...)
  }
  
  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), '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':
  		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 'o': // octal
  			prefix = "0"
  		case 'x': // hexadecimal
  			prefix = "0x"
  		case 'X':
  			prefix = "0X"
  		}
  	}
  
  	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
  // ``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) 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
  }
  

View as plain text