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 5package fmt 6 7import ( 8 "strconv" 9 "unicode/utf8" 10) 11 12const ( 13 nByte = 65 // %b of an int64, plus a sign. 14 15 ldigits = "0123456789abcdef" 16 udigits = "0123456789ABCDEF" 17) 18 19const ( 20 signed = true 21 unsigned = false 22) 23 24var padZeroBytes = make([]byte, nByte) 25var padSpaceBytes = make([]byte, nByte) 26 27func 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. 36type 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 54func (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 68func (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). 74func (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. 97func (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). 109func (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). 125func (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 140var ( 141 trueBytes = []byte("true") 142 falseBytes = []byte("false") 143) 144 145// fmt_boolean formats a boolean. 146func (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. 156func (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. 258func (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. 273func (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. 279func (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. 306func (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. 311func (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. 316func (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'. 333func (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 345func 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()...). 353func (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. 386func (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. 389func (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. 392func (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. 395func (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. 398func (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). 401func (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. 408func (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. 411func (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. 414func (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. 417func (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. 420func (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). 423func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) } 424 425// fmt_c64 formats a complex64 according to the verb. 426func (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. 456func (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} 484