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 }