Home | History | Annotate | Download | only in fmt
      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 
      5 package fmt
      6 
      7 import (
      8 	"math"
      9 	"strconv"
     10 	"unicode/utf8"
     11 )
     12 
     13 const (
     14 	// %b of an int64, plus a sign.
     15 	// Hex can add 0x and we handle it specially.
     16 	nByte = 65
     17 
     18 	ldigits = "0123456789abcdef"
     19 	udigits = "0123456789ABCDEF"
     20 )
     21 
     22 const (
     23 	signed   = true
     24 	unsigned = false
     25 )
     26 
     27 var padZeroBytes = make([]byte, nByte)
     28 var padSpaceBytes = make([]byte, nByte)
     29 
     30 func init() {
     31 	for i := 0; i < nByte; i++ {
     32 		padZeroBytes[i] = '0'
     33 		padSpaceBytes[i] = ' '
     34 	}
     35 }
     36 
     37 // flags placed in a separate struct for easy clearing.
     38 type 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 
     56 // A fmt is the raw formatter used by Printf etc.
     57 // It prints into a buffer that must be set up separately.
     58 type fmt struct {
     59 	intbuf [nByte]byte
     60 	buf    *buffer
     61 	// width, precision
     62 	wid  int
     63 	prec int
     64 	fmtFlags
     65 }
     66 
     67 func (f *fmt) clearflags() {
     68 	f.fmtFlags = fmtFlags{}
     69 }
     70 
     71 func (f *fmt) init(buf *buffer) {
     72 	f.buf = buf
     73 	f.clearflags()
     74 }
     75 
     76 // computePadding computes left and right padding widths (only one will be non-zero).
     77 func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) {
     78 	left := !f.minus
     79 	w := f.wid
     80 	if w < 0 {
     81 		left = false
     82 		w = -w
     83 	}
     84 	w -= width
     85 	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 	}
     96 	return
     97 }
     98 
     99 // writePadding generates n bytes of padding.
    100 func (f *fmt) writePadding(n int, padding []byte) {
    101 	for n > 0 {
    102 		m := n
    103 		if m > nByte {
    104 			m = nByte
    105 		}
    106 		f.buf.Write(padding[0:m])
    107 		n -= m
    108 	}
    109 }
    110 
    111 // pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus).
    112 func (f *fmt) pad(b []byte) {
    113 	if !f.widPresent || f.wid == 0 {
    114 		f.buf.Write(b)
    115 		return
    116 	}
    117 	padding, left, right := f.computePadding(utf8.RuneCount(b))
    118 	if left > 0 {
    119 		f.writePadding(left, padding)
    120 	}
    121 	f.buf.Write(b)
    122 	if right > 0 {
    123 		f.writePadding(right, padding)
    124 	}
    125 }
    126 
    127 // padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus).
    128 func (f *fmt) padString(s string) {
    129 	if !f.widPresent || f.wid == 0 {
    130 		f.buf.WriteString(s)
    131 		return
    132 	}
    133 	padding, left, right := f.computePadding(utf8.RuneCountInString(s))
    134 	if left > 0 {
    135 		f.writePadding(left, padding)
    136 	}
    137 	f.buf.WriteString(s)
    138 	if right > 0 {
    139 		f.writePadding(right, padding)
    140 	}
    141 }
    142 
    143 var (
    144 	trueBytes  = []byte("true")
    145 	falseBytes = []byte("false")
    146 )
    147 
    148 // fmt_boolean formats a boolean.
    149 func (f *fmt) fmt_boolean(v bool) {
    150 	if v {
    151 		f.pad(trueBytes)
    152 	} else {
    153 		f.pad(falseBytes)
    154 	}
    155 }
    156 
    157 // integer; interprets prec but not wid.  Once formatted, result is sent to pad()
    158 // and then flags are cleared.
    159 func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
    160 	// precision of 0 and value of 0 means "print nothing"
    161 	if f.precPresent && f.prec == 0 && a == 0 {
    162 		return
    163 	}
    164 
    165 	negative := signedness == signed && a < 0
    166 	if negative {
    167 		a = -a
    168 	}
    169 
    170 	var buf []byte = f.intbuf[0:]
    171 	if f.widPresent || f.precPresent || f.plus || f.space {
    172 		width := f.wid + f.prec // Only one will be set, both are positive; this provides the maximum.
    173 		if base == 16 && f.sharp {
    174 			// Also adds "0x".
    175 			width += 2
    176 		}
    177 		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 		}
    185 		if negative || f.plus || f.space {
    186 			width++
    187 		}
    188 		if width > nByte {
    189 			// We're going to need a bigger boat.
    190 			buf = make([]byte, width)
    191 		}
    192 	}
    193 
    194 	// two ways to ask for extra leading zero digits: %.3d or %03d.
    195 	// apparently the first cancels the second.
    196 	prec := 0
    197 	if f.precPresent {
    198 		prec = f.prec
    199 		f.zero = false
    200 	} else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
    201 		prec = f.wid
    202 		if negative || f.plus || f.space {
    203 			prec-- // leave room for sign
    204 		}
    205 	}
    206 
    207 	// 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.
    211 	i := len(buf)
    212 	ua := uint64(a)
    213 	// 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")
    243 	}
    244 	i--
    245 	buf[i] = digits[ua]
    246 	for i > 0 && prec > len(buf)-i {
    247 		i--
    248 		buf[i] = '0'
    249 	}
    250 
    251 	// Various prefixes: 0x, -, etc.
    252 	if f.sharp {
    253 		switch base {
    254 		case 8:
    255 			if buf[i] != '0' {
    256 				i--
    257 				buf[i] = '0'
    258 			}
    259 		case 16:
    260 			i--
    261 			buf[i] = 'x' + digits[10] - 'a'
    262 			i--
    263 			buf[i] = '0'
    264 		}
    265 	}
    266 	if f.unicode {
    267 		i--
    268 		buf[i] = '+'
    269 		i--
    270 		buf[i] = 'U'
    271 	}
    272 
    273 	if negative {
    274 		i--
    275 		buf[i] = '-'
    276 	} else if f.plus {
    277 		i--
    278 		buf[i] = '+'
    279 	} else if f.space {
    280 		i--
    281 		buf[i] = ' '
    282 	}
    283 
    284 	// If we want a quoted char for %#U, move the data up to make room.
    285 	if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsPrint(rune(a)) {
    286 		runeWidth := utf8.RuneLen(rune(a))
    287 		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++
    296 		utf8.EncodeRune(buf[j:], rune(a))
    297 		j += runeWidth
    298 		buf[j] = '\''
    299 	}
    300 
    301 	f.pad(buf[i:])
    302 }
    303 
    304 // truncate truncates the string to the specified precision, if present.
    305 func (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--
    314 		}
    315 	}
    316 	return s
    317 }
    318 
    319 // fmt_s formats a string.
    320 func (f *fmt) fmt_s(s string) {
    321 	s = f.truncate(s)
    322 	f.padString(s)
    323 }
    324 
    325 // fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
    326 func (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 		}
    338 		if f.sharp && (f.space || i == 0) {
    339 			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 	}
    349 	f.pad(buf)
    350 }
    351 
    352 // fmt_sx formats a string as a hexadecimal encoding of its bytes.
    353 func (f *fmt) fmt_sx(s, digits string) {
    354 	if f.precPresent && f.prec < len(s) {
    355 		s = s[:f.prec]
    356 	}
    357 	f.fmt_sbx(s, nil, digits)
    358 }
    359 
    360 // fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
    361 func (f *fmt) fmt_bx(b []byte, digits string) {
    362 	if f.precPresent && f.prec < len(b) {
    363 		b = b[:f.prec]
    364 	}
    365 	f.fmt_sbx("", b, digits)
    366 }
    367 
    368 // fmt_q formats a string as a double-quoted, escaped Go string constant.
    369 func (f *fmt) fmt_q(s string) {
    370 	s = f.truncate(s)
    371 	var quoted string
    372 	if f.sharp && strconv.CanBackquote(s) {
    373 		quoted = "`" + s + "`"
    374 	} else {
    375 		if f.plus {
    376 			quoted = strconv.QuoteToASCII(s)
    377 		} else {
    378 			quoted = strconv.Quote(s)
    379 		}
    380 	}
    381 	f.padString(quoted)
    382 }
    383 
    384 // 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'.
    386 func (f *fmt) fmt_qc(c int64) {
    387 	var quoted []byte
    388 	if f.plus {
    389 		quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
    390 	} else {
    391 		quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
    392 	}
    393 	f.pad(quoted)
    394 }
    395 
    396 // floating-point
    397 
    398 func doPrec(f *fmt, def int) int {
    399 	if f.precPresent {
    400 		return f.prec
    401 	}
    402 	return def
    403 }
    404 
    405 // formatFloat formats a float64; it is an efficient equivalent to  f.pad(strconv.FormatFloat()...).
    406 func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
    407 	// 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] = '+'
    413 	}
    414 	// 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 	}
    421 	// 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) {
    425 		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 		}
    432 		f.pad(num[1:])
    433 		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:])
    449 }
    450 
    451 // fmt_e64 formats a float64 in the form -1.23e+12.
    452 func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
    453 
    454 // fmt_E64 formats a float64 in the form -1.23E+12.
    455 func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
    456 
    457 // fmt_f64 formats a float64 in the form -1.23.
    458 func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
    459 
    460 // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
    461 func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
    462 
    463 // fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
    464 func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
    465 
    466 // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
    467 func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
    468 
    469 // float32
    470 // cannot defer to float64 versions
    471 // because it will get rounding wrong in corner cases.
    472 
    473 // fmt_e32 formats a float32 in the form -1.23e+12.
    474 func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
    475 
    476 // fmt_E32 formats a float32 in the form -1.23E+12.
    477 func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
    478 
    479 // fmt_f32 formats a float32 in the form -1.23.
    480 func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
    481 
    482 // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
    483 func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
    484 
    485 // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
    486 func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
    487 
    488 // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
    489 func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
    490 
    491 // fmt_c64 formats a complex64 according to the verb.
    492 func (f *fmt) fmt_c64(v complex64, verb rune) {
    493 	f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb)
    494 }
    495 
    496 // fmt_c128 formats a complex128 according to the verb.
    497 func (f *fmt) fmt_c128(v complex128, verb rune) {
    498 	f.fmt_complex(real(v), imag(v), 64, verb)
    499 }
    500 
    501 // fmt_complex formats a complex number as (r+ji).
    502 func (f *fmt) fmt_complex(r, j float64, size int, verb rune) {
    503 	f.buf.WriteByte('(')
    504 	oldPlus := f.plus
    505 	oldSpace := f.space
    506 	oldWid := f.wid
    507 	for i := 0; ; i++ {
    508 		switch verb {
    509 		case 'b':
    510 			f.formatFloat(r, 'b', 0, size)
    511 		case 'e':
    512 			f.formatFloat(r, 'e', doPrec(f, 6), size)
    513 		case 'E':
    514 			f.formatFloat(r, 'E', doPrec(f, 6), size)
    515 		case 'f', 'F':
    516 			f.formatFloat(r, 'f', doPrec(f, 6), size)
    517 		case 'g':
    518 			f.formatFloat(r, 'g', doPrec(f, -1), size)
    519 		case 'G':
    520 			f.formatFloat(r, 'G', doPrec(f, -1), size)
    521 		}
    522 		if i != 0 {
    523 			break
    524 		}
    525 		// Imaginary part always has a sign.
    526 		f.plus = true
    527 		f.space = false
    528 		f.wid = oldWid
    529 		r = j
    530 	}
    531 	f.space = oldSpace
    532 	f.plus = oldPlus
    533 	f.wid = oldWid
    534 	f.buf.Write(irparenBytes)
    535 }
    536