blob: 20baa4bd53d283d946003e393aa6dafa0299e6a8 [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 Pike353ef802009-12-06 12:58:16 -080037// A fmt is the raw formatter used by Printf etc.
Russ Cox0bc18812012-03-06 23:27:11 -050038// It prints into a buffer that must be set up separately.
Rob Pike353ef802009-12-06 12:58:16 -080039type fmt struct {
Robert Griesemer1c729592009-12-15 15:27:16 -080040 intbuf [nByte]byte
Russ Cox0bc18812012-03-06 23:27:11 -050041 buf *buffer
Rob Pikef91cd442009-12-06 15:01:07 -080042 // width, precision
Robert Griesemer1c729592009-12-15 15:27:16 -080043 wid int
44 prec int
Russ Cox387df5e2008-11-24 14:51:33 -080045 // flags
Rob Pike5245ea72010-06-28 14:11:38 -070046 widPresent bool
47 precPresent bool
48 minus bool
49 plus bool
50 sharp bool
51 space bool
Rob Pike730e39c2010-12-06 14:23:37 -050052 unicode bool
Rob Piked152fe72011-06-11 00:03:02 +000053 uniQuote bool // Use 'x'= prefix for %U if printable.
Rob Pike5245ea72010-06-28 14:11:38 -070054 zero bool
Rob Pike42d78502008-03-27 00:06:21 -070055}
56
Rob Pike353ef802009-12-06 12:58:16 -080057func (f *fmt) clearflags() {
Robert Griesemer1c729592009-12-15 15:27:16 -080058 f.wid = 0
59 f.widPresent = false
60 f.prec = 0
61 f.precPresent = false
62 f.minus = false
63 f.plus = false
64 f.sharp = false
65 f.space = false
Rob Pike730e39c2010-12-06 14:23:37 -050066 f.unicode = false
Rob Piked152fe72011-06-11 00:03:02 +000067 f.uniQuote = false
Robert Griesemer1c729592009-12-15 15:27:16 -080068 f.zero = false
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 }
Rob Pike53bc1942012-05-29 15:08:08 -0700117 padding, left, right := f.computePadding(len(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
Russ Coxbb84f4b2010-05-27 14:51:47 -0700165 var buf []byte = f.intbuf[0:]
Rob Pikefc908a02014-01-16 09:48:23 -0800166 if f.widPresent {
167 width := f.wid
168 if base == 16 && f.sharp {
169 // Also adds "0x".
170 width += 2
171 }
172 if width > nByte {
173 // We're going to need a bigger boat.
174 buf = make([]byte, width)
175 }
Rob Pikef59064d2013-08-07 08:38:46 +1000176 }
177
Robert Griesemer1c729592009-12-15 15:27:16 -0800178 negative := signedness == signed && a < 0
Rob Pike42d78502008-03-27 00:06:21 -0700179 if negative {
Robert Griesemer40621d52009-11-09 12:07:39 -0800180 a = -a
Rob Pike42d78502008-03-27 00:06:21 -0700181 }
Russ Cox387df5e2008-11-24 14:51:33 -0800182
183 // two ways to ask for extra leading zero digits: %.3d or %03d.
184 // apparently the first cancels the second.
Robert Griesemer1c729592009-12-15 15:27:16 -0800185 prec := 0
Rob Pike4c0e51c2009-12-06 12:03:52 -0800186 if f.precPresent {
Robert Griesemer1c729592009-12-15 15:27:16 -0800187 prec = f.prec
188 f.zero = false
Rob Pike4c0e51c2009-12-06 12:03:52 -0800189 } else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
Robert Griesemer1c729592009-12-15 15:27:16 -0800190 prec = f.wid
Russ Cox387df5e2008-11-24 14:51:33 -0800191 if negative || f.plus || f.space {
Robert Griesemer1c729592009-12-15 15:27:16 -0800192 prec-- // leave room for sign
Rob Pike42d78502008-03-27 00:06:21 -0700193 }
194 }
Russ Cox387df5e2008-11-24 14:51:33 -0800195
Rob Pikef91cd442009-12-06 15:01:07 -0800196 // format a into buf, ending at buf[i]. (printing is easier right-to-left.)
197 // a is made into unsigned ua. we could make things
198 // marginally faster by splitting the 32-bit case out into a separate
199 // block but it's not worth the duplication, so ua has 64 bits.
Rob Pikef59064d2013-08-07 08:38:46 +1000200 i := len(buf)
Robert Griesemer1c729592009-12-15 15:27:16 -0800201 ua := uint64(a)
Rob Pikef91cd442009-12-06 15:01:07 -0800202 for ua >= base {
Robert Griesemer1c729592009-12-15 15:27:16 -0800203 i--
204 buf[i] = digits[ua%base]
205 ua /= base
Rob Pikef91cd442009-12-06 15:01:07 -0800206 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800207 i--
208 buf[i] = digits[ua]
Rob Pikef59064d2013-08-07 08:38:46 +1000209 for i > 0 && prec > len(buf)-i {
Robert Griesemer1c729592009-12-15 15:27:16 -0800210 i--
211 buf[i] = '0'
Russ Cox387df5e2008-11-24 14:51:33 -0800212 }
213
Rob Pikef91cd442009-12-06 15:01:07 -0800214 // Various prefixes: 0x, -, etc.
Rob Pikec81d09d2009-05-15 15:18:09 -0700215 if f.sharp {
216 switch base {
217 case 8:
Rob Pikef91cd442009-12-06 15:01:07 -0800218 if buf[i] != '0' {
Robert Griesemer1c729592009-12-15 15:27:16 -0800219 i--
220 buf[i] = '0'
Rob Pikec81d09d2009-05-15 15:18:09 -0700221 }
222 case 16:
Robert Griesemer1c729592009-12-15 15:27:16 -0800223 i--
224 buf[i] = 'x' + digits[10] - 'a'
225 i--
226 buf[i] = '0'
Rob Pikec81d09d2009-05-15 15:18:09 -0700227 }
228 }
Rob Pike730e39c2010-12-06 14:23:37 -0500229 if f.unicode {
230 i--
231 buf[i] = '+'
232 i--
233 buf[i] = 'U'
234 }
Rob Pikec81d09d2009-05-15 15:18:09 -0700235
Rob Pike42d78502008-03-27 00:06:21 -0700236 if negative {
Robert Griesemer1c729592009-12-15 15:27:16 -0800237 i--
238 buf[i] = '-'
Russ Cox387df5e2008-11-24 14:51:33 -0800239 } else if f.plus {
Robert Griesemer1c729592009-12-15 15:27:16 -0800240 i--
241 buf[i] = '+'
Russ Cox387df5e2008-11-24 14:51:33 -0800242 } else if f.space {
Robert Griesemer1c729592009-12-15 15:27:16 -0800243 i--
244 buf[i] = ' '
Rob Pike42d78502008-03-27 00:06:21 -0700245 }
Rob Piked152fe72011-06-11 00:03:02 +0000246
247 // If we want a quoted char for %#U, move the data up to make room.
Russ Cox0bc18812012-03-06 23:27:11 -0500248 if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsPrint(rune(a)) {
Russ Cox4e4eca262011-10-25 22:21:33 -0700249 runeWidth := utf8.RuneLen(rune(a))
Rob Piked152fe72011-06-11 00:03:02 +0000250 width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
251 copy(buf[i-width:], buf[i:]) // guaranteed to have enough room.
252 i -= width
253 // Now put " 'x'" at the end.
254 j := len(buf) - width
255 buf[j] = ' '
256 j++
257 buf[j] = '\''
258 j++
Russ Cox4e4eca262011-10-25 22:21:33 -0700259 utf8.EncodeRune(buf[j:], rune(a))
Rob Piked152fe72011-06-11 00:03:02 +0000260 j += runeWidth
261 buf[j] = '\''
262 }
263
Robert Griesemer1c729592009-12-15 15:27:16 -0800264 f.pad(buf[i:])
Rob Pike42d78502008-03-27 00:06:21 -0700265}
266
Rob Pike39070312011-03-31 14:56:01 -0700267// truncate truncates the string to the specified precision, if present.
268func (f *fmt) truncate(s string) string {
269 if f.precPresent && f.prec < utf8.RuneCountInString(s) {
270 n := f.prec
271 for i := range s {
272 if n == 0 {
273 s = s[:i]
274 break
275 }
276 n--
Rob Pike42d78502008-03-27 00:06:21 -0700277 }
278 }
Rob Pike39070312011-03-31 14:56:01 -0700279 return s
280}
281
282// fmt_s formats a string.
283func (f *fmt) fmt_s(s string) {
284 s = f.truncate(s)
Robert Griesemer1c729592009-12-15 15:27:16 -0800285 f.padString(s)
Rob Pike42d78502008-03-27 00:06:21 -0700286}
287
Rob Pikeffea8352012-09-27 06:21:38 +1000288// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
289func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
290 n := len(b)
291 if b == nil {
292 n = len(s)
293 }
294 x := digits[10] - 'a' + 'x'
295 // TODO: Avoid buffer by pre-padding.
296 var buf []byte
297 for i := 0; i < n; i++ {
298 if i > 0 && f.space {
299 buf = append(buf, ' ')
300 }
Rob Pike311e2862014-06-16 10:45:05 -0700301 if f.sharp && (f.space || i == 0) {
Rob Pikeffea8352012-09-27 06:21:38 +1000302 buf = append(buf, '0', x)
303 }
304 var c byte
305 if b == nil {
306 c = s[i]
307 } else {
308 c = b[i]
309 }
310 buf = append(buf, digits[c>>4], digits[c&0xF])
311 }
312 f.pad(buf)
313}
314
Rob Pike353ef802009-12-06 12:58:16 -0800315// fmt_sx formats a string as a hexadecimal encoding of its bytes.
Rob Pike04faa082011-12-15 12:52:29 -0800316func (f *fmt) fmt_sx(s, digits string) {
Rob Pikeffea8352012-09-27 06:21:38 +1000317 f.fmt_sbx(s, nil, digits)
318}
319
320// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
321func (f *fmt) fmt_bx(b []byte, digits string) {
322 f.fmt_sbx("", b, digits)
Russ Cox387df5e2008-11-24 14:51:33 -0800323}
324
Rob Pike353ef802009-12-06 12:58:16 -0800325// fmt_q formats a string as a double-quoted, escaped Go string constant.
326func (f *fmt) fmt_q(s string) {
Rob Pike39070312011-03-31 14:56:01 -0700327 s = f.truncate(s)
Robert Griesemer1c729592009-12-15 15:27:16 -0800328 var quoted string
Russ Cox387df5e2008-11-24 14:51:33 -0800329 if f.sharp && strconv.CanBackquote(s) {
Robert Griesemerbaba2922009-11-09 21:13:17 -0800330 quoted = "`" + s + "`"
Russ Cox387df5e2008-11-24 14:51:33 -0800331 } else {
Rob Piked152fe72011-06-11 00:03:02 +0000332 if f.plus {
333 quoted = strconv.QuoteToASCII(s)
334 } else {
335 quoted = strconv.Quote(s)
336 }
Russ Cox387df5e2008-11-24 14:51:33 -0800337 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800338 f.padString(quoted)
Russ Cox387df5e2008-11-24 14:51:33 -0800339}
340
Rob Pike7b03f2a2011-05-25 21:25:15 +1000341// fmt_qc formats the integer as a single-quoted, escaped Go character constant.
342// If the character is not valid Unicode, it will print '\ufffd'.
343func (f *fmt) fmt_qc(c int64) {
Rob Pike04faa082011-12-15 12:52:29 -0800344 var quoted []byte
Rob Piked152fe72011-06-11 00:03:02 +0000345 if f.plus {
Rob Pike04faa082011-12-15 12:52:29 -0800346 quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
Rob Piked152fe72011-06-11 00:03:02 +0000347 } else {
Rob Pike04faa082011-12-15 12:52:29 -0800348 quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
Rob Piked152fe72011-06-11 00:03:02 +0000349 }
Rob Pike04faa082011-12-15 12:52:29 -0800350 f.pad(quoted)
Rob Pike7b03f2a2011-05-25 21:25:15 +1000351}
352
Russ Cox079c00a2008-11-17 12:34:03 -0800353// floating-point
Rob Pike42d78502008-03-27 00:06:21 -0700354
Rob Pike353ef802009-12-06 12:58:16 -0800355func doPrec(f *fmt, def int) int {
Rob Pike4c0e51c2009-12-06 12:03:52 -0800356 if f.precPresent {
Robert Griesemer40621d52009-11-09 12:07:39 -0800357 return f.prec
Rob Pike42d78502008-03-27 00:06:21 -0700358 }
Robert Griesemer1c729592009-12-15 15:27:16 -0800359 return def
Rob Pike42d78502008-03-27 00:06:21 -0700360}
361
Rob Pike04faa082011-12-15 12:52:29 -0800362// formatFloat formats a float64; it is an efficient equivalent to f.pad(strconv.FormatFloat()...).
363func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
Rob Pike4464ae22014-05-21 12:30:43 -0700364 // Format number, reserving space for leading + sign if needed.
365 num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
366 if num[1] == '-' || num[1] == '+' {
367 num = num[1:]
368 } else {
369 num[0] = '+'
Rob Pike542e5b82009-11-20 11:04:51 -0800370 }
Rob Pike4464ae22014-05-21 12:30:43 -0700371 // num is now a signed version of the number.
372 // If we're zero padding, want the sign before the leading zeros.
373 // Achieve this by writing the sign out and then padding the unsigned number.
374 if f.zero && f.widPresent && f.wid > len(num) {
375 f.buf.WriteByte(num[0])
376 f.wid--
377 f.pad(num[1:])
378 f.wid++ // Restore width; complex numbers will reuse this value for imaginary part.
379 return
380 }
381 // f.space says to replace a leading + with a space.
382 if f.space && num[0] == '+' {
383 num[0] = ' '
384 f.pad(num)
385 return
386 }
387 // Now we know the sign is attached directly to the number, if present at all.
388 // We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf).
389 if f.plus || num[0] == '-' || math.IsInf(v, 0) {
390 f.pad(num)
391 return
392 }
393 // No sign to show and the number is positive; just print the unsigned number.
394 f.pad(num[1:])
Rob Pike542e5b82009-11-20 11:04:51 -0800395}
396
Rob Pike353ef802009-12-06 12:58:16 -0800397// fmt_e64 formats a float64 in the form -1.23e+12.
Rob Pike04faa082011-12-15 12:52:29 -0800398func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
Rob Pike42d78502008-03-27 00:06:21 -0700399
Rob Pike353ef802009-12-06 12:58:16 -0800400// fmt_E64 formats a float64 in the form -1.23E+12.
Rob Pike04faa082011-12-15 12:52:29 -0800401func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
Russ Coxa843b452009-08-31 16:38:30 -0700402
Rob Pike353ef802009-12-06 12:58:16 -0800403// fmt_f64 formats a float64 in the form -1.23.
Rob Pike04faa082011-12-15 12:52:29 -0800404func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
Rob Pike42d78502008-03-27 00:06:21 -0700405
Rob Pike353ef802009-12-06 12:58:16 -0800406// fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800407func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
Russ Cox079c00a2008-11-17 12:34:03 -0800408
Oling Cat6dd7da82012-12-17 18:13:12 +1100409// fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800410func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
Russ Coxa843b452009-08-31 16:38:30 -0700411
Rob Pike353ef802009-12-06 12:58:16 -0800412// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
Rob Pike04faa082011-12-15 12:52:29 -0800413func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
Russ Cox079c00a2008-11-17 12:34:03 -0800414
415// float32
416// cannot defer to float64 versions
417// because it will get rounding wrong in corner cases.
Rob Pike85647c92009-03-06 03:35:38 -0800418
Rob Pike353ef802009-12-06 12:58:16 -0800419// fmt_e32 formats a float32 in the form -1.23e+12.
Rob Pike04faa082011-12-15 12:52:29 -0800420func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
Russ Cox079c00a2008-11-17 12:34:03 -0800421
Rob Pike353ef802009-12-06 12:58:16 -0800422// fmt_E32 formats a float32 in the form -1.23E+12.
Rob Pike04faa082011-12-15 12:52:29 -0800423func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
Russ Coxa843b452009-08-31 16:38:30 -0700424
Rob Pike353ef802009-12-06 12:58:16 -0800425// fmt_f32 formats a float32 in the form -1.23.
Rob Pike04faa082011-12-15 12:52:29 -0800426func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
Russ Cox079c00a2008-11-17 12:34:03 -0800427
Rob Pike353ef802009-12-06 12:58:16 -0800428// fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800429func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
Russ Cox079c00a2008-11-17 12:34:03 -0800430
Rob Pike353ef802009-12-06 12:58:16 -0800431// fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
Rob Pike04faa082011-12-15 12:52:29 -0800432func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
Russ Coxa843b452009-08-31 16:38:30 -0700433
Rob Pike353ef802009-12-06 12:58:16 -0800434// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
Rob Pike04faa082011-12-15 12:52:29 -0800435func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
Rob Pike42d78502008-03-27 00:06:21 -0700436
Rob Piked482c162010-06-14 17:16:35 -0700437// fmt_c64 formats a complex64 according to the verb.
Russ Cox4e4eca262011-10-25 22:21:33 -0700438func (f *fmt) fmt_c64(v complex64, verb rune) {
Ken Thompson788b4172010-03-06 11:26:33 -0800439 f.buf.WriteByte('(')
440 r := real(v)
Russ Cox07cc05862012-12-11 11:49:41 -0500441 oldPlus := f.plus
Ken Thompson788b4172010-03-06 11:26:33 -0800442 for i := 0; ; i++ {
Rob Piked482c162010-06-14 17:16:35 -0700443 switch verb {
Rob Pike89dacb92013-09-15 10:45:36 +1000444 case 'b':
445 f.fmt_fb32(r)
Ken Thompson788b4172010-03-06 11:26:33 -0800446 case 'e':
447 f.fmt_e32(r)
448 case 'E':
449 f.fmt_E32(r)
Rob Pikeb00d9672014-03-20 08:51:06 +1100450 case 'f', 'F':
Ken Thompson788b4172010-03-06 11:26:33 -0800451 f.fmt_f32(r)
452 case 'g':
453 f.fmt_g32(r)
454 case 'G':
455 f.fmt_G32(r)
456 }
457 if i != 0 {
458 break
459 }
460 f.plus = true
461 r = imag(v)
462 }
Russ Cox07cc05862012-12-11 11:49:41 -0500463 f.plus = oldPlus
Ken Thompson788b4172010-03-06 11:26:33 -0800464 f.buf.Write(irparenBytes)
465}
466
Rob Piked482c162010-06-14 17:16:35 -0700467// fmt_c128 formats a complex128 according to the verb.
Russ Cox4e4eca262011-10-25 22:21:33 -0700468func (f *fmt) fmt_c128(v complex128, verb rune) {
Ken Thompson788b4172010-03-06 11:26:33 -0800469 f.buf.WriteByte('(')
470 r := real(v)
Russ Cox07cc05862012-12-11 11:49:41 -0500471 oldPlus := f.plus
Ken Thompson788b4172010-03-06 11:26:33 -0800472 for i := 0; ; i++ {
Rob Piked482c162010-06-14 17:16:35 -0700473 switch verb {
Rob Pike89dacb92013-09-15 10:45:36 +1000474 case 'b':
475 f.fmt_fb64(r)
Ken Thompson788b4172010-03-06 11:26:33 -0800476 case 'e':
477 f.fmt_e64(r)
478 case 'E':
479 f.fmt_E64(r)
Rob Pikeb00d9672014-03-20 08:51:06 +1100480 case 'f', 'F':
Ken Thompson788b4172010-03-06 11:26:33 -0800481 f.fmt_f64(r)
482 case 'g':
483 f.fmt_g64(r)
484 case 'G':
485 f.fmt_G64(r)
486 }
487 if i != 0 {
488 break
489 }
490 f.plus = true
491 r = imag(v)
492 }
Russ Cox07cc05862012-12-11 11:49:41 -0500493 f.plus = oldPlus
Ken Thompson788b4172010-03-06 11:26:33 -0800494 f.buf.Write(irparenBytes)
495}