intconv.go 6.7 KB

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