Source file
src/fmt/format.go
Documentation: fmt
1
2
3
4
5 package fmt
6
7 import (
8 "strconv"
9 "unicode/utf8"
10 )
11
12 const (
13 ldigits = "0123456789abcdefx"
14 udigits = "0123456789ABCDEFX"
15 )
16
17 const (
18 signed = true
19 unsigned = false
20 )
21
22
23 type fmtFlags struct {
24 widPresent bool
25 precPresent bool
26 minus bool
27 plus bool
28 sharp bool
29 space bool
30 zero bool
31
32
33
34
35 plusV bool
36 sharpV bool
37 }
38
39
40
41 type fmt struct {
42 buf *buffer
43
44 fmtFlags
45
46 wid int
47 prec int
48
49
50
51 intbuf [68]byte
52 }
53
54 func (f *fmt) clearflags() {
55 f.fmtFlags = fmtFlags{}
56 }
57
58 func (f *fmt) init(buf *buffer) {
59 f.buf = buf
60 f.clearflags()
61 }
62
63
64 func (f *fmt) writePadding(n int) {
65 if n <= 0 {
66 return
67 }
68 buf := *f.buf
69 oldLen := len(buf)
70 newLen := oldLen + n
71
72 if newLen > cap(buf) {
73 buf = make(buffer, cap(buf)*2+n)
74 copy(buf, *f.buf)
75 }
76
77 padByte := byte(' ')
78 if f.zero {
79 padByte = byte('0')
80 }
81
82 padding := buf[oldLen:newLen]
83 for i := range padding {
84 padding[i] = padByte
85 }
86 *f.buf = buf[:newLen]
87 }
88
89
90 func (f *fmt) pad(b []byte) {
91 if !f.widPresent || f.wid == 0 {
92 f.buf.write(b)
93 return
94 }
95 width := f.wid - utf8.RuneCount(b)
96 if !f.minus {
97
98 f.writePadding(width)
99 f.buf.write(b)
100 } else {
101
102 f.buf.write(b)
103 f.writePadding(width)
104 }
105 }
106
107
108 func (f *fmt) padString(s string) {
109 if !f.widPresent || f.wid == 0 {
110 f.buf.writeString(s)
111 return
112 }
113 width := f.wid - utf8.RuneCountInString(s)
114 if !f.minus {
115
116 f.writePadding(width)
117 f.buf.writeString(s)
118 } else {
119
120 f.buf.writeString(s)
121 f.writePadding(width)
122 }
123 }
124
125
126 func (f *fmt) fmtBoolean(v bool) {
127 if v {
128 f.padString("true")
129 } else {
130 f.padString("false")
131 }
132 }
133
134
135 func (f *fmt) fmtUnicode(u uint64) {
136 buf := f.intbuf[0:]
137
138
139
140
141 prec := 4
142 if f.precPresent && f.prec > 4 {
143 prec = f.prec
144
145 width := 2 + prec + 2 + utf8.UTFMax + 1
146 if width > len(buf) {
147 buf = make([]byte, width)
148 }
149 }
150
151
152 i := len(buf)
153
154
155 if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
156 i--
157 buf[i] = '\''
158 i -= utf8.RuneLen(rune(u))
159 utf8.EncodeRune(buf[i:], rune(u))
160 i--
161 buf[i] = '\''
162 i--
163 buf[i] = ' '
164 }
165
166 for u >= 16 {
167 i--
168 buf[i] = udigits[u&0xF]
169 prec--
170 u >>= 4
171 }
172 i--
173 buf[i] = udigits[u]
174 prec--
175
176 for prec > 0 {
177 i--
178 buf[i] = '0'
179 prec--
180 }
181
182 i--
183 buf[i] = '+'
184 i--
185 buf[i] = 'U'
186
187 oldZero := f.zero
188 f.zero = false
189 f.pad(buf[i:])
190 f.zero = oldZero
191 }
192
193
194 func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits string) {
195 negative := isSigned && int64(u) < 0
196 if negative {
197 u = -u
198 }
199
200 buf := f.intbuf[0:]
201
202
203 if f.widPresent || f.precPresent {
204
205 width := 3 + f.wid + f.prec
206 if width > len(buf) {
207
208 buf = make([]byte, width)
209 }
210 }
211
212
213
214
215 prec := 0
216 if f.precPresent {
217 prec = f.prec
218
219 if prec == 0 && u == 0 {
220 oldZero := f.zero
221 f.zero = false
222 f.writePadding(f.wid)
223 f.zero = oldZero
224 return
225 }
226 } else if f.zero && f.widPresent {
227 prec = f.wid
228 if negative || f.plus || f.space {
229 prec--
230 }
231 }
232
233
234
235
236 i := len(buf)
237
238
239 switch base {
240 case 10:
241 for u >= 10 {
242 i--
243 next := u / 10
244 buf[i] = byte('0' + u - next*10)
245 u = next
246 }
247 case 16:
248 for u >= 16 {
249 i--
250 buf[i] = digits[u&0xF]
251 u >>= 4
252 }
253 case 8:
254 for u >= 8 {
255 i--
256 buf[i] = byte('0' + u&7)
257 u >>= 3
258 }
259 case 2:
260 for u >= 2 {
261 i--
262 buf[i] = byte('0' + u&1)
263 u >>= 1
264 }
265 default:
266 panic("fmt: unknown base; can't happen")
267 }
268 i--
269 buf[i] = digits[u]
270 for i > 0 && prec > len(buf)-i {
271 i--
272 buf[i] = '0'
273 }
274
275
276 if f.sharp {
277 switch base {
278 case 2:
279
280 i--
281 buf[i] = 'b'
282 i--
283 buf[i] = '0'
284 case 8:
285 if buf[i] != '0' {
286 i--
287 buf[i] = '0'
288 }
289 case 16:
290
291 i--
292 buf[i] = digits[16]
293 i--
294 buf[i] = '0'
295 }
296 }
297 if verb == 'O' {
298 i--
299 buf[i] = 'o'
300 i--
301 buf[i] = '0'
302 }
303
304 if negative {
305 i--
306 buf[i] = '-'
307 } else if f.plus {
308 i--
309 buf[i] = '+'
310 } else if f.space {
311 i--
312 buf[i] = ' '
313 }
314
315
316
317 oldZero := f.zero
318 f.zero = false
319 f.pad(buf[i:])
320 f.zero = oldZero
321 }
322
323
324 func (f *fmt) truncateString(s string) string {
325 if f.precPresent {
326 n := f.prec
327 for i := range s {
328 n--
329 if n < 0 {
330 return s[:i]
331 }
332 }
333 }
334 return s
335 }
336
337
338 func (f *fmt) truncate(b []byte) []byte {
339 if f.precPresent {
340 n := f.prec
341 for i := 0; i < len(b); {
342 n--
343 if n < 0 {
344 return b[:i]
345 }
346 wid := 1
347 if b[i] >= utf8.RuneSelf {
348 _, wid = utf8.DecodeRune(b[i:])
349 }
350 i += wid
351 }
352 }
353 return b
354 }
355
356
357 func (f *fmt) fmtS(s string) {
358 s = f.truncateString(s)
359 f.padString(s)
360 }
361
362
363 func (f *fmt) fmtBs(b []byte) {
364 b = f.truncate(b)
365 f.pad(b)
366 }
367
368
369 func (f *fmt) fmtSbx(s string, b []byte, digits string) {
370 length := len(b)
371 if b == nil {
372
373 length = len(s)
374 }
375
376 if f.precPresent && f.prec < length {
377 length = f.prec
378 }
379
380 width := 2 * length
381 if width > 0 {
382 if f.space {
383
384 if f.sharp {
385 width *= 2
386 }
387
388 width += length - 1
389 } else if f.sharp {
390
391 width += 2
392 }
393 } else {
394 if f.widPresent {
395 f.writePadding(f.wid)
396 }
397 return
398 }
399
400 if f.widPresent && f.wid > width && !f.minus {
401 f.writePadding(f.wid - width)
402 }
403
404 buf := *f.buf
405 if f.sharp {
406
407 buf = append(buf, '0', digits[16])
408 }
409 var c byte
410 for i := 0; i < length; i++ {
411 if f.space && i > 0 {
412
413 buf = append(buf, ' ')
414 if f.sharp {
415
416 buf = append(buf, '0', digits[16])
417 }
418 }
419 if b != nil {
420 c = b[i]
421 } else {
422 c = s[i]
423 }
424
425 buf = append(buf, digits[c>>4], digits[c&0xF])
426 }
427 *f.buf = buf
428
429 if f.widPresent && f.wid > width && f.minus {
430 f.writePadding(f.wid - width)
431 }
432 }
433
434
435 func (f *fmt) fmtSx(s, digits string) {
436 f.fmtSbx(s, nil, digits)
437 }
438
439
440 func (f *fmt) fmtBx(b []byte, digits string) {
441 f.fmtSbx("", b, digits)
442 }
443
444
445
446
447 func (f *fmt) fmtQ(s string) {
448 s = f.truncateString(s)
449 if f.sharp && strconv.CanBackquote(s) {
450 f.padString("`" + s + "`")
451 return
452 }
453 buf := f.intbuf[:0]
454 if f.plus {
455 f.pad(strconv.AppendQuoteToASCII(buf, s))
456 } else {
457 f.pad(strconv.AppendQuote(buf, s))
458 }
459 }
460
461
462
463 func (f *fmt) fmtC(c uint64) {
464
465
466 r := rune(c)
467 if c > utf8.MaxRune {
468 r = utf8.RuneError
469 }
470 buf := f.intbuf[:0]
471 f.pad(utf8.AppendRune(buf, r))
472 }
473
474
475
476 func (f *fmt) fmtQc(c uint64) {
477 r := rune(c)
478 if c > utf8.MaxRune {
479 r = utf8.RuneError
480 }
481 buf := f.intbuf[:0]
482 if f.plus {
483 f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
484 } else {
485 f.pad(strconv.AppendQuoteRune(buf, r))
486 }
487 }
488
489
490
491 func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
492
493 if f.precPresent {
494 prec = f.prec
495 }
496
497 num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
498 if num[1] == '-' || num[1] == '+' {
499 num = num[1:]
500 } else {
501 num[0] = '+'
502 }
503
504
505 if f.space && num[0] == '+' && !f.plus {
506 num[0] = ' '
507 }
508
509
510 if num[1] == 'I' || num[1] == 'N' {
511 oldZero := f.zero
512 f.zero = false
513
514 if num[1] == 'N' && !f.space && !f.plus {
515 num = num[1:]
516 }
517 f.pad(num)
518 f.zero = oldZero
519 return
520 }
521
522
523 if f.sharp && verb != 'b' {
524 digits := 0
525 switch verb {
526 case 'v', 'g', 'G', 'x':
527 digits = prec
528
529 if digits == -1 {
530 digits = 6
531 }
532 }
533
534
535
536 var tailBuf [6]byte
537 tail := tailBuf[:0]
538
539 hasDecimalPoint := false
540 sawNonzeroDigit := false
541
542 for i := 1; i < len(num); i++ {
543 switch num[i] {
544 case '.':
545 hasDecimalPoint = true
546 case 'p', 'P':
547 tail = append(tail, num[i:]...)
548 num = num[:i]
549 case 'e', 'E':
550 if verb != 'x' && verb != 'X' {
551 tail = append(tail, num[i:]...)
552 num = num[:i]
553 break
554 }
555 fallthrough
556 default:
557 if num[i] != '0' {
558 sawNonzeroDigit = true
559 }
560
561 if sawNonzeroDigit {
562 digits--
563 }
564 }
565 }
566 if !hasDecimalPoint {
567
568 if len(num) == 2 && num[1] == '0' {
569 digits--
570 }
571 num = append(num, '.')
572 }
573 for digits > 0 {
574 num = append(num, '0')
575 digits--
576 }
577 num = append(num, tail...)
578 }
579
580 if f.plus || num[0] != '+' {
581
582
583 if f.zero && f.widPresent && f.wid > len(num) {
584 f.buf.writeByte(num[0])
585 f.writePadding(f.wid - len(num))
586 f.buf.write(num[1:])
587 return
588 }
589 f.pad(num)
590 return
591 }
592
593 f.pad(num[1:])
594 }
595
View as plain text