github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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  	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  }