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