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.
16 ldigits = "0123456789abcdef"
17 udigits = "0123456789ABCDEF"
25 var padZeroBytes = make([]byte, nByte)
26 var padSpaceBytes = make([]byte, nByte)
28 var newline = []byte{'\n'}
31 for i := 0; i < nByte; i++ {
33 padSpaceBytes[i] = ' '
37 // A fmt is the raw formatter used by Printf etc.
38 // It prints into a bytes.Buffer that must be set up externally.
56 func (f *fmt) clearflags() {
69 func (f *fmt) init(buf *bytes.Buffer) {
74 // Compute left and right padding widths (only one will be non-zero).
75 func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
85 return padZeroBytes, w, 0
88 return padSpaceBytes, w, 0
90 // can't be zero padding on the right
91 return padSpaceBytes, 0, w
97 // Generate n bytes of padding.
98 func (f *fmt) writePadding(n int, padding []byte) {
104 f.buf.Write(padding[0:m])
109 // Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus)
110 // clear flags afterwards.
111 func (f *fmt) pad(b []byte) {
114 if f.widPresent && f.wid != 0 {
115 padding, left, right = f.computePadding(len(b))
118 f.writePadding(left, padding)
122 f.writePadding(right, padding)
126 // append s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
127 // clear flags afterwards.
128 func (f *fmt) padString(s string) {
131 if f.widPresent && f.wid != 0 {
132 padding, left, right = f.computePadding(utf8.RuneCountInString(s))
135 f.writePadding(left, padding)
139 f.writePadding(right, padding)
143 func putint(buf []byte, base, val uint64, digits string) int {
146 buf[i] = digits[val%base]
154 // fmt_boolean formats a boolean.
155 func (f *fmt) fmt_boolean(v bool) {
163 // integer; interprets prec but not wid. Once formatted, result is sent to pad()
164 // and then flags are cleared.
165 func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
166 var buf []byte = f.intbuf[0:]
167 negative := signedness == signed && a < 0
172 // two ways to ask for extra leading zero digits: %.3d or %03d.
173 // apparently the first cancels the second.
178 } else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
180 if negative || f.plus || f.space {
181 prec-- // leave room for sign
185 // format a into buf, ending at buf[i]. (printing is easier right-to-left.)
186 // a is made into unsigned ua. we could make things
187 // marginally faster by splitting the 32-bit case out into a separate
188 // block but it's not worth the duplication, so ua has 64 bits.
193 buf[i] = digits[ua%base]
198 for i > 0 && prec > nByte-i {
203 // Various prefixes: 0x, -, etc.
213 buf[i] = 'x' + digits[10] - 'a'
238 // truncate truncates the string to the specified precision, if present.
239 func (f *fmt) truncate(s string) string {
240 if f.precPresent && f.prec < utf8.RuneCountInString(s) {
253 // fmt_s formats a string.
254 func (f *fmt) fmt_s(s string) {
259 // fmt_sx formats a string as a hexadecimal encoding of its bytes.
260 func (f *fmt) fmt_sx(s string) {
262 for i := 0; i < len(s); i++ {
263 if i > 0 && f.space {
267 t += string(ldigits[v>>4])
268 t += string(ldigits[v&0xF])
273 // fmt_sX formats a string as an uppercase hexadecimal encoding of its bytes.
274 func (f *fmt) fmt_sX(s string) {
276 for i := 0; i < len(s); i++ {
277 if i > 0 && f.space {
281 t += string(udigits[v>>4])
282 t += string(udigits[v&0xF])
287 // fmt_q formats a string as a double-quoted, escaped Go string constant.
288 func (f *fmt) fmt_q(s string) {
291 if f.sharp && strconv.CanBackquote(s) {
292 quoted = "`" + s + "`"
294 quoted = strconv.Quote(s)
301 func doPrec(f *fmt, def int) int {
308 // Add a plus sign or space to the floating-point string representation if missing and required.
309 func (f *fmt) plusSpace(s string) {
320 // fmt_e64 formats a float64 in the form -1.23e+12.
321 func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) }
323 // fmt_E64 formats a float64 in the form -1.23E+12.
324 func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) }
326 // fmt_f64 formats a float64 in the form -1.23.
327 func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) }
329 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
330 func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) }
332 // fmt_g64 formats a float64 in the 'f' or 'E' form according to size.
333 func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) }
335 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
336 func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) }
339 // cannot defer to float64 versions
340 // because it will get rounding wrong in corner cases.
342 // fmt_e32 formats a float32 in the form -1.23e+12.
343 func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) }
345 // fmt_E32 formats a float32 in the form -1.23E+12.
346 func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) }
348 // fmt_f32 formats a float32 in the form -1.23.
349 func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) }
351 // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
352 func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) }
354 // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
355 func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) }
357 // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
358 func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) }
360 // fmt_c64 formats a complex64 according to the verb.
361 func (f *fmt) fmt_c64(v complex64, verb int) {
383 f.buf.Write(irparenBytes)
386 // fmt_c128 formats a complex128 according to the verb.
387 func (f *fmt) fmt_c128(v complex128, verb int) {
409 f.buf.Write(irparenBytes)