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 r := rune(c)
465 if c > utf8.MaxRune {
466 r = utf8.RuneError
467 }
468 buf := f.intbuf[:0]
469 w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
470 f.pad(buf[:w])
471 }
472
473
474
475 func (f *fmt) fmtQc(c uint64) {
476 r := rune(c)
477 if c > utf8.MaxRune {
478 r = utf8.RuneError
479 }
480 buf := f.intbuf[:0]
481 if f.plus {
482 f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
483 } else {
484 f.pad(strconv.AppendQuoteRune(buf, r))
485 }
486 }
487
488
489
490 func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
491
492 if f.precPresent {
493 prec = f.prec
494 }
495
496 num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
497 if num[1] == '-' || num[1] == '+' {
498 num = num[1:]
499 } else {
500 num[0] = '+'
501 }
502
503
504 if f.space && num[0] == '+' && !f.plus {
505 num[0] = ' '
506 }
507
508
509 if num[1] == 'I' || num[1] == 'N' {
510 oldZero := f.zero
511 f.zero = false
512
513 if num[1] == 'N' && !f.space && !f.plus {
514 num = num[1:]
515 }
516 f.pad(num)
517 f.zero = oldZero
518 return
519 }
520
521
522 if f.sharp && verb != 'b' {
523 digits := 0
524 switch verb {
525 case 'v', 'g', 'G', 'x':
526 digits = prec
527
528 if digits == -1 {
529 digits = 6
530 }
531 }
532
533
534
535 var tailBuf [6]byte
536 tail := tailBuf[:0]
537
538 hasDecimalPoint := false
539 sawNonzeroDigit := false
540
541 for i := 1; i < len(num); i++ {
542 switch num[i] {
543 case '.':
544 hasDecimalPoint = true
545 case 'p', 'P':
546 tail = append(tail, num[i:]...)
547 num = num[:i]
548 case 'e', 'E':
549 if verb != 'x' && verb != 'X' {
550 tail = append(tail, num[i:]...)
551 num = num[:i]
552 break
553 }
554 fallthrough
555 default:
556 if num[i] != '0' {
557 sawNonzeroDigit = true
558 }
559
560 if sawNonzeroDigit {
561 digits--
562 }
563 }
564 }
565 if !hasDecimalPoint {
566
567 if len(num) == 2 && num[1] == '0' {
568 digits--
569 }
570 num = append(num, '.')
571 }
572 for digits > 0 {
573 num = append(num, '0')
574 digits--
575 }
576 num = append(num, tail...)
577 }
578
579 if f.plus || num[0] != '+' {
580
581
582 if f.zero && f.widPresent && f.wid > len(num) {
583 f.buf.writeByte(num[0])
584 f.writePadding(f.wid - len(num))
585 f.buf.write(num[1:])
586 return
587 }
588 f.pad(num)
589 return
590 }
591
592 f.pad(num[1:])
593 }
594
View as plain text