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