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. 20 func (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. 29 func (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 36 func (x *Int) String() string { 37 return x.Text(10) 38 } 39 40 // write count copies of text to s 41 func 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 50 var _ 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 // 63 func (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 // 172 func (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 189 func 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. 207 type byteReader struct { 208 fmt.ScanState 209 } 210 211 func (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 219 func (r byteReader) UnreadByte() error { 220 return r.UnreadRune() 221 } 222 223 var _ 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). 228 func (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