您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

511 行
12 KiB

  1. // Copyright 2017 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. package message
  5. import (
  6. "bytes"
  7. "strconv"
  8. "unicode/utf8"
  9. "golang.org/x/text/internal/format"
  10. )
  11. const (
  12. ldigits = "0123456789abcdefx"
  13. udigits = "0123456789ABCDEFX"
  14. )
  15. const (
  16. signed = true
  17. unsigned = false
  18. )
  19. // A formatInfo is the raw formatter used by Printf etc.
  20. // It prints into a buffer that must be set up separately.
  21. type formatInfo struct {
  22. buf *bytes.Buffer
  23. format.Parser
  24. // intbuf is large enough to store %b of an int64 with a sign and
  25. // avoids padding at the end of the struct on 32 bit architectures.
  26. intbuf [68]byte
  27. }
  28. func (f *formatInfo) init(buf *bytes.Buffer) {
  29. f.ClearFlags()
  30. f.buf = buf
  31. }
  32. // writePadding generates n bytes of padding.
  33. func (f *formatInfo) writePadding(n int) {
  34. if n <= 0 { // No padding bytes needed.
  35. return
  36. }
  37. f.buf.Grow(n)
  38. // Decide which byte the padding should be filled with.
  39. padByte := byte(' ')
  40. if f.Zero {
  41. padByte = byte('0')
  42. }
  43. // Fill padding with padByte.
  44. for i := 0; i < n; i++ {
  45. f.buf.WriteByte(padByte) // TODO: make more efficient.
  46. }
  47. }
  48. // pad appends b to f.buf, padded on left (!f.minus) or right (f.minus).
  49. func (f *formatInfo) pad(b []byte) {
  50. if !f.WidthPresent || f.Width == 0 {
  51. f.buf.Write(b)
  52. return
  53. }
  54. width := f.Width - utf8.RuneCount(b)
  55. if !f.Minus {
  56. // left padding
  57. f.writePadding(width)
  58. f.buf.Write(b)
  59. } else {
  60. // right padding
  61. f.buf.Write(b)
  62. f.writePadding(width)
  63. }
  64. }
  65. // padString appends s to f.buf, padded on left (!f.minus) or right (f.minus).
  66. func (f *formatInfo) padString(s string) {
  67. if !f.WidthPresent || f.Width == 0 {
  68. f.buf.WriteString(s)
  69. return
  70. }
  71. width := f.Width - utf8.RuneCountInString(s)
  72. if !f.Minus {
  73. // left padding
  74. f.writePadding(width)
  75. f.buf.WriteString(s)
  76. } else {
  77. // right padding
  78. f.buf.WriteString(s)
  79. f.writePadding(width)
  80. }
  81. }
  82. // fmt_boolean formats a boolean.
  83. func (f *formatInfo) fmt_boolean(v bool) {
  84. if v {
  85. f.padString("true")
  86. } else {
  87. f.padString("false")
  88. }
  89. }
  90. // fmt_unicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'".
  91. func (f *formatInfo) fmt_unicode(u uint64) {
  92. buf := f.intbuf[0:]
  93. // With default precision set the maximum needed buf length is 18
  94. // for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits
  95. // into the already allocated intbuf with a capacity of 68 bytes.
  96. prec := 4
  97. if f.PrecPresent && f.Prec > 4 {
  98. prec = f.Prec
  99. // Compute space needed for "U+" , number, " '", character, "'".
  100. width := 2 + prec + 2 + utf8.UTFMax + 1
  101. if width > len(buf) {
  102. buf = make([]byte, width)
  103. }
  104. }
  105. // Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
  106. i := len(buf)
  107. // For %#U we want to add a space and a quoted character at the end of the buffer.
  108. if f.Sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
  109. i--
  110. buf[i] = '\''
  111. i -= utf8.RuneLen(rune(u))
  112. utf8.EncodeRune(buf[i:], rune(u))
  113. i--
  114. buf[i] = '\''
  115. i--
  116. buf[i] = ' '
  117. }
  118. // Format the Unicode code point u as a hexadecimal number.
  119. for u >= 16 {
  120. i--
  121. buf[i] = udigits[u&0xF]
  122. prec--
  123. u >>= 4
  124. }
  125. i--
  126. buf[i] = udigits[u]
  127. prec--
  128. // Add zeros in front of the number until requested precision is reached.
  129. for prec > 0 {
  130. i--
  131. buf[i] = '0'
  132. prec--
  133. }
  134. // Add a leading "U+".
  135. i--
  136. buf[i] = '+'
  137. i--
  138. buf[i] = 'U'
  139. oldZero := f.Zero
  140. f.Zero = false
  141. f.pad(buf[i:])
  142. f.Zero = oldZero
  143. }
  144. // fmt_integer formats signed and unsigned integers.
  145. func (f *formatInfo) fmt_integer(u uint64, base int, isSigned bool, digits string) {
  146. negative := isSigned && int64(u) < 0
  147. if negative {
  148. u = -u
  149. }
  150. buf := f.intbuf[0:]
  151. // The already allocated f.intbuf with a capacity of 68 bytes
  152. // is large enough for integer formatting when no precision or width is set.
  153. if f.WidthPresent || f.PrecPresent {
  154. // Account 3 extra bytes for possible addition of a sign and "0x".
  155. width := 3 + f.Width + f.Prec // wid and prec are always positive.
  156. if width > len(buf) {
  157. // We're going to need a bigger boat.
  158. buf = make([]byte, width)
  159. }
  160. }
  161. // Two ways to ask for extra leading zero digits: %.3d or %03d.
  162. // If both are specified the f.zero flag is ignored and
  163. // padding with spaces is used instead.
  164. prec := 0
  165. if f.PrecPresent {
  166. prec = f.Prec
  167. // Precision of 0 and value of 0 means "print nothing" but padding.
  168. if prec == 0 && u == 0 {
  169. oldZero := f.Zero
  170. f.Zero = false
  171. f.writePadding(f.Width)
  172. f.Zero = oldZero
  173. return
  174. }
  175. } else if f.Zero && f.WidthPresent {
  176. prec = f.Width
  177. if negative || f.Plus || f.Space {
  178. prec-- // leave room for sign
  179. }
  180. }
  181. // Because printing is easier right-to-left: format u into buf, ending at buf[i].
  182. // We could make things marginally faster by splitting the 32-bit case out
  183. // into a separate block but it's not worth the duplication, so u has 64 bits.
  184. i := len(buf)
  185. // Use constants for the division and modulo for more efficient code.
  186. // Switch cases ordered by popularity.
  187. switch base {
  188. case 10:
  189. for u >= 10 {
  190. i--
  191. next := u / 10
  192. buf[i] = byte('0' + u - next*10)
  193. u = next
  194. }
  195. case 16:
  196. for u >= 16 {
  197. i--
  198. buf[i] = digits[u&0xF]
  199. u >>= 4
  200. }
  201. case 8:
  202. for u >= 8 {
  203. i--
  204. buf[i] = byte('0' + u&7)
  205. u >>= 3
  206. }
  207. case 2:
  208. for u >= 2 {
  209. i--
  210. buf[i] = byte('0' + u&1)
  211. u >>= 1
  212. }
  213. default:
  214. panic("fmt: unknown base; can't happen")
  215. }
  216. i--
  217. buf[i] = digits[u]
  218. for i > 0 && prec > len(buf)-i {
  219. i--
  220. buf[i] = '0'
  221. }
  222. // Various prefixes: 0x, -, etc.
  223. if f.Sharp {
  224. switch base {
  225. case 8:
  226. if buf[i] != '0' {
  227. i--
  228. buf[i] = '0'
  229. }
  230. case 16:
  231. // Add a leading 0x or 0X.
  232. i--
  233. buf[i] = digits[16]
  234. i--
  235. buf[i] = '0'
  236. }
  237. }
  238. if negative {
  239. i--
  240. buf[i] = '-'
  241. } else if f.Plus {
  242. i--
  243. buf[i] = '+'
  244. } else if f.Space {
  245. i--
  246. buf[i] = ' '
  247. }
  248. // Left padding with zeros has already been handled like precision earlier
  249. // or the f.zero flag is ignored due to an explicitly set precision.
  250. oldZero := f.Zero
  251. f.Zero = false
  252. f.pad(buf[i:])
  253. f.Zero = oldZero
  254. }
  255. // truncate truncates the string to the specified precision, if present.
  256. func (f *formatInfo) truncate(s string) string {
  257. if f.PrecPresent {
  258. n := f.Prec
  259. for i := range s {
  260. n--
  261. if n < 0 {
  262. return s[:i]
  263. }
  264. }
  265. }
  266. return s
  267. }
  268. // fmt_s formats a string.
  269. func (f *formatInfo) fmt_s(s string) {
  270. s = f.truncate(s)
  271. f.padString(s)
  272. }
  273. // fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
  274. func (f *formatInfo) fmt_sbx(s string, b []byte, digits string) {
  275. length := len(b)
  276. if b == nil {
  277. // No byte slice present. Assume string s should be encoded.
  278. length = len(s)
  279. }
  280. // Set length to not process more bytes than the precision demands.
  281. if f.PrecPresent && f.Prec < length {
  282. length = f.Prec
  283. }
  284. // Compute width of the encoding taking into account the f.sharp and f.space flag.
  285. width := 2 * length
  286. if width > 0 {
  287. if f.Space {
  288. // Each element encoded by two hexadecimals will get a leading 0x or 0X.
  289. if f.Sharp {
  290. width *= 2
  291. }
  292. // Elements will be separated by a space.
  293. width += length - 1
  294. } else if f.Sharp {
  295. // Only a leading 0x or 0X will be added for the whole string.
  296. width += 2
  297. }
  298. } else { // The byte slice or string that should be encoded is empty.
  299. if f.WidthPresent {
  300. f.writePadding(f.Width)
  301. }
  302. return
  303. }
  304. // Handle padding to the left.
  305. if f.WidthPresent && f.Width > width && !f.Minus {
  306. f.writePadding(f.Width - width)
  307. }
  308. // Write the encoding directly into the output buffer.
  309. buf := f.buf
  310. if f.Sharp {
  311. // Add leading 0x or 0X.
  312. buf.WriteByte('0')
  313. buf.WriteByte(digits[16])
  314. }
  315. var c byte
  316. for i := 0; i < length; i++ {
  317. if f.Space && i > 0 {
  318. // Separate elements with a space.
  319. buf.WriteByte(' ')
  320. if f.Sharp {
  321. // Add leading 0x or 0X for each element.
  322. buf.WriteByte('0')
  323. buf.WriteByte(digits[16])
  324. }
  325. }
  326. if b != nil {
  327. c = b[i] // Take a byte from the input byte slice.
  328. } else {
  329. c = s[i] // Take a byte from the input string.
  330. }
  331. // Encode each byte as two hexadecimal digits.
  332. buf.WriteByte(digits[c>>4])
  333. buf.WriteByte(digits[c&0xF])
  334. }
  335. // Handle padding to the right.
  336. if f.WidthPresent && f.Width > width && f.Minus {
  337. f.writePadding(f.Width - width)
  338. }
  339. }
  340. // fmt_sx formats a string as a hexadecimal encoding of its bytes.
  341. func (f *formatInfo) fmt_sx(s, digits string) {
  342. f.fmt_sbx(s, nil, digits)
  343. }
  344. // fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
  345. func (f *formatInfo) fmt_bx(b []byte, digits string) {
  346. f.fmt_sbx("", b, digits)
  347. }
  348. // fmt_q formats a string as a double-quoted, escaped Go string constant.
  349. // If f.sharp is set a raw (backquoted) string may be returned instead
  350. // if the string does not contain any control characters other than tab.
  351. func (f *formatInfo) fmt_q(s string) {
  352. s = f.truncate(s)
  353. if f.Sharp && strconv.CanBackquote(s) {
  354. f.padString("`" + s + "`")
  355. return
  356. }
  357. buf := f.intbuf[:0]
  358. if f.Plus {
  359. f.pad(strconv.AppendQuoteToASCII(buf, s))
  360. } else {
  361. f.pad(strconv.AppendQuote(buf, s))
  362. }
  363. }
  364. // fmt_c formats an integer as a Unicode character.
  365. // If the character is not valid Unicode, it will print '\ufffd'.
  366. func (f *formatInfo) fmt_c(c uint64) {
  367. r := rune(c)
  368. if c > utf8.MaxRune {
  369. r = utf8.RuneError
  370. }
  371. buf := f.intbuf[:0]
  372. w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
  373. f.pad(buf[:w])
  374. }
  375. // fmt_qc formats an integer as a single-quoted, escaped Go character constant.
  376. // If the character is not valid Unicode, it will print '\ufffd'.
  377. func (f *formatInfo) fmt_qc(c uint64) {
  378. r := rune(c)
  379. if c > utf8.MaxRune {
  380. r = utf8.RuneError
  381. }
  382. buf := f.intbuf[:0]
  383. if f.Plus {
  384. f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
  385. } else {
  386. f.pad(strconv.AppendQuoteRune(buf, r))
  387. }
  388. }
  389. // fmt_float formats a float64. It assumes that verb is a valid format specifier
  390. // for strconv.AppendFloat and therefore fits into a byte.
  391. func (f *formatInfo) fmt_float(v float64, size int, verb rune, prec int) {
  392. // Explicit precision in format specifier overrules default precision.
  393. if f.PrecPresent {
  394. prec = f.Prec
  395. }
  396. // Format number, reserving space for leading + sign if needed.
  397. num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
  398. if num[1] == '-' || num[1] == '+' {
  399. num = num[1:]
  400. } else {
  401. num[0] = '+'
  402. }
  403. // f.space means to add a leading space instead of a "+" sign unless
  404. // the sign is explicitly asked for by f.plus.
  405. if f.Space && num[0] == '+' && !f.Plus {
  406. num[0] = ' '
  407. }
  408. // Special handling for infinities and NaN,
  409. // which don't look like a number so shouldn't be padded with zeros.
  410. if num[1] == 'I' || num[1] == 'N' {
  411. oldZero := f.Zero
  412. f.Zero = false
  413. // Remove sign before NaN if not asked for.
  414. if num[1] == 'N' && !f.Space && !f.Plus {
  415. num = num[1:]
  416. }
  417. f.pad(num)
  418. f.Zero = oldZero
  419. return
  420. }
  421. // The sharp flag forces printing a decimal point for non-binary formats
  422. // and retains trailing zeros, which we may need to restore.
  423. if f.Sharp && verb != 'b' {
  424. digits := 0
  425. switch verb {
  426. case 'v', 'g', 'G':
  427. digits = prec
  428. // If no precision is set explicitly use a precision of 6.
  429. if digits == -1 {
  430. digits = 6
  431. }
  432. }
  433. // Buffer pre-allocated with enough room for
  434. // exponent notations of the form "e+123".
  435. var tailBuf [5]byte
  436. tail := tailBuf[:0]
  437. hasDecimalPoint := false
  438. // Starting from i = 1 to skip sign at num[0].
  439. for i := 1; i < len(num); i++ {
  440. switch num[i] {
  441. case '.':
  442. hasDecimalPoint = true
  443. case 'e', 'E':
  444. tail = append(tail, num[i:]...)
  445. num = num[:i]
  446. default:
  447. digits--
  448. }
  449. }
  450. if !hasDecimalPoint {
  451. num = append(num, '.')
  452. }
  453. for digits > 0 {
  454. num = append(num, '0')
  455. digits--
  456. }
  457. num = append(num, tail...)
  458. }
  459. // We want a sign if asked for and if the sign is not positive.
  460. if f.Plus || num[0] != '+' {
  461. // If we're zero padding to the left we want the sign before the leading zeros.
  462. // Achieve this by writing the sign out and then padding the unsigned number.
  463. if f.Zero && f.WidthPresent && f.Width > len(num) {
  464. f.buf.WriteByte(num[0])
  465. f.writePadding(f.Width - len(num))
  466. f.buf.Write(num[1:])
  467. return
  468. }
  469. f.pad(num)
  470. return
  471. }
  472. // No sign to show and the number is positive; just print the unsigned number.
  473. f.pad(num[1:])
  474. }