1// 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
7import (
8	"strconv"
9	"unicode/utf8"
10)
11
12const (
13	nByte = 65 // %b of an int64, plus a sign.
14
15	ldigits = "0123456789abcdef"
16	udigits = "0123456789ABCDEF"
17)
18
19const (
20	signed   = true
21	unsigned = false
22)
23
24var padZeroBytes = make([]byte, nByte)
25var padSpaceBytes = make([]byte, nByte)
26
27func init() {
28	for i := 0; i < nByte; i++ {
29		padZeroBytes[i] = '0'
30		padSpaceBytes[i] = ' '
31	}
32}
33
34// A fmt is the raw formatter used by Printf etc.
35// It prints into a buffer that must be set up separately.
36type fmt struct {
37	intbuf [nByte]byte
38	buf    *buffer
39	// width, precision
40	wid  int
41	prec int
42	// flags
43	widPresent  bool
44	precPresent bool
45	minus       bool
46	plus        bool
47	sharp       bool
48	space       bool
49	unicode     bool
50	uniQuote    bool // Use 'x'= prefix for %U if printable.
51	zero        bool
52}
53
54func (f *fmt) clearflags() {
55	f.wid = 0
56	f.widPresent = false
57	f.prec = 0
58	f.precPresent = false
59	f.minus = false
60	f.plus = false
61	f.sharp = false
62	f.space = false
63	f.unicode = false
64	f.uniQuote = false
65	f.zero = false
66}
67
68func (f *fmt) init(buf *buffer) {
69	f.buf = buf
70	f.clearflags()
71}
72
73// computePadding computes left and right padding widths (only one will be non-zero).
74func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
75	left := !f.minus
76	w := f.wid
77	if w < 0 {
78		left = false
79		w = -w
80	}
81	w -= width
82	if w > 0 {
83		if left && f.zero {
84			return padZeroBytes, w, 0
85		}
86		if left {
87			return padSpaceBytes, w, 0
88		} else {
89			// can't be zero padding on the right
90			return padSpaceBytes, 0, w
91		}
92	}
93	return
94}
95
96// writePadding generates n bytes of padding.
97func (f *fmt) writePadding(n int, padding []byte) {
98	for n > 0 {
99		m := n
100		if m > nByte {
101			m = nByte
102		}
103		f.buf.Write(padding[0:m])
104		n -= m
105	}
106}
107
108// pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus).
109func (f *fmt) pad(b []byte) {
110	if !f.widPresent || f.wid == 0 {
111		f.buf.Write(b)
112		return
113	}
114	padding, left, right := f.computePadding(len(b))
115	if left > 0 {
116		f.writePadding(left, padding)
117	}
118	f.buf.Write(b)
119	if right > 0 {
120		f.writePadding(right, padding)
121	}
122}
123
124// padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
125func (f *fmt) padString(s string) {
126	if !f.widPresent || f.wid == 0 {
127		f.buf.WriteString(s)
128		return
129	}
130	padding, left, right := f.computePadding(utf8.RuneCountInString(s))
131	if left > 0 {
132		f.writePadding(left, padding)
133	}
134	f.buf.WriteString(s)
135	if right > 0 {
136		f.writePadding(right, padding)
137	}
138}
139
140var (
141	trueBytes  = []byte("true")
142	falseBytes = []byte("false")
143)
144
145// fmt_boolean formats a boolean.
146func (f *fmt) fmt_boolean(v bool) {
147	if v {
148		f.pad(trueBytes)
149	} else {
150		f.pad(falseBytes)
151	}
152}
153
154// integer; interprets prec but not wid.  Once formatted, result is sent to pad()
155// and then flags are cleared.
156func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
157	// precision of 0 and value of 0 means "print nothing"
158	if f.precPresent && f.prec == 0 && a == 0 {
159		return
160	}
161
162	var buf []byte = f.intbuf[0:]
163	if f.widPresent && f.wid > nByte {
164		// We're going to need a bigger boat.
165		buf = make([]byte, f.wid)
166	}
167
168	negative := signedness == signed && a < 0
169	if negative {
170		a = -a
171	}
172
173	// two ways to ask for extra leading zero digits: %.3d or %03d.
174	// apparently the first cancels the second.
175	prec := 0
176	if f.precPresent {
177		prec = f.prec
178		f.zero = false
179	} else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
180		prec = f.wid
181		if negative || f.plus || f.space {
182			prec-- // leave room for sign
183		}
184	}
185
186	// format a into buf, ending at buf[i].  (printing is easier right-to-left.)
187	// a is made into unsigned ua.  we could make things
188	// marginally faster by splitting the 32-bit case out into a separate
189	// block but it's not worth the duplication, so ua has 64 bits.
190	i := len(buf)
191	ua := uint64(a)
192	for ua >= base {
193		i--
194		buf[i] = digits[ua%base]
195		ua /= base
196	}
197	i--
198	buf[i] = digits[ua]
199	for i > 0 && prec > len(buf)-i {
200		i--
201		buf[i] = '0'
202	}
203
204	// Various prefixes: 0x, -, etc.
205	if f.sharp {
206		switch base {
207		case 8:
208			if buf[i] != '0' {
209				i--
210				buf[i] = '0'
211			}
212		case 16:
213			i--
214			buf[i] = 'x' + digits[10] - 'a'
215			i--
216			buf[i] = '0'
217		}
218	}
219	if f.unicode {
220		i--
221		buf[i] = '+'
222		i--
223		buf[i] = 'U'
224	}
225
226	if negative {
227		i--
228		buf[i] = '-'
229	} else if f.plus {
230		i--
231		buf[i] = '+'
232	} else if f.space {
233		i--
234		buf[i] = ' '
235	}
236
237	// If we want a quoted char for %#U, move the data up to make room.
238	if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsPrint(rune(a)) {
239		runeWidth := utf8.RuneLen(rune(a))
240		width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
241		copy(buf[i-width:], buf[i:])   // guaranteed to have enough room.
242		i -= width
243		// Now put " 'x'" at the end.
244		j := len(buf) - width
245		buf[j] = ' '
246		j++
247		buf[j] = '\''
248		j++
249		utf8.EncodeRune(buf[j:], rune(a))
250		j += runeWidth
251		buf[j] = '\''
252	}
253
254	f.pad(buf[i:])
255}
256
257// truncate truncates the string to the specified precision, if present.
258func (f *fmt) truncate(s string) string {
259	if f.precPresent && f.prec < utf8.RuneCountInString(s) {
260		n := f.prec
261		for i := range s {
262			if n == 0 {
263				s = s[:i]
264				break
265			}
266			n--
267		}
268	}
269	return s
270}
271
272// fmt_s formats a string.
273func (f *fmt) fmt_s(s string) {
274	s = f.truncate(s)
275	f.padString(s)
276}
277
278// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
279func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
280	n := len(b)
281	if b == nil {
282		n = len(s)
283	}
284	x := digits[10] - 'a' + 'x'
285	// TODO: Avoid buffer by pre-padding.
286	var buf []byte
287	for i := 0; i < n; i++ {
288		if i > 0 && f.space {
289			buf = append(buf, ' ')
290		}
291		if f.sharp {
292			buf = append(buf, '0', x)
293		}
294		var c byte
295		if b == nil {
296			c = s[i]
297		} else {
298			c = b[i]
299		}
300		buf = append(buf, digits[c>>4], digits[c&0xF])
301	}
302	f.pad(buf)
303}
304
305// fmt_sx formats a string as a hexadecimal encoding of its bytes.
306func (f *fmt) fmt_sx(s, digits string) {
307	f.fmt_sbx(s, nil, digits)
308}
309
310// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
311func (f *fmt) fmt_bx(b []byte, digits string) {
312	f.fmt_sbx("", b, digits)
313}
314
315// fmt_q formats a string as a double-quoted, escaped Go string constant.
316func (f *fmt) fmt_q(s string) {
317	s = f.truncate(s)
318	var quoted string
319	if f.sharp && strconv.CanBackquote(s) {
320		quoted = "`" + s + "`"
321	} else {
322		if f.plus {
323			quoted = strconv.QuoteToASCII(s)
324		} else {
325			quoted = strconv.Quote(s)
326		}
327	}
328	f.padString(quoted)
329}
330
331// fmt_qc formats the integer as a single-quoted, escaped Go character constant.
332// If the character is not valid Unicode, it will print '\ufffd'.
333func (f *fmt) fmt_qc(c int64) {
334	var quoted []byte
335	if f.plus {
336		quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
337	} else {
338		quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
339	}
340	f.pad(quoted)
341}
342
343// floating-point
344
345func doPrec(f *fmt, def int) int {
346	if f.precPresent {
347		return f.prec
348	}
349	return def
350}
351
352// formatFloat formats a float64; it is an efficient equivalent to  f.pad(strconv.FormatFloat()...).
353func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
354	// We leave one byte at the beginning of f.intbuf for a sign if needed,
355	// and make it a space, which we might be able to use.
356	f.intbuf[0] = ' '
357	slice := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
358	// Add a plus sign or space to the floating-point string representation if missing and required.
359	// The formatted number starts at slice[1].
360	switch slice[1] {
361	case '-', '+':
362		// If we're zero padding, want the sign before the leading zeros.
363		// Achieve this by writing the sign out and padding the postive number.
364		if f.zero && f.widPresent && f.wid > len(slice) {
365			f.buf.WriteByte(slice[1])
366			f.wid--
367			f.pad(slice[2:])
368			return
369		}
370		// We're set; drop the leading space.
371		slice = slice[1:]
372	default:
373		// There's no sign, but we might need one.
374		if f.plus {
375			slice[0] = '+'
376		} else if f.space {
377			// space is already there
378		} else {
379			slice = slice[1:]
380		}
381	}
382	f.pad(slice)
383}
384
385// fmt_e64 formats a float64 in the form -1.23e+12.
386func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
387
388// fmt_E64 formats a float64 in the form -1.23E+12.
389func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
390
391// fmt_f64 formats a float64 in the form -1.23.
392func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
393
394// fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
395func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
396
397// fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
398func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
399
400// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
401func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
402
403// float32
404// cannot defer to float64 versions
405// because it will get rounding wrong in corner cases.
406
407// fmt_e32 formats a float32 in the form -1.23e+12.
408func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
409
410// fmt_E32 formats a float32 in the form -1.23E+12.
411func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
412
413// fmt_f32 formats a float32 in the form -1.23.
414func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
415
416// fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
417func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
418
419// fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
420func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
421
422// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
423func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
424
425// fmt_c64 formats a complex64 according to the verb.
426func (f *fmt) fmt_c64(v complex64, verb rune) {
427	f.buf.WriteByte('(')
428	r := real(v)
429	oldPlus := f.plus
430	for i := 0; ; i++ {
431		switch verb {
432		case 'b':
433			f.fmt_fb32(r)
434		case 'e':
435			f.fmt_e32(r)
436		case 'E':
437			f.fmt_E32(r)
438		case 'f':
439			f.fmt_f32(r)
440		case 'g':
441			f.fmt_g32(r)
442		case 'G':
443			f.fmt_G32(r)
444		}
445		if i != 0 {
446			break
447		}
448		f.plus = true
449		r = imag(v)
450	}
451	f.plus = oldPlus
452	f.buf.Write(irparenBytes)
453}
454
455// fmt_c128 formats a complex128 according to the verb.
456func (f *fmt) fmt_c128(v complex128, verb rune) {
457	f.buf.WriteByte('(')
458	r := real(v)
459	oldPlus := f.plus
460	for i := 0; ; i++ {
461		switch verb {
462		case 'b':
463			f.fmt_fb64(r)
464		case 'e':
465			f.fmt_e64(r)
466		case 'E':
467			f.fmt_E64(r)
468		case 'f':
469			f.fmt_f64(r)
470		case 'g':
471			f.fmt_g64(r)
472		case 'G':
473			f.fmt_G64(r)
474		}
475		if i != 0 {
476			break
477		}
478		f.plus = true
479		r = imag(v)
480	}
481	f.plus = oldPlus
482	f.buf.Write(irparenBytes)
483}
484