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) []byte {
22 if x == nil {
23 return "<nil>"
24 }
25 return []byte(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 []byte, 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 func (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.
180 func (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 197 func 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.
215 type byteReader struct {
216 fmt.ScanState
217 }
218 219 func (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 227 func (r byteReader) UnreadByte() error {
228 return r.UnreadRune()
229 }
230 231 var _ 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).
236 func (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