|  | // Copyright 2015 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // This file implements int-to-string conversion functions. | 
|  |  | 
|  | package big | 
|  |  | 
|  | import ( | 
|  | "errors" | 
|  | "fmt" | 
|  | "io" | 
|  | ) | 
|  |  | 
|  | // Text returns the string representation of x in the given base. | 
|  | // Base must be between 2 and 62, inclusive. The result uses the | 
|  | // lower-case letters 'a' to 'z' for digit values 10 to 35, and | 
|  | // the upper-case letters 'A' to 'Z' for digit values 36 to 61. | 
|  | // No prefix (such as "0x") is added to the string. If x is a nil | 
|  | // pointer it returns "<nil>". | 
|  | func (x *Int) Text(base int) string { | 
|  | if x == nil { | 
|  | return "<nil>" | 
|  | } | 
|  | return string(x.abs.itoa(x.neg, base)) | 
|  | } | 
|  |  | 
|  | // Append appends the string representation of x, as generated by | 
|  | // x.Text(base), to buf and returns the extended buffer. | 
|  | func (x *Int) Append(buf []byte, base int) []byte { | 
|  | if x == nil { | 
|  | return append(buf, "<nil>"...) | 
|  | } | 
|  | return append(buf, x.abs.itoa(x.neg, base)...) | 
|  | } | 
|  |  | 
|  | // String returns the decimal representation of x as generated by | 
|  | // x.Text(10). | 
|  | func (x *Int) String() string { | 
|  | return x.Text(10) | 
|  | } | 
|  |  | 
|  | // write count copies of text to s. | 
|  | func writeMultiple(s fmt.State, text string, count int) { | 
|  | if len(text) > 0 { | 
|  | b := []byte(text) | 
|  | for ; count > 0; count-- { | 
|  | s.Write(b) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | var _ fmt.Formatter = intOne // *Int must implement fmt.Formatter | 
|  |  | 
|  | // Format implements [fmt.Formatter]. It accepts the formats | 
|  | // 'b' (binary), 'o' (octal with 0 prefix), 'O' (octal with 0o prefix), | 
|  | // 'd' (decimal), 'x' (lowercase hexadecimal), and | 
|  | // 'X' (uppercase hexadecimal). | 
|  | // Also supported are the full suite of package fmt's format | 
|  | // flags for integral types, including '+' and ' ' for sign | 
|  | // control, '#' for leading zero in octal and for hexadecimal, | 
|  | // a leading "0x" or "0X" for "%#x" and "%#X" respectively, | 
|  | // specification of minimum digits precision, output field | 
|  | // width, space or zero padding, and '-' for left or right | 
|  | // justification. | 
|  | func (x *Int) Format(s fmt.State, ch rune) { | 
|  | // determine base | 
|  | var base int | 
|  | switch ch { | 
|  | case 'b': | 
|  | base = 2 | 
|  | case 'o', 'O': | 
|  | base = 8 | 
|  | case 'd', 's', 'v': | 
|  | base = 10 | 
|  | case 'x', 'X': | 
|  | base = 16 | 
|  | default: | 
|  | // unknown format | 
|  | fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String()) | 
|  | return | 
|  | } | 
|  |  | 
|  | if x == nil { | 
|  | fmt.Fprint(s, "<nil>") | 
|  | return | 
|  | } | 
|  |  | 
|  | // determine sign character | 
|  | sign := "" | 
|  | switch { | 
|  | case x.neg: | 
|  | sign = "-" | 
|  | case s.Flag('+'): // supersedes ' ' when both specified | 
|  | sign = "+" | 
|  | case s.Flag(' '): | 
|  | sign = " " | 
|  | } | 
|  |  | 
|  | // determine prefix characters for indicating output base | 
|  | prefix := "" | 
|  | if s.Flag('#') { | 
|  | switch ch { | 
|  | case 'b': // binary | 
|  | prefix = "0b" | 
|  | case 'o': // octal | 
|  | prefix = "0" | 
|  | case 'x': // hexadecimal | 
|  | prefix = "0x" | 
|  | case 'X': | 
|  | prefix = "0X" | 
|  | } | 
|  | } | 
|  | if ch == 'O' { | 
|  | prefix = "0o" | 
|  | } | 
|  |  | 
|  | digits := x.abs.utoa(base) | 
|  | if ch == 'X' { | 
|  | // faster than bytes.ToUpper | 
|  | for i, d := range digits { | 
|  | if 'a' <= d && d <= 'z' { | 
|  | digits[i] = 'A' + (d - 'a') | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // number of characters for the three classes of number padding | 
|  | var left int  // space characters to left of digits for right justification ("%8d") | 
|  | var zeros int // zero characters (actually cs[0]) as left-most digits ("%.8d") | 
|  | var right int // space characters to right of digits for left justification ("%-8d") | 
|  |  | 
|  | // determine number padding from precision: the least number of digits to output | 
|  | precision, precisionSet := s.Precision() | 
|  | if precisionSet { | 
|  | switch { | 
|  | case len(digits) < precision: | 
|  | zeros = precision - len(digits) // count of zero padding | 
|  | case len(digits) == 1 && digits[0] == '0' && precision == 0: | 
|  | return // print nothing if zero value (x == 0) and zero precision ("." or ".0") | 
|  | } | 
|  | } | 
|  |  | 
|  | // determine field pad from width: the least number of characters to output | 
|  | length := len(sign) + len(prefix) + zeros + len(digits) | 
|  | if width, widthSet := s.Width(); widthSet && length < width { // pad as specified | 
|  | switch d := width - length; { | 
|  | case s.Flag('-'): | 
|  | // pad on the right with spaces; supersedes '0' when both specified | 
|  | right = d | 
|  | case s.Flag('0') && !precisionSet: | 
|  | // pad with zeros unless precision also specified | 
|  | zeros = d | 
|  | default: | 
|  | // pad on the left with spaces | 
|  | left = d | 
|  | } | 
|  | } | 
|  |  | 
|  | // print number as [left pad][sign][prefix][zero pad][digits][right pad] | 
|  | writeMultiple(s, " ", left) | 
|  | writeMultiple(s, sign, 1) | 
|  | writeMultiple(s, prefix, 1) | 
|  | writeMultiple(s, "0", zeros) | 
|  | s.Write(digits) | 
|  | writeMultiple(s, " ", right) | 
|  | } | 
|  |  | 
|  | // scan sets z to the integer value corresponding to the longest possible prefix | 
|  | // read from r representing a signed integer number in a given conversion base. | 
|  | // It returns z, the actual conversion base used, and an error, if any. In the | 
|  | // error case, the value of z is undefined but the returned value is nil. The | 
|  | // syntax follows the syntax of integer literals in Go. | 
|  | // | 
|  | // The base argument must be 0 or a value from 2 through MaxBase. If the base | 
|  | // is 0, the string prefix determines the actual conversion base. A prefix of | 
|  | // “0b” or “0B” selects base 2; a “0”, “0o”, or “0O” prefix selects | 
|  | // base 8, and a “0x” or “0X” prefix selects base 16. Otherwise the selected | 
|  | // base is 10. | 
|  | func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) { | 
|  | // determine sign | 
|  | neg, err := scanSign(r) | 
|  | if err != nil { | 
|  | return nil, 0, err | 
|  | } | 
|  |  | 
|  | // determine mantissa | 
|  | z.abs, base, _, err = z.abs.scan(r, base, false) | 
|  | if err != nil { | 
|  | return nil, base, err | 
|  | } | 
|  | z.neg = len(z.abs) > 0 && neg // 0 has no sign | 
|  |  | 
|  | return z, base, nil | 
|  | } | 
|  |  | 
|  | func scanSign(r io.ByteScanner) (neg bool, err error) { | 
|  | var ch byte | 
|  | if ch, err = r.ReadByte(); err != nil { | 
|  | return false, err | 
|  | } | 
|  | switch ch { | 
|  | case '-': | 
|  | neg = true | 
|  | case '+': | 
|  | // nothing to do | 
|  | default: | 
|  | r.UnreadByte() | 
|  | } | 
|  | return | 
|  | } | 
|  |  | 
|  | // byteReader is a local wrapper around fmt.ScanState; | 
|  | // it implements the ByteReader interface. | 
|  | type byteReader struct { | 
|  | fmt.ScanState | 
|  | } | 
|  |  | 
|  | func (r byteReader) ReadByte() (byte, error) { | 
|  | ch, size, err := r.ReadRune() | 
|  | if size != 1 && err == nil { | 
|  | err = fmt.Errorf("invalid rune %#U", ch) | 
|  | } | 
|  | return byte(ch), err | 
|  | } | 
|  |  | 
|  | func (r byteReader) UnreadByte() error { | 
|  | return r.UnreadRune() | 
|  | } | 
|  |  | 
|  | var _ fmt.Scanner = intOne // *Int must implement fmt.Scanner | 
|  |  | 
|  | // Scan is a support routine for [fmt.Scanner]; it sets z to the value of | 
|  | // the scanned number. It accepts the formats 'b' (binary), 'o' (octal), | 
|  | // 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal). | 
|  | func (z *Int) Scan(s fmt.ScanState, ch rune) error { | 
|  | s.SkipSpace() // skip leading space characters | 
|  | base := 0 | 
|  | switch ch { | 
|  | case 'b': | 
|  | base = 2 | 
|  | case 'o': | 
|  | base = 8 | 
|  | case 'd': | 
|  | base = 10 | 
|  | case 'x', 'X': | 
|  | base = 16 | 
|  | case 's', 'v': | 
|  | // let scan determine the base | 
|  | default: | 
|  | return errors.New("Int.Scan: invalid verb") | 
|  | } | 
|  | _, _, err := z.scan(byteReader{s}, base) | 
|  | return err | 
|  | } |