github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/fmt/format.go (about)

     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  	var buf []byte = f.intbuf[0:]
   166  	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  		}
   176  	}
   177  
   178  	negative := signedness == signed && a < 0
   179  	if negative {
   180  		a = -a
   181  	}
   182  
   183  	// two ways to ask for extra leading zero digits: %.3d or %03d.
   184  	// apparently the first cancels the second.
   185  	prec := 0
   186  	if f.precPresent {
   187  		prec = f.prec
   188  		f.zero = false
   189  	} else if f.zero && f.widPresent && !f.minus && f.wid > 0 {
   190  		prec = f.wid
   191  		if negative || f.plus || f.space {
   192  			prec-- // leave room for sign
   193  		}
   194  	}
   195  
   196  	// 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.
   200  	i := len(buf)
   201  	ua := uint64(a)
   202  	// use constants for the division and modulo for more efficient code.
   203  	// switch cases ordered by popularity.
   204  	switch base {
   205  	case 10:
   206  		for ua >= 10 {
   207  			i--
   208  			next := ua / 10
   209  			buf[i] = byte('0' + ua - next*10)
   210  			ua = next
   211  		}
   212  	case 16:
   213  		for ua >= 16 {
   214  			i--
   215  			buf[i] = digits[ua&0xF]
   216  			ua >>= 4
   217  		}
   218  	case 8:
   219  		for ua >= 8 {
   220  			i--
   221  			buf[i] = byte('0' + ua&7)
   222  			ua >>= 3
   223  		}
   224  	case 2:
   225  		for ua >= 2 {
   226  			i--
   227  			buf[i] = byte('0' + ua&1)
   228  			ua >>= 1
   229  		}
   230  	default:
   231  		panic("fmt: unknown base; can't happen")
   232  	}
   233  	i--
   234  	buf[i] = digits[ua]
   235  	for i > 0 && prec > len(buf)-i {
   236  		i--
   237  		buf[i] = '0'
   238  	}
   239  
   240  	// Various prefixes: 0x, -, etc.
   241  	if f.sharp {
   242  		switch base {
   243  		case 8:
   244  			if buf[i] != '0' {
   245  				i--
   246  				buf[i] = '0'
   247  			}
   248  		case 16:
   249  			i--
   250  			buf[i] = 'x' + digits[10] - 'a'
   251  			i--
   252  			buf[i] = '0'
   253  		}
   254  	}
   255  	if f.unicode {
   256  		i--
   257  		buf[i] = '+'
   258  		i--
   259  		buf[i] = 'U'
   260  	}
   261  
   262  	if negative {
   263  		i--
   264  		buf[i] = '-'
   265  	} else if f.plus {
   266  		i--
   267  		buf[i] = '+'
   268  	} else if f.space {
   269  		i--
   270  		buf[i] = ' '
   271  	}
   272  
   273  	// If we want a quoted char for %#U, move the data up to make room.
   274  	if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsPrint(rune(a)) {
   275  		runeWidth := utf8.RuneLen(rune(a))
   276  		width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote
   277  		copy(buf[i-width:], buf[i:])   // guaranteed to have enough room.
   278  		i -= width
   279  		// Now put " 'x'" at the end.
   280  		j := len(buf) - width
   281  		buf[j] = ' '
   282  		j++
   283  		buf[j] = '\''
   284  		j++
   285  		utf8.EncodeRune(buf[j:], rune(a))
   286  		j += runeWidth
   287  		buf[j] = '\''
   288  	}
   289  
   290  	f.pad(buf[i:])
   291  }
   292  
   293  // truncate truncates the string to the specified precision, if present.
   294  func (f *fmt) truncate(s string) string {
   295  	if f.precPresent && f.prec < utf8.RuneCountInString(s) {
   296  		n := f.prec
   297  		for i := range s {
   298  			if n == 0 {
   299  				s = s[:i]
   300  				break
   301  			}
   302  			n--
   303  		}
   304  	}
   305  	return s
   306  }
   307  
   308  // fmt_s formats a string.
   309  func (f *fmt) fmt_s(s string) {
   310  	s = f.truncate(s)
   311  	f.padString(s)
   312  }
   313  
   314  // fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes.
   315  func (f *fmt) fmt_sbx(s string, b []byte, digits string) {
   316  	n := len(b)
   317  	if b == nil {
   318  		n = len(s)
   319  	}
   320  	x := digits[10] - 'a' + 'x'
   321  	// TODO: Avoid buffer by pre-padding.
   322  	var buf []byte
   323  	for i := 0; i < n; i++ {
   324  		if i > 0 && f.space {
   325  			buf = append(buf, ' ')
   326  		}
   327  		if f.sharp && (f.space || i == 0) {
   328  			buf = append(buf, '0', x)
   329  		}
   330  		var c byte
   331  		if b == nil {
   332  			c = s[i]
   333  		} else {
   334  			c = b[i]
   335  		}
   336  		buf = append(buf, digits[c>>4], digits[c&0xF])
   337  	}
   338  	f.pad(buf)
   339  }
   340  
   341  // fmt_sx formats a string as a hexadecimal encoding of its bytes.
   342  func (f *fmt) fmt_sx(s, digits string) {
   343  	if f.precPresent && f.prec < len(s) {
   344  		s = s[:f.prec]
   345  	}
   346  	f.fmt_sbx(s, nil, digits)
   347  }
   348  
   349  // fmt_bx formats a byte slice as a hexadecimal encoding of its bytes.
   350  func (f *fmt) fmt_bx(b []byte, digits string) {
   351  	if f.precPresent && f.prec < len(b) {
   352  		b = b[:f.prec]
   353  	}
   354  	f.fmt_sbx("", b, digits)
   355  }
   356  
   357  // fmt_q formats a string as a double-quoted, escaped Go string constant.
   358  func (f *fmt) fmt_q(s string) {
   359  	s = f.truncate(s)
   360  	var quoted string
   361  	if f.sharp && strconv.CanBackquote(s) {
   362  		quoted = "`" + s + "`"
   363  	} else {
   364  		if f.plus {
   365  			quoted = strconv.QuoteToASCII(s)
   366  		} else {
   367  			quoted = strconv.Quote(s)
   368  		}
   369  	}
   370  	f.padString(quoted)
   371  }
   372  
   373  // fmt_qc formats the integer as a single-quoted, escaped Go character constant.
   374  // If the character is not valid Unicode, it will print '\ufffd'.
   375  func (f *fmt) fmt_qc(c int64) {
   376  	var quoted []byte
   377  	if f.plus {
   378  		quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c))
   379  	} else {
   380  		quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c))
   381  	}
   382  	f.pad(quoted)
   383  }
   384  
   385  // floating-point
   386  
   387  func doPrec(f *fmt, def int) int {
   388  	if f.precPresent {
   389  		return f.prec
   390  	}
   391  	return def
   392  }
   393  
   394  // formatFloat formats a float64; it is an efficient equivalent to  f.pad(strconv.FormatFloat()...).
   395  func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
   396  	// Format number, reserving space for leading + sign if needed.
   397  	num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n)
   398  	if num[1] == '-' || num[1] == '+' {
   399  		num = num[1:]
   400  	} else {
   401  		num[0] = '+'
   402  	}
   403  	// Special handling for infinity, which doesn't look like a number so shouldn't be padded with zeros.
   404  	if math.IsInf(v, 0) {
   405  		if f.zero {
   406  			defer func() { f.zero = true }()
   407  			f.zero = false
   408  		}
   409  	}
   410  	// num is now a signed version of the number.
   411  	// If we're zero padding, want the sign before the leading zeros.
   412  	// Achieve this by writing the sign out and then padding the unsigned number.
   413  	if f.zero && f.widPresent && f.wid > len(num) {
   414  		if f.space && v >= 0 {
   415  			f.buf.WriteByte(' ') // This is what C does: even with zero, f.space means space.
   416  			f.wid--
   417  		} else if f.plus || v < 0 {
   418  			f.buf.WriteByte(num[0])
   419  			f.wid--
   420  		}
   421  		f.pad(num[1:])
   422  		return
   423  	}
   424  	// f.space says to replace a leading + with a space.
   425  	if f.space && num[0] == '+' {
   426  		num[0] = ' '
   427  		f.pad(num)
   428  		return
   429  	}
   430  	// Now we know the sign is attached directly to the number, if present at all.
   431  	// We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf).
   432  	if f.plus || num[0] == '-' || math.IsInf(v, 0) {
   433  		f.pad(num)
   434  		return
   435  	}
   436  	// No sign to show and the number is positive; just print the unsigned number.
   437  	f.pad(num[1:])
   438  }
   439  
   440  // fmt_e64 formats a float64 in the form -1.23e+12.
   441  func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) }
   442  
   443  // fmt_E64 formats a float64 in the form -1.23E+12.
   444  func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) }
   445  
   446  // fmt_f64 formats a float64 in the form -1.23.
   447  func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) }
   448  
   449  // fmt_g64 formats a float64 in the 'f' or 'e' form according to size.
   450  func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) }
   451  
   452  // fmt_G64 formats a float64 in the 'f' or 'E' form according to size.
   453  func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) }
   454  
   455  // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2).
   456  func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) }
   457  
   458  // float32
   459  // cannot defer to float64 versions
   460  // because it will get rounding wrong in corner cases.
   461  
   462  // fmt_e32 formats a float32 in the form -1.23e+12.
   463  func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) }
   464  
   465  // fmt_E32 formats a float32 in the form -1.23E+12.
   466  func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) }
   467  
   468  // fmt_f32 formats a float32 in the form -1.23.
   469  func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) }
   470  
   471  // fmt_g32 formats a float32 in the 'f' or 'e' form according to size.
   472  func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) }
   473  
   474  // fmt_G32 formats a float32 in the 'f' or 'E' form according to size.
   475  func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) }
   476  
   477  // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
   478  func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) }
   479  
   480  // fmt_c64 formats a complex64 according to the verb.
   481  func (f *fmt) fmt_c64(v complex64, verb rune) {
   482  	f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb)
   483  }
   484  
   485  // fmt_c128 formats a complex128 according to the verb.
   486  func (f *fmt) fmt_c128(v complex128, verb rune) {
   487  	f.fmt_complex(real(v), imag(v), 64, verb)
   488  }
   489  
   490  // fmt_complex formats a complex number as (r+ji).
   491  func (f *fmt) fmt_complex(r, j float64, size int, verb rune) {
   492  	f.buf.WriteByte('(')
   493  	oldPlus := f.plus
   494  	oldSpace := f.space
   495  	oldWid := f.wid
   496  	for i := 0; ; i++ {
   497  		switch verb {
   498  		case 'b':
   499  			f.formatFloat(r, 'b', 0, size)
   500  		case 'e':
   501  			f.formatFloat(r, 'e', doPrec(f, 6), size)
   502  		case 'E':
   503  			f.formatFloat(r, 'E', doPrec(f, 6), size)
   504  		case 'f', 'F':
   505  			f.formatFloat(r, 'f', doPrec(f, 6), size)
   506  		case 'g':
   507  			f.formatFloat(r, 'g', doPrec(f, -1), size)
   508  		case 'G':
   509  			f.formatFloat(r, 'G', doPrec(f, -1), size)
   510  		}
   511  		if i != 0 {
   512  			break
   513  		}
   514  		// Imaginary part always has a sign.
   515  		f.plus = true
   516  		f.space = false
   517  		f.wid = oldWid
   518  		r = j
   519  	}
   520  	f.space = oldSpace
   521  	f.plus = oldPlus
   522  	f.wid = oldWid
   523  	f.buf.Write(irparenBytes)
   524  }