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