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