Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: third_party/golang/src/fmt/fmt.go

Issue 1414693011: Adds unmodified source files from golang.org. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/golang/README ('k') | third_party/golang/src/fmt/print.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2009 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 fmt
6
7 import (
8 "math"
9 "strconv"
10 "unicode/utf8"
11 )
12
13 const (
14 // %b of an int64, plus a sign.
15 // Hex can add 0x and we handle it specially.
16 nByte = 65
17
18 ldigits = "0123456789abcdef"
19 udigits = "0123456789ABCDEF"
20 )
21
22 const (
23 signed = true
24 unsigned = false
25 )
26
27 var padZeroBytes = make([]byte, nByte)
28 var padSpaceBytes = make([]byte, nByte)
29
30 func init() {
31 for i := 0; i < nByte; i++ {
32 padZeroBytes[i] = '0'
33 padSpaceBytes[i] = ' '
34 }
35 }
36
37 // flags placed in a separate struct for easy clearing.
38 type fmtFlags struct {
39 widPresent bool
40 precPresent bool
41 minus bool
42 plus bool
43 sharp bool
44 space bool
45 unicode bool
46 uniQuote bool // Use 'x'= prefix for %U if printable.
47 zero bool
48
49 // For the formats %+v %#v, we set the plusV/sharpV flags
50 // and clear the plus/sharp flags since %+v and %#v are in effect
51 // different, flagless formats set at the top level.
52 plusV bool
53 sharpV bool
54 }
55
56 // A fmt is the raw formatter used by Printf etc.
57 // It prints into a buffer that must be set up separately.
58 type fmt struct {
59 intbuf [nByte]byte
60 buf *buffer
61 // width, precision
62 wid int
63 prec int
64 fmtFlags
65 }
66
67 func (f *fmt) clearflags() {
68 f.fmtFlags = fmtFlags{}
69 }
70
71 func (f *fmt) init(buf *buffer) {
72 f.buf = buf
73 f.clearflags()
74 }
75
76 // computePadding computes left and right padding widths (only one will be non-z ero).
77 func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth i nt) {
78 left := !f.minus
79 w := f.wid
80 if w < 0 {
81 left = false
82 w = -w
83 }
84 w -= width
85 if w > 0 {
86 if left && f.zero {
87 return padZeroBytes, w, 0
88 }
89 if left {
90 return padSpaceBytes, w, 0
91 } else {
92 // can't be zero padding on the right
93 return padSpaceBytes, 0, w
94 }
95 }
96 return
97 }
98
99 // writePadding generates n bytes of padding.
100 func (f *fmt) writePadding(n int, padding []byte) {
101 for n > 0 {
102 m := n
103 if m > nByte {
104 m = nByte
105 }
106 f.buf.Write(padding[0:m])
107 n -= m
108 }
109 }
110
111 // pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus).
112 func (f *fmt) pad(b []byte) {
113 if !f.widPresent || f.wid == 0 {
114 f.buf.Write(b)
115 return
116 }
117 padding, left, right := f.computePadding(utf8.RuneCount(b))
118 if left > 0 {
119 f.writePadding(left, padding)
120 }
121 f.buf.Write(b)
122 if right > 0 {
123 f.writePadding(right, padding)
124 }
125 }
126
127 // padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus ).
128 func (f *fmt) padString(s string) {
129 if !f.widPresent || f.wid == 0 {
130 f.buf.WriteString(s)
131 return
132 }
133 padding, left, right := f.computePadding(utf8.RuneCountInString(s))
134 if left > 0 {
135 f.writePadding(left, padding)
136 }
137 f.buf.WriteString(s)
138 if right > 0 {
139 f.writePadding(right, padding)
140 }
141 }
142
143 var (
144 trueBytes = []byte("true")
145 falseBytes = []byte("false")
146 )
147
148 // fmt_boolean formats a boolean.
149 func (f *fmt) fmt_boolean(v bool) {
150 if v {
151 f.pad(trueBytes)
152 } else {
153 f.pad(falseBytes)
154 }
155 }
156
157 // integer; interprets prec but not wid. Once formatted, result is sent to pad( )
158 // and then flags are cleared.
159 func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
160 // precision of 0 and value of 0 means "print nothing"
161 if f.precPresent && f.prec == 0 && a == 0 {
162 return
163 }
164
165 negative := signedness == signed && a < 0
166 if negative {
167 a = -a
168 }
169
170 var buf []byte = f.intbuf[0:]
171 if f.widPresent || f.precPresent || f.plus || f.space {
172 width := f.wid + f.prec // Only one will be set, both are positi ve; this provides the maximum.
173 if base == 16 && f.sharp {
174 // Also adds "0x".
175 width += 2
176 }
177 if f.unicode {
178 // Also adds "U+".
179 width += 2
180 if f.uniQuote {
181 // Also adds " 'x'".
182 width += 1 + 1 + utf8.UTFMax + 1
183 }
184 }
185 if negative || f.plus || f.space {
186 width++
187 }
188 if width > nByte {
189 // We're going to need a bigger boat.
190 buf = make([]byte, width)
191 }
192 }
193
194 // two ways to ask for extra leading zero digits: %.3d or %03d.
195 // apparently the first cancels the second.
196 prec := 0
197 if f.precPresent {
198 prec = f.prec
199 f.zero = false
200 } else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
201 prec = f.wid
202 if negative || f.plus || f.space {
203 prec-- // leave room for sign
204 }
205 }
206
207 // format a into buf, ending at buf[i]. (printing is easier right-to-le ft.)
208 // a is made into unsigned ua. we could make things
209 // marginally faster by splitting the 32-bit case out into a separate
210 // block but it's not worth the duplication, so ua has 64 bits.
211 i := len(buf)
212 ua := uint64(a)
213 // use constants for the division and modulo for more efficient code.
214 // switch cases ordered by popularity.
215 switch base {
216 case 10:
217 for ua >= 10 {
218 i--
219 next := ua / 10
220 buf[i] = byte('0' + ua - next*10)
221 ua = next
222 }
223 case 16:
224 for ua >= 16 {
225 i--
226 buf[i] = digits[ua&0xF]
227 ua >>= 4
228 }
229 case 8:
230 for ua >= 8 {
231 i--
232 buf[i] = byte('0' + ua&7)
233 ua >>= 3
234 }
235 case 2:
236 for ua >= 2 {
237 i--
238 buf[i] = byte('0' + ua&1)
239 ua >>= 1
240 }
241 default:
242 panic("fmt: unknown base; can't happen")
243 }
244 i--
245 buf[i] = digits[ua]
246 for i > 0 && prec > len(buf)-i {
247 i--
248 buf[i] = '0'
249 }
250
251 // Various prefixes: 0x, -, etc.
252 if f.sharp {
253 switch base {
254 case 8:
255 if buf[i] != '0' {
256 i--
257 buf[i] = '0'
258 }
259 case 16:
260 i--
261 buf[i] = 'x' + digits[10] - 'a'
262 i--
263 buf[i] = '0'
264 }
265 }
266 if f.unicode {
267 i--
268 buf[i] = '+'
269 i--
270 buf[i] = 'U'
271 }
272
273 if negative {
274 i--
275 buf[i] = '-'
276 } else if f.plus {
277 i--
278 buf[i] = '+'
279 } else if f.space {
280 i--
281 buf[i] = ' '
282 }
283
284 // If we want a quoted char for %#U, move the data up to make room.
285 if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsP rint(rune(a)) {
286 runeWidth := utf8.RuneLen(rune(a))
287 width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
288 copy(buf[i-width:], buf[i:]) // guaranteed to have enough room .
289 i -= width
290 // Now put " 'x'" at the end.
291 j := len(buf) - width
292 buf[j] = ' '
293 j++
294 buf[j] = '\''
295 j++
296 utf8.EncodeRune(buf[j:], rune(a))
297 j += runeWidth
298 buf[j] = '\''
299 }
300
301 f.pad(buf[i:])
302 }
303
304 // truncate truncates the string to the specified precision, if present.
305 func (f *fmt) truncate(s string) string {
306 if f.precPresent && f.prec < utf8.RuneCountInString(s) {
307 n := f.prec
308 for i := range s {
309 if n == 0 {
310 s = s[:i]
311 break
312 }
313 n--
314 }
315 }
316 return s
317 }
318
319 // fmt_s formats a string.
320 func (f *fmt) fmt_s(s string) {
321 s = f.truncate(s)
322 f.padString(s)
323 }
324
325 // fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes .
326 func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
327 n := len(b)
328 if b == nil {
329 n = len(s)
330 }
331 x := digits[10] - 'a' + 'x'
332 // TODO: Avoid buffer by pre-padding.
333 var buf []byte
334 for i := 0; i < n; i++ {
335 if i > 0 && f.space {
336 buf = append(buf, ' ')
337 }
338 if f.sharp && (f.space || i == 0) {
339 buf = append(buf, '0', x)
340 }
341 var c byte
342 if b == nil {
343 c = s[i]
344 } else {
345 c = b[i]
346 }
347 buf = append(buf, digits[c>>4], digits[c&0xF])
348 }
349 f.pad(buf)
350 }
351
352 // fmt_sx formats a string as a hexadecimal encoding of its bytes.
353 func (f *fmt) fmt_sx(s, digits string) {
354 if f.precPresent && f.prec < len(s) {
355 s = s[:f.prec]
356 }
357 f.fmt_sbx(s, nil, digits)
358 }
359
360 // fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
361 func (f *fmt) fmt_bx(b []byte, digits string) {
362 if f.precPresent && f.prec < len(b) {
363 b = b[:f.prec]
364 }
365 f.fmt_sbx("", b, digits)
366 }
367
368 // fmt_q formats a string as a double-quoted, escaped Go string constant.
369 func (f *fmt) fmt_q(s string) {
370 s = f.truncate(s)
371 var quoted string
372 if f.sharp && strconv.CanBackquote(s) {
373 quoted = "`" + s + "`"
374 } else {
375 if f.plus {
376 quoted = strconv.QuoteToASCII(s)
377 } else {
378 quoted = strconv.Quote(s)
379 }
380 }
381 f.padString(quoted)
382 }
383
384 // fmt_qc formats the integer as a single-quoted, escaped Go character constant.
385 // If the character is not valid Unicode, it will print '\ufffd'.
386 func (f *fmt) fmt_qc(c int64) {
387 var quoted []byte
388 if f.plus {
389 quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
390 } else {
391 quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
392 }
393 f.pad(quoted)
394 }
395
396 // floating-point
397
398 func doPrec(f *fmt, def int) int {
399 if f.precPresent {
400 return f.prec
401 }
402 return def
403 }
404
405 // formatFloat formats a float64; it is an efficient equivalent to f.pad(strcon v.FormatFloat()...).
406 func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
407 // Format number, reserving space for leading + sign if needed.
408 num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
409 if num[1] == '-' || num[1] == '+' {
410 num = num[1:]
411 } else {
412 num[0] = '+'
413 }
414 // Special handling for infinity, which doesn't look like a number so sh ouldn't be padded with zeros.
415 if math.IsInf(v, 0) {
416 if f.zero {
417 defer func() { f.zero = true }()
418 f.zero = false
419 }
420 }
421 // num is now a signed version of the number.
422 // If we're zero padding, want the sign before the leading zeros.
423 // Achieve this by writing the sign out and then padding the unsigned nu mber.
424 if f.zero && f.widPresent && f.wid > len(num) {
425 if f.space && v >= 0 {
426 f.buf.WriteByte(' ') // This is what C does: even with z ero, f.space means space.
427 f.wid--
428 } else if f.plus || v < 0 {
429 f.buf.WriteByte(num[0])
430 f.wid--
431 }
432 f.pad(num[1:])
433 return
434 }
435 // f.space says to replace a leading + with a space.
436 if f.space && num[0] == '+' {
437 num[0] = ' '
438 f.pad(num)
439 return
440 }
441 // Now we know the sign is attached directly to the number, if present a t all.
442 // We want a sign if asked for, if it's negative, or if it's infinity (+ Inf vs. -Inf).
443 if f.plus || num[0] == '-' || math.IsInf(v, 0) {
444 f.pad(num)
445 return
446 }
447 // No sign to show and the number is positive; just print the unsigned n umber.
448 f.pad(num[1:])
449 }
450
451 // fmt_e64 formats a float64 in the form -1.23e+12.
452 func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
453
454 // fmt_E64 formats a float64 in the form -1.23E+12.
455 func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
456
457 // fmt_f64 formats a float64 in the form -1.23.
458 func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
459
460 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
461 func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
462
463 // fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
464 func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
465
466 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
467 func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
468
469 // float32
470 // cannot defer to float64 versions
471 // because it will get rounding wrong in corner cases.
472
473 // fmt_e32 formats a float32 in the form -1.23e+12.
474 func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
475
476 // fmt_E32 formats a float32 in the form -1.23E+12.
477 func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
478
479 // fmt_f32 formats a float32 in the form -1.23.
480 func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
481
482 // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
483 func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
484
485 // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
486 func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
487
488 // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
489 func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
490
491 // fmt_c64 formats a complex64 according to the verb.
492 func (f *fmt) fmt_c64(v complex64, verb rune) {
493 f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb)
494 }
495
496 // fmt_c128 formats a complex128 according to the verb.
497 func (f *fmt) fmt_c128(v complex128, verb rune) {
498 f.fmt_complex(real(v), imag(v), 64, verb)
499 }
500
501 // fmt_complex formats a complex number as (r+ji).
502 func (f *fmt) fmt_complex(r, j float64, size int, verb rune) {
503 f.buf.WriteByte('(')
504 oldPlus := f.plus
505 oldSpace := f.space
506 oldWid := f.wid
507 for i := 0; ; i++ {
508 switch verb {
509 case 'b':
510 f.formatFloat(r, 'b', 0, size)
511 case 'e':
512 f.formatFloat(r, 'e', doPrec(f, 6), size)
513 case 'E':
514 f.formatFloat(r, 'E', doPrec(f, 6), size)
515 case 'f', 'F':
516 f.formatFloat(r, 'f', doPrec(f, 6), size)
517 case 'g':
518 f.formatFloat(r, 'g', doPrec(f, -1), size)
519 case 'G':
520 f.formatFloat(r, 'G', doPrec(f, -1), size)
521 }
522 if i != 0 {
523 break
524 }
525 // Imaginary part always has a sign.
526 f.plus = true
527 f.space = false
528 f.wid = oldWid
529 r = j
530 }
531 f.space = oldSpace
532 f.plus = oldPlus
533 f.wid = oldWid
534 f.buf.Write(irparenBytes)
535 }
OLDNEW
« no previous file with comments | « third_party/golang/README ('k') | third_party/golang/src/fmt/print.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698