Source file
src/fmt/format.go
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 f.wid = 0
57 f.prec = 0
58 }
59
60 func (f *fmt) init(buf *buffer) {
61 f.buf = buf
62 f.clearflags()
63 }
64
65
66 func (f *fmt) writePadding(n int) {
67 if n <= 0 {
68 return
69 }
70 buf := *f.buf
71 oldLen := len(buf)
72 newLen := oldLen + n
73
74 if newLen > cap(buf) {
75 buf = make(buffer, cap(buf)*2+n)
76 copy(buf, *f.buf)
77 }
78
79 padByte := byte(' ')
80
81 if f.zero && !f.minus {
82 padByte = byte('0')
83 }
84
85 padding := buf[oldLen:newLen]
86 for i := range padding {
87 padding[i] = padByte
88 }
89 *f.buf = buf[:newLen]
90 }
91
92
93 func (f *fmt) pad(b []byte) {
94 if !f.widPresent || f.wid == 0 {
95 f.buf.write(b)
96 return
97 }
98 width := f.wid - utf8.RuneCount(b)
99 if !f.minus {
100
101 f.writePadding(width)
102 f.buf.write(b)
103 } else {
104
105 f.buf.write(b)
106 f.writePadding(width)
107 }
108 }
109
110
111 func (f *fmt) padString(s string) {
112 if !f.widPresent || f.wid == 0 {
113 f.buf.writeString(s)
114 return
115 }
116 width := f.wid - utf8.RuneCountInString(s)
117 if !f.minus {
118
119 f.writePadding(width)
120 f.buf.writeString(s)
121 } else {
122
123 f.buf.writeString(s)
124 f.writePadding(width)
125 }
126 }
127
128
129 func (f *fmt) fmtBoolean(v bool) {
130 if v {
131 f.padString("true")
132 } else {
133 f.padString("false")
134 }
135 }
136
137
138 func (f *fmt) fmtUnicode(u uint64) {
139 buf := f.intbuf[0:]
140
141
142
143
144 prec := 4
145 if f.precPresent && f.prec > 4 {
146 prec = f.prec
147
148 width := 2 + prec + 2 + utf8.UTFMax + 1
149 if width > len(buf) {
150 buf = make([]byte, width)
151 }
152 }
153
154
155 i := len(buf)
156
157
158 if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
159 i--
160 buf[i] = '\''
161 i -= utf8.RuneLen(rune(u))
162 utf8.EncodeRune(buf[i:], rune(u))
163 i--
164 buf[i] = '\''
165 i--
166 buf[i] = ' '
167 }
168
169 for u >= 16 {
170 i--
171 buf[i] = udigits[u&0xF]
172 prec--
173 u >>= 4
174 }
175 i--
176 buf[i] = udigits[u]
177 prec--
178
179 for prec > 0 {
180 i--
181 buf[i] = '0'
182 prec--
183 }
184
185 i--
186 buf[i] = '+'
187 i--
188 buf[i] = 'U'
189
190 oldZero := f.zero
191 f.zero = false
192 f.pad(buf[i:])
193 f.zero = oldZero
194 }
195
196
197 func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits string) {
198 negative := isSigned && int64(u) < 0
199 if negative {
200 u = -u
201 }
202
203 buf := f.intbuf[0:]
204
205
206 if f.widPresent || f.precPresent {
207
208 width := 3 + f.wid + f.prec
209 if width > len(buf) {
210
211 buf = make([]byte, width)
212 }
213 }
214
215
216
217
218 prec := 0
219 if f.precPresent {
220 prec = f.prec
221
222 if prec == 0 && u == 0 {
223 oldZero := f.zero
224 f.zero = false
225 f.writePadding(f.wid)
226 f.zero = oldZero
227 return
228 }
229 } else if f.zero && !f.minus && f.widPresent {
230 prec = f.wid
231 if negative || f.plus || f.space {
232 prec--
233 }
234 }
235
236
237
238
239 i := len(buf)
240
241
242 switch base {
243 case 10:
244 for u >= 10 {
245 i--
246 next := u / 10
247 buf[i] = byte('0' + u - next*10)
248 u = next
249 }
250 case 16:
251 for u >= 16 {
252 i--
253 buf[i] = digits[u&0xF]
254 u >>= 4
255 }
256 case 8:
257 for u >= 8 {
258 i--
259 buf[i] = byte('0' + u&7)
260 u >>= 3
261 }
262 case 2:
263 for u >= 2 {
264 i--
265 buf[i] = byte('0' + u&1)
266 u >>= 1
267 }
268 default:
269 panic("fmt: unknown base; can't happen")
270 }
271 i--
272 buf[i] = digits[u]
273 for i > 0 && prec > len(buf)-i {
274 i--
275 buf[i] = '0'
276 }
277
278
279 if f.sharp {
280 switch base {
281 case 2:
282
283 i--
284 buf[i] = 'b'
285 i--
286 buf[i] = '0'
287 case 8:
288 if buf[i] != '0' {
289 i--
290 buf[i] = '0'
291 }
292 case 16:
293
294 i--
295 buf[i] = digits[16]
296 i--
297 buf[i] = '0'
298 }
299 }
300 if verb == 'O' {
301 i--
302 buf[i] = 'o'
303 i--
304 buf[i] = '0'
305 }
306
307 if negative {
308 i--
309 buf[i] = '-'
310 } else if f.plus {
311 i--
312 buf[i] = '+'
313 } else if f.space {
314 i--
315 buf[i] = ' '
316 }
317
318
319
320 oldZero := f.zero
321 f.zero = false
322 f.pad(buf[i:])
323 f.zero = oldZero
324 }
325
326
327 func (f *fmt) truncateString(s string) string {
328 if f.precPresent {
329 n := f.prec
330 for i := range s {
331 n--
332 if n < 0 {
333 return s[:i]
334 }
335 }
336 }
337 return s
338 }
339
340
341 func (f *fmt) truncate(b []byte) []byte {
342 if f.precPresent {
343 n := f.prec
344 for i := 0; i < len(b); {
345 n--
346 if n < 0 {
347 return b[:i]
348 }
349 _, wid := utf8.DecodeRune(b[i:])
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
584 if f.zero && !f.minus && f.widPresent && f.wid > len(num) {
585 f.buf.writeByte(num[0])
586 f.writePadding(f.wid - len(num))
587 f.buf.write(num[1:])
588 return
589 }
590 f.pad(num)
591 return
592 }
593
594 f.pad(num[1:])
595 }
596
View as plain text