Black Lives Matter. Support the Equal Justice Initiative.

# Source file src/math/big/intconv.go

## Documentation: math/big

2  // Use of this source code is governed by a BSD-style
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
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"
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
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:
211  	}
212  	return
213  }
214
215  // byteReader is a local wrapper around fmt.ScanState;
216  // it implements the ByteReader interface.
218  	fmt.ScanState
219  }
220
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
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),
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