OSDN Git Service

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