...

Source file src/math/big/intconv.go

Documentation: math/big

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

View as plain text