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