blob: 517b18f7d4378e3c60bc3f9c123d10273d42a2ac [file] [log] [blame]
Rob Pike42d78502008-03-27 00:06:21 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package fmt
6
Russ Cox387df5e2008-11-24 14:51:33 -08007import (
Rob Pike4464ae22014-05-21 12:30:43 -07008 "math"
Robert Griesemer1c729592009-12-15 15:27:16 -08009 "strconv"
Rob Pike30aa7012011-11-08 15:40:58 -080010 "unicode/utf8"
Russ Cox387df5e2008-11-24 14:51:33 -080011)
Russ Cox079c00a2008-11-17 12:34:03 -080012
Rob Piked984f982009-12-03 00:04:40 -080013const (
Rob Pikefc908a02014-01-16 09:48:23 -080014 // %b of an int64, plus a sign.
15 // Hex can add 0x and we handle it specially.
16 nByte = 65
Rob Pike42d78502008-03-27 00:06:21 -070017
Robert Griesemer1c729592009-12-15 15:27:16 -080018 ldigits = "0123456789abcdef"
19 udigits = "0123456789ABCDEF"
Rob Piked984f982009-12-03 00:04:40 -080020)
Rob Pike655c2812008-07-08 14:20:04 -070021
Rob Pikef91cd442009-12-06 15:01:07 -080022const (
Robert Griesemer1c729592009-12-15 15:27:16 -080023 signed = true
24 unsigned = false
Rob Pikef91cd442009-12-06 15:01:07 -080025)
26
Rob Pike4c0e51c2009-12-06 12:03:52 -080027var padZeroBytes = make([]byte, nByte)
28var padSpaceBytes = make([]byte, nByte)
29
Rob Piked984f982009-12-03 00:04:40 -080030func init() {
Rob Pike4c0e51c2009-12-06 12:03:52 -080031 for i := 0; i < nByte; i++ {
Robert Griesemer1c729592009-12-15 15:27:16 -080032 padZeroBytes[i] = '0'
33 padSpaceBytes[i] = ' '
Rob Piked984f982009-12-03 00:04:40 -080034 }
35}
Rob Pikeacf3d592008-07-19 14:52:01 -070036
Rob Pikea2242452014-10-03 13:23:35 -070037// flags placed in a separate struct for easy clearing.
38type fmtFlags struct {
39 widPresent bool
40 precPresent bool
41 minus bool
42 plus bool
43 sharp bool
44 space bool
45 unicode bool
46 uniQuote bool // Use 'x'= prefix for %U if printable.
47 zero bool
48
49 // For the formats %+v %#v, we set the plusV/sharpV flags
50 // and clear the plus/sharp flags since %+v and %#v are in effect
51 // different, flagless formats set at the top level.
52 plusV bool
53 sharpV bool
54}
55
Rob Pike353ef802009-12-06 12:58:16 -080056// A fmt is the raw formatter used by Printf etc.
Russ Cox0bc18812012-03-06 23:27:11 -050057// It prints into a buffer that must be set up separately.
Rob Pike353ef802009-12-06 12:58:16 -080058type fmt struct {
Robert Griesemer1c729592009-12-15 15:27:16 -080059 intbuf [nByte]byte
Russ Cox0bc18812012-03-06 23:27:11 -050060 buf *buffer
Rob Pikef91cd442009-12-06 15:01:07 -080061 // width, precision
Robert Griesemer1c729592009-12-15 15:27:16 -080062 wid int
63 prec int
Rob Pikea2242452014-10-03 13:23:35 -070064 fmtFlags
Rob Pike42d78502008-03-27 00:06:21 -070065}
66
Rob Pike353ef802009-12-06 12:58:16 -080067func (f *fmt) clearflags() {
Rob Pikea2242452014-10-03 13:23:35 -070068 f.fmtFlags = fmtFlags{}
Rob Pike42d78502008-03-27 00:06:21 -070069}
70
Russ Cox0bc18812012-03-06 23:27:11 -050071func (f *fmt) init(buf *buffer) {
Robert Griesemer1c729592009-12-15 15:27:16 -080072 f.buf = buf
73 f.clearflags()
Rob Pike4c0e51c2009-12-06 12:03:52 -080074}
75
Robin Eklind3692dfd2013-01-22 17:12:45 -050076// computePadding computes left and right padding widths (only one will be non-zero).
Rob Pike353ef802009-12-06 12:58:16 -080077func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
Robert Griesemer1c729592009-12-15 15:27:16 -080078 left := !f.minus
79 w := f.wid
Rob Pike4c0e51c2009-12-06 12:03:52 -080080 if w < 0 {
Robert Griesemer1c729592009-12-15 15:27:16 -080081 left = false
82 w = -w
Rob Pike4c0e51c2009-12-06 12:03:52 -080083 }
Robert Griesemer1c729592009-12-15 15:27:16 -080084 w -= width
Rob Pike4c0e51c2009-12-06 12:03:52 -080085 if w > 0 {
86 if left && f.zero {
87 return padZeroBytes, w, 0
88 }
89 if left {
90 return padSpaceBytes, w, 0
91 } else {
92 // can't be zero padding on the right
93 return padSpaceBytes, 0, w
94 }
95 }
Robert Griesemer1c729592009-12-15 15:27:16 -080096 return
Rob Pike4c0e51c2009-12-06 12:03:52 -080097}
98
Robin Eklind3692dfd2013-01-22 17:12:45 -050099// writePadding generates n bytes of padding.
Rob Pike353ef802009-12-06 12:58:16 -0800100func (f *fmt) writePadding(n int, padding []byte) {
Rob Pike4c0e51c2009-12-06 12:03:52 -0800101 for n > 0 {
Robert Griesemer1c729592009-12-15 15:27:16 -0800102 m := n
Rob Pike4c0e51c2009-12-06 12:03:52 -0800103 if m > nByte {
104 m = nByte
105 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800106 f.buf.Write(padding[0:m])
107 n -= m
Rob Pike4c0e51c2009-12-06 12:03:52 -0800108 }
109}
110
Robin Eklind3692dfd2013-01-22 17:12:45 -0500111// pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus).
Rob Pikef91cd442009-12-06 15:01:07 -0800112func (f *fmt) pad(b []byte) {
Rob Pike53bc1942012-05-29 15:08:08 -0700113 if !f.widPresent || f.wid == 0 {
114 f.buf.Write(b)
115 return
Rob Pike4c0e51c2009-12-06 12:03:52 -0800116 }
Mihai Boroboceabfdeb572014-07-29 16:46:53 -0700117 padding, left, right := f.computePadding(utf8.RuneCount(b))
Rob Pike4c0e51c2009-12-06 12:03:52 -0800118 if left > 0 {
119 f.writePadding(left, padding)
120 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800121 f.buf.Write(b)
Rob Pike4c0e51c2009-12-06 12:03:52 -0800122 if right > 0 {
123 f.writePadding(right, padding)
124 }
Rob Pike42d78502008-03-27 00:06:21 -0700125}
126
Robin Eklind3692dfd2013-01-22 17:12:45 -0500127// padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
Rob Pikef91cd442009-12-06 15:01:07 -0800128func (f *fmt) padString(s string) {
Rob Pike53bc1942012-05-29 15:08:08 -0700129 if !f.widPresent || f.wid == 0 {
130 f.buf.WriteString(s)
131 return
Rob Pike42d78502008-03-27 00:06:21 -0700132 }
Rob Pike53bc1942012-05-29 15:08:08 -0700133 padding, left, right := f.computePadding(utf8.RuneCountInString(s))
Rob Pike4c0e51c2009-12-06 12:03:52 -0800134 if left > 0 {
135 f.writePadding(left, padding)
136 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800137 f.buf.WriteString(s)
Rob Pike4c0e51c2009-12-06 12:03:52 -0800138 if right > 0 {
139 f.writePadding(right, padding)
140 }
Rob Pike42d78502008-03-27 00:06:21 -0700141}
142
Rob Pike04faa082011-12-15 12:52:29 -0800143var (
144 trueBytes = []byte("true")
145 falseBytes = []byte("false")
146)
147
Rob Pike353ef802009-12-06 12:58:16 -0800148// fmt_boolean formats a boolean.
149func (f *fmt) fmt_boolean(v bool) {
Rob Pike85647c92009-03-06 03:35:38 -0800150 if v {
Rob Pike04faa082011-12-15 12:52:29 -0800151 f.pad(trueBytes)
Rob Pike362ea7c2008-06-24 12:54:26 -0700152 } else {
Rob Pike04faa082011-12-15 12:52:29 -0800153 f.pad(falseBytes)
Rob Pike362ea7c2008-06-24 12:54:26 -0700154 }
Rob Pike362ea7c2008-06-24 12:54:26 -0700155}
156
Rob Pikef91cd442009-12-06 15:01:07 -0800157// integer; interprets prec but not wid. Once formatted, result is sent to pad()
158// and then flags are cleared.
159func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
Michael T. Jones8cdee892011-07-21 16:46:51 +1000160 // precision of 0 and value of 0 means "print nothing"
161 if f.precPresent && f.prec == 0 && a == 0 {
162 return
163 }
164
HÃ¥vard Haugen70cf7352015-05-25 23:14:35 +0200165 negative := signedness == signed && a < 0
166 if negative {
167 a = -a
168 }
169
Russ Coxbb84f4b2010-05-27 14:51:47 -0700170 var buf []byte = f.intbuf[0:]
Rob Pikee3a9a082015-05-11 11:13:22 -0700171 if f.widPresent || f.precPresent || f.plus || f.space {
Rob Pikec6688b72015-05-07 11:22:43 -0700172 width := f.wid + f.prec // Only one will be set, both are positive; this provides the maximum.
Rob Pikefc908a02014-01-16 09:48:23 -0800173 if base == 16 && f.sharp {
174 // Also adds "0x".
175 width += 2
176 }
Rob Pikec6688b72015-05-07 11:22:43 -0700177 if f.unicode {
178 // Also adds "U+".
179 width += 2
180 if f.uniQuote {
181 // Also adds " 'x'".
182 width += 1 + 1 + utf8.UTFMax + 1
183 }
184 }
HÃ¥vard Haugen70cf7352015-05-25 23:14:35 +0200185 if negative || f.plus || f.space {
Rob Pikee3a9a082015-05-11 11:13:22 -0700186 width++
187 }
Rob Pikefc908a02014-01-16 09:48:23 -0800188 if width > nByte {
189 // We're going to need a bigger boat.
190 buf = make([]byte, width)
191 }
Rob Pikef59064d2013-08-07 08:38:46 +1000192 }
193
Russ Cox387df5e2008-11-24 14:51:33 -0800194 // two ways to ask for extra leading zero digits: %.3d or %03d.
195 // apparently the first cancels the second.
Robert Griesemer1c729592009-12-15 15:27:16 -0800196 prec := 0
Rob Pike4c0e51c2009-12-06 12:03:52 -0800197 if f.precPresent {
Robert Griesemer1c729592009-12-15 15:27:16 -0800198 prec = f.prec
199 f.zero = false
Rob Pike4c0e51c2009-12-06 12:03:52 -0800200 } else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
Robert Griesemer1c729592009-12-15 15:27:16 -0800201 prec = f.wid
Russ Cox387df5e2008-11-24 14:51:33 -0800202 if negative || f.plus || f.space {
Robert Griesemer1c729592009-12-15 15:27:16 -0800203 prec-- // leave room for sign
Rob Pike42d78502008-03-27 00:06:21 -0700204 }
205 }
Russ Cox387df5e2008-11-24 14:51:33 -0800206
Rob Pikef91cd442009-12-06 15:01:07 -0800207 // format a into buf, ending at buf[i]. (printing is easier right-to-left.)
208 // a is made into unsigned ua. we could make things
209 // marginally faster by splitting the 32-bit case out into a separate
210 // block but it's not worth the duplication, so ua has 64 bits.
Rob Pikef59064d2013-08-07 08:38:46 +1000211 i := len(buf)
Robert Griesemer1c729592009-12-15 15:27:16 -0800212 ua := uint64(a)
Rob Pike78b53212014-09-22 11:58:15 -0700213 // use constants for the division and modulo for more efficient code.
214 // switch cases ordered by popularity.
215 switch base {
216 case 10:
217 for ua >= 10 {
218 i--
219 next := ua / 10
220 buf[i] = byte('0' + ua - next*10)
221 ua = next
222 }
223 case 16:
224 for ua >= 16 {
225 i--
226 buf[i] = digits[ua&0xF]
227 ua >>= 4
228 }
229 case 8:
230 for ua >= 8 {
231 i--
232 buf[i] = byte('0' + ua&7)
233 ua >>= 3
234 }
235 case 2:
236 for ua >= 2 {
237 i--
238 buf[i] = byte('0' + ua&1)
239 ua >>= 1
240 }
241 default:
242 panic("fmt: unknown base; can't happen")
Rob Pikef91cd442009-12-06 15:01:07 -0800243 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800244 i--
245 buf[i] = digits[ua]
Rob Pikef59064d2013-08-07 08:38:46 +1000246 for i > 0 && prec > len(buf)-i {
Robert Griesemer1c729592009-12-15 15:27:16 -0800247 i--
248 buf[i] = '0'
Russ Cox387df5e2008-11-24 14:51:33 -0800249 }
250
Rob Pikef91cd442009-12-06 15:01:07 -0800251 // Various prefixes: 0x, -, etc.
Rob Pikec81d09d2009-05-15 15:18:09 -0700252 if f.sharp {
253 switch base {
254 case 8:
Rob Pikef91cd442009-12-06 15:01:07 -0800255 if buf[i] != '0' {
Robert Griesemer1c729592009-12-15 15:27:16 -0800256 i--
257 buf[i] = '0'
Rob Pikec81d09d2009-05-15 15:18:09 -0700258 }
259 case 16:
Robert Griesemer1c729592009-12-15 15:27:16 -0800260 i--
261 buf[i] = 'x' + digits[10] - 'a'
262 i--
263 buf[i] = '0'
Rob Pikec81d09d2009-05-15 15:18:09 -0700264 }
265 }
Rob Pike730e39c2010-12-06 14:23:37 -0500266 if f.unicode {
267 i--
268 buf[i] = '+'
269 i--
270 buf[i] = 'U'
271 }
Rob Pikec81d09d2009-05-15 15:18:09 -0700272
Rob Pike42d78502008-03-27 00:06:21 -0700273 if negative {
Robert Griesemer1c729592009-12-15 15:27:16 -0800274 i--
275 buf[i] = '-'
Russ Cox387df5e2008-11-24 14:51:33 -0800276 } else if f.plus {
Robert Griesemer1c729592009-12-15 15:27:16 -0800277 i--
278 buf[i] = '+'
Russ Cox387df5e2008-11-24 14:51:33 -0800279 } else if f.space {
Robert Griesemer1c729592009-12-15 15:27:16 -0800280 i--
281 buf[i] = ' '
Rob Pike42d78502008-03-27 00:06:21 -0700282 }
Rob Piked152fe72011-06-11 00:03:02 +0000283
284 // If we want a quoted char for %#U, move the data up to make room.
Russ Cox0bc18812012-03-06 23:27:11 -0500285 if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsPrint(rune(a)) {
Russ Cox4e4eca262011-10-25 22:21:33 -0700286 runeWidth := utf8.RuneLen(rune(a))
Rob Piked152fe72011-06-11 00:03:02 +0000287 width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
288 copy(buf[i-width:], buf[i:]) // guaranteed to have enough room.
289 i -= width
290 // Now put " 'x'" at the end.
291 j := len(buf) - width
292 buf[j] = ' '
293 j++
294 buf[j] = '\''
295 j++
Russ Cox4e4eca262011-10-25 22:21:33 -0700296 utf8.EncodeRune(buf[j:], rune(a))
Rob Piked152fe72011-06-11 00:03:02 +0000297 j += runeWidth
298 buf[j] = '\''
299 }
300
Robert Griesemer1c729592009-12-15 15:27:16 -0800301 f.pad(buf[i:])
Rob Pike42d78502008-03-27 00:06:21 -0700302}
303
Rob Pike39070312011-03-31 14:56:01 -0700304// truncate truncates the string to the specified precision, if present.
305func (f *fmt) truncate(s string) string {
306 if f.precPresent && f.prec < utf8.RuneCountInString(s) {
307 n := f.prec
308 for i := range s {
309 if n == 0 {
310 s = s[:i]
311 break
312 }
313 n--
Rob Pike42d78502008-03-27 00:06:21 -0700314 }
315 }
Rob Pike39070312011-03-31 14:56:01 -0700316 return s
317}
318
319// fmt_s formats a string.
320func (f *fmt) fmt_s(s string) {
321 s = f.truncate(s)
Robert Griesemer1c729592009-12-15 15:27:16 -0800322 f.padString(s)
Rob Pike42d78502008-03-27 00:06:21 -0700323}
324
Rob Pikeffea8352012-09-27 06:21:38 +1000325// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
326func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
327 n := len(b)
328 if b == nil {
329 n = len(s)
330 }
331 x := digits[10] - 'a' + 'x'
332 // TODO: Avoid buffer by pre-padding.
333 var buf []byte
334 for i := 0; i < n; i++ {
335 if i > 0 && f.space {
336 buf = append(buf, ' ')
337 }
Rob Pike311e2862014-06-16 10:45:05 -0700338 if f.sharp && (f.space || i == 0) {
Rob Pikeffea8352012-09-27 06:21:38 +1000339 buf = append(buf, '0', x)
340 }
341 var c byte
342 if b == nil {
343 c = s[i]
344 } else {
345 c = b[i]
346 }
347 buf = append(buf, digits[c>>4], digits[c&0xF])
348 }
Rob Pikea76c1a52015-06-27 11:07:30 +1000349 f.pad(buf)
Rob Pikeffea8352012-09-27 06:21:38 +1000350}
351
Rob Pike353ef802009-12-06 12:58:16 -0800352// fmt_sx formats a string as a hexadecimal encoding of its bytes.
Rob Pike04faa082011-12-15 12:52:29 -0800353func (f *fmt) fmt_sx(s, digits string) {
Rob Pike54111a52014-09-24 14:33:30 -0700354 if f.precPresent && f.prec < len(s) {
355 s = s[:f.prec]
356 }
Rob Pikeffea8352012-09-27 06:21:38 +1000357 f.fmt_sbx(s, nil, digits)
358}
359
360// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
361func (f *fmt) fmt_bx(b []byte, digits string) {
Rob Pike54111a52014-09-24 14:33:30 -0700362 if f.precPresent && f.prec < len(b) {
363 b = b[:f.prec]
364 }
Rob Pikeffea8352012-09-27 06:21:38 +1000365 f.fmt_sbx("", b, digits)
Russ Cox387df5e2008-11-24 14:51:33 -0800366}
367
Rob Pike353ef802009-12-06 12:58:16 -0800368// fmt_q formats a string as a double-quoted, escaped Go string constant.
369func (f *fmt) fmt_q(s string) {
Rob Pike39070312011-03-31 14:56:01 -0700370 s = f.truncate(s)
Robert Griesemer1c729592009-12-15 15:27:16 -0800371 var quoted string
Russ Cox387df5e2008-11-24 14:51:33 -0800372 if f.sharp && strconv.CanBackquote(s) {
Robert Griesemerbaba2922009-11-09 21:13:17 -0800373 quoted = "`" + s + "`"
Russ Cox387df5e2008-11-24 14:51:33 -0800374 } else {
Rob Piked152fe72011-06-11 00:03:02 +0000375 if f.plus {
376 quoted = strconv.QuoteToASCII(s)
377 } else {
378 quoted = strconv.Quote(s)
379 }
Russ Cox387df5e2008-11-24 14:51:33 -0800380 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800381 f.padString(quoted)
Russ Cox387df5e2008-11-24 14:51:33 -0800382}
383
Rob Pike7b03f2a2011-05-25 21:25:15 +1000384// fmt_qc formats the integer as a single-quoted, escaped Go character constant.
385// If the character is not valid Unicode, it will print '\ufffd'.
386func (f *fmt) fmt_qc(c int64) {
Rob Pike04faa082011-12-15 12:52:29 -0800387 var quoted []byte
Rob Piked152fe72011-06-11 00:03:02 +0000388 if f.plus {
Rob Pike04faa082011-12-15 12:52:29 -0800389 quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
Rob Piked152fe72011-06-11 00:03:02 +0000390 } else {
Rob Pike04faa082011-12-15 12:52:29 -0800391 quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
Rob Piked152fe72011-06-11 00:03:02 +0000392 }
Rob Pike04faa082011-12-15 12:52:29 -0800393 f.pad(quoted)
Rob Pike7b03f2a2011-05-25 21:25:15 +1000394}
395
Russ Cox079c00a2008-11-17 12:34:03 -0800396// floating-point
Rob Pike42d78502008-03-27 00:06:21 -0700397
Rob Pike353ef802009-12-06 12:58:16 -0800398func doPrec(f *fmt, def int) int {
Rob Pike4c0e51c2009-12-06 12:03:52 -0800399 if f.precPresent {
Robert Griesemer40621d52009-11-09 12:07:39 -0800400 return f.prec
Rob Pike42d78502008-03-27 00:06:21 -0700401 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800402 return def
Rob Pike42d78502008-03-27 00:06:21 -0700403}
404
Rob Pike04faa082011-12-15 12:52:29 -0800405// formatFloat formats a float64; it is an efficient equivalent to f.pad(strconv.FormatFloat()...).
406func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
Rob Pike4464ae22014-05-21 12:30:43 -0700407 // Format number, reserving space for leading + sign if needed.
408 num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
409 if num[1] == '-' || num[1] == '+' {
410 num = num[1:]
411 } else {
412 num[0] = '+'
Rob Pike542e5b82009-11-20 11:04:51 -0800413 }
Rob Pikeb5593922014-06-17 14:56:54 -0700414 // Special handling for infinity, which doesn't look like a number so shouldn't be padded with zeros.
415 if math.IsInf(v, 0) {
416 if f.zero {
417 defer func() { f.zero = true }()
418 f.zero = false
419 }
420 }
Rob Pike4464ae22014-05-21 12:30:43 -0700421 // num is now a signed version of the number.
422 // If we're zero padding, want the sign before the leading zeros.
423 // Achieve this by writing the sign out and then padding the unsigned number.
424 if f.zero && f.widPresent && f.wid > len(num) {
Rob Pikeb5593922014-06-17 14:56:54 -0700425 if f.space && v >= 0 {
426 f.buf.WriteByte(' ') // This is what C does: even with zero, f.space means space.
427 f.wid--
428 } else if f.plus || v < 0 {
429 f.buf.WriteByte(num[0])
430 f.wid--
431 }
Rob Pike4464ae22014-05-21 12:30:43 -0700432 f.pad(num[1:])
Rob Pike4464ae22014-05-21 12:30:43 -0700433 return
434 }
435 // f.space says to replace a leading + with a space.
436 if f.space && num[0] == '+' {
437 num[0] = ' '
438 f.pad(num)
439 return
440 }
441 // Now we know the sign is attached directly to the number, if present at all.
442 // We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf).
443 if f.plus || num[0] == '-' || math.IsInf(v, 0) {
444 f.pad(num)
445 return
446 }
447 // No sign to show and the number is positive; just print the unsigned number.
448 f.pad(num[1:])
Rob Pike542e5b82009-11-20 11:04:51 -0800449}
450
Rob Pike353ef802009-12-06 12:58:16 -0800451// fmt_e64 formats a float64 in the form -1.23e+12.
Rob Pike04faa082011-12-15 12:52:29 -0800452func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
Rob Pike42d78502008-03-27 00:06:21 -0700453
Rob Pike353ef802009-12-06 12:58:16 -0800454// fmt_E64 formats a float64 in the form -1.23E+12.
Rob Pike04faa082011-12-15 12:52:29 -0800455func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
Russ Coxa843b452009-08-31 16:38:30 -0700456
Rob Pike353ef802009-12-06 12:58:16 -0800457// fmt_f64 formats a float64 in the form -1.23.
Rob Pike04faa082011-12-15 12:52:29 -0800458func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
Rob Pike42d78502008-03-27 00:06:21 -0700459
Rob Pike353ef802009-12-06 12:58:16 -0800460// fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800461func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
Russ Cox079c00a2008-11-17 12:34:03 -0800462
Oling Cat6dd7da82012-12-17 18:13:12 +1100463// fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800464func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
Russ Coxa843b452009-08-31 16:38:30 -0700465
Rob Pike353ef802009-12-06 12:58:16 -0800466// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
Rob Pike04faa082011-12-15 12:52:29 -0800467func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
Russ Cox079c00a2008-11-17 12:34:03 -0800468
469// float32
470// cannot defer to float64 versions
471// because it will get rounding wrong in corner cases.
Rob Pike85647c92009-03-06 03:35:38 -0800472
Rob Pike353ef802009-12-06 12:58:16 -0800473// fmt_e32 formats a float32 in the form -1.23e+12.
Rob Pike04faa082011-12-15 12:52:29 -0800474func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
Russ Cox079c00a2008-11-17 12:34:03 -0800475
Rob Pike353ef802009-12-06 12:58:16 -0800476// fmt_E32 formats a float32 in the form -1.23E+12.
Rob Pike04faa082011-12-15 12:52:29 -0800477func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
Russ Coxa843b452009-08-31 16:38:30 -0700478
Rob Pike353ef802009-12-06 12:58:16 -0800479// fmt_f32 formats a float32 in the form -1.23.
Rob Pike04faa082011-12-15 12:52:29 -0800480func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
Russ Cox079c00a2008-11-17 12:34:03 -0800481
Rob Pike353ef802009-12-06 12:58:16 -0800482// fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800483func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
Russ Cox079c00a2008-11-17 12:34:03 -0800484
Rob Pike353ef802009-12-06 12:58:16 -0800485// fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800486func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
Russ Coxa843b452009-08-31 16:38:30 -0700487
Rob Pike353ef802009-12-06 12:58:16 -0800488// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
Rob Pike04faa082011-12-15 12:52:29 -0800489func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
Rob Pike42d78502008-03-27 00:06:21 -0700490
Rob Piked482c162010-06-14 17:16:35 -0700491// fmt_c64 formats a complex64 according to the verb.
Russ Cox4e4eca262011-10-25 22:21:33 -0700492func (f *fmt) fmt_c64(v complex64, verb rune) {
Rob Pikeb5593922014-06-17 14:56:54 -0700493 f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb)
Ken Thompson788b4172010-03-06 11:26:33 -0800494}
495
Rob Piked482c162010-06-14 17:16:35 -0700496// fmt_c128 formats a complex128 according to the verb.
Russ Cox4e4eca262011-10-25 22:21:33 -0700497func (f *fmt) fmt_c128(v complex128, verb rune) {
Rob Pikeb5593922014-06-17 14:56:54 -0700498 f.fmt_complex(real(v), imag(v), 64, verb)
499}
500
501// fmt_complex formats a complex number as (r+ji).
502func (f *fmt) fmt_complex(r, j float64, size int, verb rune) {
Ken Thompson788b4172010-03-06 11:26:33 -0800503 f.buf.WriteByte('(')
Russ Cox07cc05862012-12-11 11:49:41 -0500504 oldPlus := f.plus
Rob Pikeb5593922014-06-17 14:56:54 -0700505 oldSpace := f.space
506 oldWid := f.wid
Ken Thompson788b4172010-03-06 11:26:33 -0800507 for i := 0; ; i++ {
Rob Piked482c162010-06-14 17:16:35 -0700508 switch verb {
Rob Pike89dacb92013-09-15 10:45:36 +1000509 case 'b':
Rob Pikeb5593922014-06-17 14:56:54 -0700510 f.formatFloat(r, 'b', 0, size)
Ken Thompson788b4172010-03-06 11:26:33 -0800511 case 'e':
Rob Pikeb5593922014-06-17 14:56:54 -0700512 f.formatFloat(r, 'e', doPrec(f, 6), size)
Ken Thompson788b4172010-03-06 11:26:33 -0800513 case 'E':
Rob Pikeb5593922014-06-17 14:56:54 -0700514 f.formatFloat(r, 'E', doPrec(f, 6), size)
Rob Pikeb00d9672014-03-20 08:51:06 +1100515 case 'f', 'F':
Rob Pikeb5593922014-06-17 14:56:54 -0700516 f.formatFloat(r, 'f', doPrec(f, 6), size)
Ken Thompson788b4172010-03-06 11:26:33 -0800517 case 'g':
Rob Pikeb5593922014-06-17 14:56:54 -0700518 f.formatFloat(r, 'g', doPrec(f, -1), size)
Ken Thompson788b4172010-03-06 11:26:33 -0800519 case 'G':
Rob Pikeb5593922014-06-17 14:56:54 -0700520 f.formatFloat(r, 'G', doPrec(f, -1), size)
Ken Thompson788b4172010-03-06 11:26:33 -0800521 }
522 if i != 0 {
523 break
524 }
Rob Pikeb5593922014-06-17 14:56:54 -0700525 // Imaginary part always has a sign.
Ken Thompson788b4172010-03-06 11:26:33 -0800526 f.plus = true
Rob Pikeb5593922014-06-17 14:56:54 -0700527 f.space = false
528 f.wid = oldWid
529 r = j
Ken Thompson788b4172010-03-06 11:26:33 -0800530 }
Rob Pikeb5593922014-06-17 14:56:54 -0700531 f.space = oldSpace
Russ Cox07cc05862012-12-11 11:49:41 -0500532 f.plus = oldPlus
Rob Pikeb5593922014-06-17 14:56:54 -0700533 f.wid = oldWid
Ken Thompson788b4172010-03-06 11:26:33 -0800534 f.buf.Write(irparenBytes)
535}