...
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) fmt_boolean(v bool) {
127 if v {
128 f.padString("true")
129 } else {
130 f.padString("false")
131 }
132 }
133
134
135 func (f *fmt) fmt_unicode(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) fmt_integer(u uint64, base int, isSigned bool, 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 8:
279 if buf[i] != '0' {
280 i--
281 buf[i] = '0'
282 }
283 case 16:
284
285 i--
286 buf[i] = digits[16]
287 i--
288 buf[i] = '0'
289 }
290 }
291
292 if negative {
293 i--
294 buf[i] = '-'
295 } else if f.plus {
296 i--
297 buf[i] = '+'
298 } else if f.space {
299 i--
300 buf[i] = ' '
301 }
302
303
304
305 oldZero := f.zero
306 f.zero = false
307 f.pad(buf[i:])
308 f.zero = oldZero
309 }
310
311
312 func (f *fmt) truncate(s string) string {
313 if f.precPresent {
314 n := f.prec
315 for i := range s {
316 n--
317 if n < 0 {
318 return s[:i]
319 }
320 }
321 }
322 return s
323 }
324
325
326 func (f *fmt) fmt_s(s string) {
327 s = f.truncate(s)
328 f.padString(s)
329 }
330
331
332 func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
333 length := len(b)
334 if b == nil {
335
336 length = len(s)
337 }
338
339 if f.precPresent && f.prec < length {
340 length = f.prec
341 }
342
343 width := 2 * length
344 if width > 0 {
345 if f.space {
346
347 if f.sharp {
348 width *= 2
349 }
350
351 width += length - 1
352 } else if f.sharp {
353
354 width += 2
355 }
356 } else {
357 if f.widPresent {
358 f.writePadding(f.wid)
359 }
360 return
361 }
362
363 if f.widPresent && f.wid > width && !f.minus {
364 f.writePadding(f.wid - width)
365 }
366
367 buf := *f.buf
368 if f.sharp {
369
370 buf = append(buf, '0', digits[16])
371 }
372 var c byte
373 for i := 0; i < length; i++ {
374 if f.space && i > 0 {
375
376 buf = append(buf, ' ')
377 if f.sharp {
378
379 buf = append(buf, '0', digits[16])
380 }
381 }
382 if b != nil {
383 c = b[i]
384 } else {
385 c = s[i]
386 }
387
388 buf = append(buf, digits[c>>4], digits[c&0xF])
389 }
390 *f.buf = buf
391
392 if f.widPresent && f.wid > width && f.minus {
393 f.writePadding(f.wid - width)
394 }
395 }
396
397
398 func (f *fmt) fmt_sx(s, digits string) {
399 f.fmt_sbx(s, nil, digits)
400 }
401
402
403 func (f *fmt) fmt_bx(b []byte, digits string) {
404 f.fmt_sbx("", b, digits)
405 }
406
407
408
409
410 func (f *fmt) fmt_q(s string) {
411 s = f.truncate(s)
412 if f.sharp && strconv.CanBackquote(s) {
413 f.padString("`" + s + "`")
414 return
415 }
416 buf := f.intbuf[:0]
417 if f.plus {
418 f.pad(strconv.AppendQuoteToASCII(buf, s))
419 } else {
420 f.pad(strconv.AppendQuote(buf, s))
421 }
422 }
423
424
425
426 func (f *fmt) fmt_c(c uint64) {
427 r := rune(c)
428 if c > utf8.MaxRune {
429 r = utf8.RuneError
430 }
431 buf := f.intbuf[:0]
432 w := utf8.EncodeRune(buf[:utf8.UTFMax], r)
433 f.pad(buf[:w])
434 }
435
436
437
438 func (f *fmt) fmt_qc(c uint64) {
439 r := rune(c)
440 if c > utf8.MaxRune {
441 r = utf8.RuneError
442 }
443 buf := f.intbuf[:0]
444 if f.plus {
445 f.pad(strconv.AppendQuoteRuneToASCII(buf, r))
446 } else {
447 f.pad(strconv.AppendQuoteRune(buf, r))
448 }
449 }
450
451
452
453 func (f *fmt) fmt_float(v float64, size int, verb rune, prec int) {
454
455 if f.precPresent {
456 prec = f.prec
457 }
458
459 num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size)
460 if num[1] == '-' || num[1] == '+' {
461 num = num[1:]
462 } else {
463 num[0] = '+'
464 }
465
466
467 if f.space && num[0] == '+' && !f.plus {
468 num[0] = ' '
469 }
470
471
472 if num[1] == 'I' || num[1] == 'N' {
473 oldZero := f.zero
474 f.zero = false
475
476 if num[1] == 'N' && !f.space && !f.plus {
477 num = num[1:]
478 }
479 f.pad(num)
480 f.zero = oldZero
481 return
482 }
483
484
485 if f.sharp && verb != 'b' {
486 digits := 0
487 switch verb {
488 case 'v', 'g', 'G':
489 digits = prec
490
491 if digits == -1 {
492 digits = 6
493 }
494 }
495
496
497
498 var tailBuf [5]byte
499 tail := tailBuf[:0]
500
501 hasDecimalPoint := false
502
503 for i := 1; i < len(num); i++ {
504 switch num[i] {
505 case '.':
506 hasDecimalPoint = true
507 case 'e', 'E':
508 tail = append(tail, num[i:]...)
509 num = num[:i]
510 default:
511 digits--
512 }
513 }
514 if !hasDecimalPoint {
515 num = append(num, '.')
516 }
517 for digits > 0 {
518 num = append(num, '0')
519 digits--
520 }
521 num = append(num, tail...)
522 }
523
524 if f.plus || num[0] != '+' {
525
526
527 if f.zero && f.widPresent && f.wid > len(num) {
528 f.buf.WriteByte(num[0])
529 f.writePadding(f.wid - len(num))
530 f.buf.Write(num[1:])
531 return
532 }
533 f.pad(num)
534 return
535 }
536
537 f.pad(num[1:])
538 }
539
View as plain text