github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/math/big/intconv.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file implements int-to-string conversion functions.
     6  
     7  package big
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  )
    14  
    15  // TODO(gri) Should rename itoa to utoa (there's no sign). That
    16  // would permit the introduction of itoa which is like utoa but
    17  // reserves a byte for a possible sign that's passed in. That
    18  // would permit Int.Text to be implemented w/o the need for
    19  // string copy if the number is negative.
    20  
    21  // Text returns the string representation of x in the given base.
    22  // Base must be between 2 and 36, inclusive. The result uses the
    23  // lower-case letters 'a' to 'z' for digit values >= 10. No base
    24  // prefix (such as "0x") is added to the string.
    25  func (x *Int) Text(base int) string {
    26  	if x == nil {
    27  		return "<nil>"
    28  	}
    29  	return string(x.abs.itoa(x.neg, base))
    30  }
    31  
    32  // Append appends the string representation of x, as generated by
    33  // x.Text(base), to buf and returns the extended buffer.
    34  func (x *Int) Append(buf []byte, base int) []byte {
    35  	if x == nil {
    36  		return append(buf, "<nil>"...)
    37  	}
    38  	return append(buf, x.abs.itoa(x.neg, base)...)
    39  }
    40  
    41  func (x *Int) String() string {
    42  	return x.Text(10)
    43  }
    44  
    45  // write count copies of text to s
    46  func writeMultiple(s fmt.State, text string, count int) {
    47  	if len(text) > 0 {
    48  		b := []byte(text)
    49  		for ; count > 0; count-- {
    50  			s.Write(b)
    51  		}
    52  	}
    53  }
    54  
    55  var _ fmt.Formatter = intOne // *Int must implement fmt.Formatter
    56  
    57  // Format implements fmt.Formatter. It accepts the formats
    58  // 'b' (binary), 'o' (octal), 'd' (decimal), 'x' (lowercase
    59  // hexadecimal), and 'X' (uppercase hexadecimal).
    60  // Also supported are the full suite of package fmt's format
    61  // flags for integral types, including '+' and ' ' for sign
    62  // control, '#' for leading zero in octal and for hexadecimal,
    63  // a leading "0x" or "0X" for "%#x" and "%#X" respectively,
    64  // specification of minimum digits precision, output field
    65  // width, space or zero padding, and '-' for left or right
    66  // justification.
    67  //
    68  func (x *Int) Format(s fmt.State, ch rune) {
    69  	// determine base
    70  	var base int
    71  	switch ch {
    72  	case 'b':
    73  		base = 2
    74  	case 'o':
    75  		base = 8
    76  	case 'd', 's', 'v':
    77  		base = 10
    78  	case 'x', 'X':
    79  		base = 16
    80  	default:
    81  		// unknown format
    82  		fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
    83  		return
    84  	}
    85  
    86  	if x == nil {
    87  		fmt.Fprint(s, "<nil>")
    88  		return
    89  	}
    90  
    91  	// determine sign character
    92  	sign := ""
    93  	switch {
    94  	case x.neg:
    95  		sign = "-"
    96  	case s.Flag('+'): // supersedes ' ' when both specified
    97  		sign = "+"
    98  	case s.Flag(' '):
    99  		sign = " "
   100  	}
   101  
   102  	// determine prefix characters for indicating output base
   103  	prefix := ""
   104  	if s.Flag('#') {
   105  		switch ch {
   106  		case 'o': // octal
   107  			prefix = "0"
   108  		case 'x': // hexadecimal
   109  			prefix = "0x"
   110  		case 'X':
   111  			prefix = "0X"
   112  		}
   113  	}
   114  
   115  	digits := x.abs.utoa(base)
   116  	if ch == 'X' {
   117  		// faster than bytes.ToUpper
   118  		for i, d := range digits {
   119  			if 'a' <= d && d <= 'z' {
   120  				digits[i] = 'A' + (d - 'a')
   121  			}
   122  		}
   123  	}
   124  
   125  	// number of characters for the three classes of number padding
   126  	var left int  // space characters to left of digits for right justification ("%8d")
   127  	var zeros int // zero characters (actually cs[0]) as left-most digits ("%.8d")
   128  	var right int // space characters to right of digits for left justification ("%-8d")
   129  
   130  	// determine number padding from precision: the least number of digits to output
   131  	precision, precisionSet := s.Precision()
   132  	if precisionSet {
   133  		switch {
   134  		case len(digits) < precision:
   135  			zeros = precision - len(digits) // count of zero padding
   136  		case len(digits) == 1 && digits[0] == '0' && precision == 0:
   137  			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
   138  		}
   139  	}
   140  
   141  	// determine field pad from width: the least number of characters to output
   142  	length := len(sign) + len(prefix) + zeros + len(digits)
   143  	if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
   144  		switch d := width - length; {
   145  		case s.Flag('-'):
   146  			// pad on the right with spaces; supersedes '0' when both specified
   147  			right = d
   148  		case s.Flag('0') && !precisionSet:
   149  			// pad with zeros unless precision also specified
   150  			zeros = d
   151  		default:
   152  			// pad on the left with spaces
   153  			left = d
   154  		}
   155  	}
   156  
   157  	// print number as [left pad][sign][prefix][zero pad][digits][right pad]
   158  	writeMultiple(s, " ", left)
   159  	writeMultiple(s, sign, 1)
   160  	writeMultiple(s, prefix, 1)
   161  	writeMultiple(s, "0", zeros)
   162  	s.Write(digits)
   163  	writeMultiple(s, " ", right)
   164  }
   165  
   166  // scan sets z to the integer value corresponding to the longest possible prefix
   167  // read from r representing a signed integer number in a given conversion base.
   168  // It returns z, the actual conversion base used, and an error, if any. In the
   169  // error case, the value of z is undefined but the returned value is nil. The
   170  // syntax follows the syntax of integer literals in Go.
   171  //
   172  // The base argument must be 0 or a value from 2 through MaxBase. If the base
   173  // is 0, the string prefix determines the actual conversion base. A prefix of
   174  // ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
   175  // ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
   176  //
   177  func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) {
   178  	// determine sign
   179  	neg, err := scanSign(r)
   180  	if err != nil {
   181  		return nil, 0, err
   182  	}
   183  
   184  	// determine mantissa
   185  	z.abs, base, _, err = z.abs.scan(r, base, false)
   186  	if err != nil {
   187  		return nil, base, err
   188  	}
   189  	z.neg = len(z.abs) > 0 && neg // 0 has no sign
   190  
   191  	return z, base, nil
   192  }
   193  
   194  func scanSign(r io.ByteScanner) (neg bool, err error) {
   195  	var ch byte
   196  	if ch, err = r.ReadByte(); err != nil {
   197  		return false, err
   198  	}
   199  	switch ch {
   200  	case '-':
   201  		neg = true
   202  	case '+':
   203  		// nothing to do
   204  	default:
   205  		r.UnreadByte()
   206  	}
   207  	return
   208  }
   209  
   210  // byteReader is a local wrapper around fmt.ScanState;
   211  // it implements the ByteReader interface.
   212  type byteReader struct {
   213  	fmt.ScanState
   214  }
   215  
   216  func (r byteReader) ReadByte() (byte, error) {
   217  	ch, size, err := r.ReadRune()
   218  	if size != 1 && err == nil {
   219  		err = fmt.Errorf("invalid rune %#U", ch)
   220  	}
   221  	return byte(ch), err
   222  }
   223  
   224  func (r byteReader) UnreadByte() error {
   225  	return r.UnreadRune()
   226  }
   227  
   228  var _ fmt.Scanner = intOne // *Int must implement fmt.Scanner
   229  
   230  // Scan is a support routine for fmt.Scanner; it sets z to the value of
   231  // the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
   232  // 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
   233  func (z *Int) Scan(s fmt.ScanState, ch rune) error {
   234  	s.SkipSpace() // skip leading space characters
   235  	base := 0
   236  	switch ch {
   237  	case 'b':
   238  		base = 2
   239  	case 'o':
   240  		base = 8
   241  	case 'd':
   242  		base = 10
   243  	case 'x', 'X':
   244  		base = 16
   245  	case 's', 'v':
   246  		// let scan determine the base
   247  	default:
   248  		return errors.New("Int.Scan: invalid verb")
   249  	}
   250  	_, _, err := z.scan(byteReader{s}, base)
   251  	return err
   252  }