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 := 1
350 if b[i] >= utf8.RuneSelf {
351 _, wid = utf8.DecodeRune(b[i:])
352 }
353 i += wid
354 }
355 }
356 return b
357 }
358
359
360 func (f *fmt) fmtS(s string) {
361 s = f.truncateString(s)
362 f.padString(s)
363 }
364
365
366 func (f *fmt) fmtBs(b []byte) {
367 b = f.truncate(b)
368 f.pad(b)
369 }
370
371
372 func (f *fmt) fmtSbx(s string, b []byte, digits string) {
373 length := len(b)
374 if b == nil {
375
376 length = len(s)
377 }
378
379 if f.precPresent && f.prec < length {
380 length = f.prec
381 }
382
383 width := 2 * length
384 if width > 0 {
385 if f.space {
386
387 if f.sharp {
388 width *= 2
389 }
390
391 width += length - 1
392 } else if f.sharp {
393
394 width += 2
395 }
396 } else {
397 if f.widPresent {
398 f.writePadding(f.wid)
399 }
400 return
401 }
402
403 if f.widPresent && f.wid > width && !f.minus {
404 f.writePadding(f.wid - width)
405 }
406
407 buf := *f.buf
408 if f.sharp {
409
410 buf = append(buf, '0', digits[16])
411 }
412 var c byte
413 for i := 0; i < length; i++ {
414 if f.space && i > 0 {
415
416 buf = append(buf, ' ')
417 if f.sharp {
418
419 buf = append(buf, '0', digits[16])
420 }
421 }
422 if b != nil {
423 c = b[i]
424 } else {
425 c = s[i]
426 }
427
428 buf = append(buf, digits[c>>4], digits[c&0xF])
429 }
430 *f.buf = buf
431
432 if f.widPresent && f.wid > width && f.minus {
433 f.writePadding(f.wid - width)
434 }
435 }
436
437
438 func (f *fmt) fmtSx(s, digits string) {
439 f.fmtSbx(s, nil, digits)
440 }
441
442
443 func (f *fmt) fmtBx(b []byte, digits string) {
444 f.fmtSbx("", b, digits)
445 }
446
447
448
449
450 func (f *fmt) fmtQ(s string) {
451 s = f.truncateString(s)
452 if f.sharp && strconv.CanBackquote(s) {
453 f.padString("`" + s + "`")
454 return
455 }
456 buf := f.intbuf[:0]
457 if f.plus {
458 f.pad(strconv.AppendQuoteToASCII(buf, s))
459 } else {
460 f.pad(strconv.AppendQuote(buf, s))
461 }
462 }
463
464
465
466 func (f *fmt) fmtC(c uint64) {
467
468
469 r := rune(c)
470 if c > utf8.MaxRune {
471 r = utf8.RuneError
472 }
473 buf := f.intbuf[:0]
474 f.pad(utf8.AppendRune(buf, r))
475 }
476
477
478
479 func (f *fmt) fmtQc(c uint64) {
480 r := rune(c)
481 if c > utf8.MaxRune {
482 r = utf8.RuneError
483 }
484 buf := f.intbuf[:0]
485 if f.plus {
486 f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
487 } else {
488 f.pad(strconv.AppendQuoteRune(buf, r))
489 }
490 }
491
492
493
494 func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
495
496 if f.precPresent {
497 prec = f.prec
498 }
499
500 num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
501 if num[1] == '-' || num[1] == '+' {
502 num = num[1:]
503 } else {
504 num[0] = '+'
505 }
506
507
508 if f.space && num[0] == '+' && !f.plus {
509 num[0] = ' '
510 }
511
512
513 if num[1] == 'I' || num[1] == 'N' {
514 oldZero := f.zero
515 f.zero = false
516
517 if num[1] == 'N' && !f.space && !f.plus {
518 num = num[1:]
519 }
520 f.pad(num)
521 f.zero = oldZero
522 return
523 }
524
525
526 if f.sharp && verb != 'b' {
527 digits := 0
528 switch verb {
529 case 'v', 'g', 'G', 'x':
530 digits = prec
531
532 if digits == -1 {
533 digits = 6
534 }
535 }
536
537
538
539 var tailBuf [6]byte
540 tail := tailBuf[:0]
541
542 hasDecimalPoint := false
543 sawNonzeroDigit := false
544
545 for i := 1; i < len(num); i++ {
546 switch num[i] {
547 case '.':
548 hasDecimalPoint = true
549 case 'p', 'P':
550 tail = append(tail, num[i:]...)
551 num = num[:i]
552 case 'e', 'E':
553 if verb != 'x' && verb != 'X' {
554 tail = append(tail, num[i:]...)
555 num = num[:i]
556 break
557 }
558 fallthrough
559 default:
560 if num[i] != '0' {
561 sawNonzeroDigit = true
562 }
563
564 if sawNonzeroDigit {
565 digits--
566 }
567 }
568 }
569 if !hasDecimalPoint {
570
571 if len(num) == 2 && num[1] == '0' {
572 digits--
573 }
574 num = append(num, '.')
575 }
576 for digits > 0 {
577 num = append(num, '0')
578 digits--
579 }
580 num = append(num, tail...)
581 }
582
583 if f.plus || num[0] != '+' {
584
585
586
587 if f.zero && !f.minus && f.widPresent && f.wid > len(num) {
588 f.buf.writeByte(num[0])
589 f.writePadding(f.wid - len(num))
590 f.buf.write(num[1:])
591 return
592 }
593 f.pad(num)
594 return
595 }
596
597 f.pad(num[1:])
598 }
599
View as plain text