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 ldigits = "0123456789abcdefx" 14 udigits = "0123456789ABCDEFX" 15) 16 17const ( 18 signed = true 19 unsigned = false 20) 21 22// flags placed in a separate struct for easy clearing. 23type fmtFlags struct { 24 widPresent bool 25 precPresent bool 26 minus bool 27 plus bool 28 sharp bool 29 space bool 30 zero bool 31 32 // For the formats %+v %#v, we set the plusV/sharpV flags 33 // and clear the plus/sharp flags since %+v and %#v are in effect 34 // different, flagless formats set at the top level. 35 plusV bool 36 sharpV bool 37} 38 39// A fmt is the raw formatter used by Printf etc. 40// It prints into a buffer that must be set up separately. 41type fmt struct { 42 buf *buffer 43 44 fmtFlags 45 46 wid int // width 47 prec int // precision 48 49 // intbuf is large enough to store %b of an int64 with a sign and 50 // avoids padding at the end of the struct on 32 bit architectures. 51 intbuf [68]byte 52} 53 54func (f *fmt) clearflags() { 55 f.fmtFlags = fmtFlags{} 56} 57 58func (f *fmt) init(buf *buffer) { 59 f.buf = buf 60 f.clearflags() 61} 62 63// writePadding generates n bytes of padding. 64func (f *fmt) writePadding(n int) { 65 if n <= 0 { // No padding bytes needed. 66 return 67 } 68 buf := *f.buf 69 oldLen := len(buf) 70 newLen := oldLen + n 71 // Make enough room for padding. 72 if newLen > cap(buf) { 73 buf = make(buffer, cap(buf)*2+n) 74 copy(buf, *f.buf) 75 } 76 // Decide which byte the padding should be filled with. 77 padByte := byte(' ') 78 if f.zero { 79 padByte = byte('0') 80 } 81 // Fill padding with padByte. 82 padding := buf[oldLen:newLen] 83 for i := range padding { 84 padding[i] = padByte 85 } 86 *f.buf = buf[:newLen] 87} 88 89// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus). 90func (f *fmt) pad(b []byte) { 91 if !f.widPresent || f.wid == 0 { 92 f.buf.Write(b) 93 return 94 } 95 width := f.wid - utf8.RuneCount(b) 96 if !f.minus { 97 // left padding 98 f.writePadding(width) 99 f.buf.Write(b) 100 } else { 101 // right padding 102 f.buf.Write(b) 103 f.writePadding(width) 104 } 105} 106 107// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus). 108func (f *fmt) padString(s string) { 109 if !f.widPresent || f.wid == 0 { 110 f.buf.WriteString(s) 111 return 112 } 113 width := f.wid - utf8.RuneCountInString(s) 114 if !f.minus { 115 // left padding 116 f.writePadding(width) 117 f.buf.WriteString(s) 118 } else { 119 // right padding 120 f.buf.WriteString(s) 121 f.writePadding(width) 122 } 123} 124 125// fmtBoolean formats a boolean. 126func (f *fmt) fmtBoolean(v bool) { 127 if v { 128 f.padString("true") 129 } else { 130 f.padString("false") 131 } 132} 133 134// fmtUnicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'". 135func (f *fmt) fmtUnicode(u uint64) { 136 buf := f.intbuf[0:] 137 138 // With default precision set the maximum needed buf length is 18 139 // for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits 140 // into the already allocated intbuf with a capacity of 68 bytes. 141 prec := 4 142 if f.precPresent && f.prec > 4 { 143 prec = f.prec 144 // Compute space needed for "U+" , number, " '", character, "'". 145 width := 2 + prec + 2 + utf8.UTFMax + 1 146 if width > len(buf) { 147 buf = make([]byte, width) 148 } 149 } 150 151 // Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left. 152 i := len(buf) 153 154 // For %#U we want to add a space and a quoted character at the end of the buffer. 155 if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) { 156 i-- 157 buf[i] = '\'' 158 i -= utf8.RuneLen(rune(u)) 159 utf8.EncodeRune(buf[i:], rune(u)) 160 i-- 161 buf[i] = '\'' 162 i-- 163 buf[i] = ' ' 164 } 165 // Format the Unicode code point u as a hexadecimal number. 166 for u >= 16 { 167 i-- 168 buf[i] = udigits[u&0xF] 169 prec-- 170 u >>= 4 171 } 172 i-- 173 buf[i] = udigits[u] 174 prec-- 175 // Add zeros in front of the number until requested precision is reached. 176 for prec > 0 { 177 i-- 178 buf[i] = '0' 179 prec-- 180 } 181 // Add a leading "U+". 182 i-- 183 buf[i] = '+' 184 i-- 185 buf[i] = 'U' 186 187 oldZero := f.zero 188 f.zero = false 189 f.pad(buf[i:]) 190 f.zero = oldZero 191} 192 193// fmtInteger formats signed and unsigned integers. 194func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) { 195 negative := isSigned && int64(u) < 0 196 if negative { 197 u = -u 198 } 199 200 buf := f.intbuf[0:] 201 // The already allocated f.intbuf with a capacity of 68 bytes 202 // is large enough for integer formatting when no precision or width is set. 203 if f.widPresent || f.precPresent { 204 // Account 3 extra bytes for possible addition of a sign and "0x". 205 width := 3 + f.wid + f.prec // wid and prec are always positive. 206 if width > len(buf) { 207 // We're going to need a bigger boat. 208 buf = make([]byte, width) 209 } 210 } 211 212 // Two ways to ask for extra leading zero digits: %.3d or %03d. 213 // If both are specified the f.zero flag is ignored and 214 // padding with spaces is used instead. 215 prec := 0 216 if f.precPresent { 217 prec = f.prec 218 // Precision of 0 and value of 0 means "print nothing" but padding. 219 if prec == 0 && u == 0 { 220 oldZero := f.zero 221 f.zero = false 222 f.writePadding(f.wid) 223 f.zero = oldZero 224 return 225 } 226 } else if f.zero && f.widPresent { 227 prec = f.wid 228 if negative || f.plus || f.space { 229 prec-- // leave room for sign 230 } 231 } 232 233 // Because printing is easier right-to-left: format u into buf, ending at buf[i]. 234 // We could make things marginally faster by splitting the 32-bit case out 235 // into a separate block but it's not worth the duplication, so u has 64 bits. 236 i := len(buf) 237 // Use constants for the division and modulo for more efficient code. 238 // Switch cases ordered by popularity. 239 switch base { 240 case 10: 241 for u >= 10 { 242 i-- 243 next := u / 10 244 buf[i] = byte('0' + u - next*10) 245 u = next 246 } 247 case 16: 248 for u >= 16 { 249 i-- 250 buf[i] = digits[u&0xF] 251 u >>= 4 252 } 253 case 8: 254 for u >= 8 { 255 i-- 256 buf[i] = byte('0' + u&7) 257 u >>= 3 258 } 259 case 2: 260 for u >= 2 { 261 i-- 262 buf[i] = byte('0' + u&1) 263 u >>= 1 264 } 265 default: 266 panic("fmt: unknown base; can't happen") 267 } 268 i-- 269 buf[i] = digits[u] 270 for i > 0 && prec > len(buf)-i { 271 i-- 272 buf[i] = '0' 273 } 274 275 // Various prefixes: 0x, -, etc. 276 if f.sharp { 277 switch base { 278 case 8: 279 if buf[i] != '0' { 280 i-- 281 buf[i] = '0' 282 } 283 case 16: 284 // Add a leading 0x or 0X. 285 i-- 286 buf[i] = digits[16] 287 i-- 288 buf[i] = '0' 289 } 290 } 291 292 if negative { 293 i-- 294 buf[i] = '-' 295 } else if f.plus { 296 i-- 297 buf[i] = '+' 298 } else if f.space { 299 i-- 300 buf[i] = ' ' 301 } 302 303 // Left padding with zeros has already been handled like precision earlier 304 // or the f.zero flag is ignored due to an explicitly set precision. 305 oldZero := f.zero 306 f.zero = false 307 f.pad(buf[i:]) 308 f.zero = oldZero 309} 310 311// truncate truncates the string s to the specified precision, if present. 312func (f *fmt) truncateString(s string) string { 313 if f.precPresent { 314 n := f.prec 315 for i := range s { 316 n-- 317 if n < 0 { 318 return s[:i] 319 } 320 } 321 } 322 return s 323} 324 325// truncate truncates the byte slice b as a string of the specified precision, if present. 326func (f *fmt) truncate(b []byte) []byte { 327 if f.precPresent { 328 n := f.prec 329 for i := 0; i < len(b); { 330 n-- 331 if n < 0 { 332 return b[:i] 333 } 334 wid := 1 335 if b[i] >= utf8.RuneSelf { 336 _, wid = utf8.DecodeRune(b[i:]) 337 } 338 i += wid 339 } 340 } 341 return b 342} 343 344// fmtS formats a string. 345func (f *fmt) fmtS(s string) { 346 s = f.truncateString(s) 347 f.padString(s) 348} 349 350// fmtBs formats the byte slice b as if it was formatted as string with fmtS. 351func (f *fmt) fmtBs(b []byte) { 352 b = f.truncate(b) 353 f.pad(b) 354} 355 356// fmtSbx formats a string or byte slice as a hexadecimal encoding of its bytes. 357func (f *fmt) fmtSbx(s string, b []byte, digits string) { 358 length := len(b) 359 if b == nil { 360 // No byte slice present. Assume string s should be encoded. 361 length = len(s) 362 } 363 // Set length to not process more bytes than the precision demands. 364 if f.precPresent && f.prec < length { 365 length = f.prec 366 } 367 // Compute width of the encoding taking into account the f.sharp and f.space flag. 368 width := 2 * length 369 if width > 0 { 370 if f.space { 371 // Each element encoded by two hexadecimals will get a leading 0x or 0X. 372 if f.sharp { 373 width *= 2 374 } 375 // Elements will be separated by a space. 376 width += length - 1 377 } else if f.sharp { 378 // Only a leading 0x or 0X will be added for the whole string. 379 width += 2 380 } 381 } else { // The byte slice or string that should be encoded is empty. 382 if f.widPresent { 383 f.writePadding(f.wid) 384 } 385 return 386 } 387 // Handle padding to the left. 388 if f.widPresent && f.wid > width && !f.minus { 389 f.writePadding(f.wid - width) 390 } 391 // Write the encoding directly into the output buffer. 392 buf := *f.buf 393 if f.sharp { 394 // Add leading 0x or 0X. 395 buf = append(buf, '0', digits[16]) 396 } 397 var c byte 398 for i := 0; i < length; i++ { 399 if f.space && i > 0 { 400 // Separate elements with a space. 401 buf = append(buf, ' ') 402 if f.sharp { 403 // Add leading 0x or 0X for each element. 404 buf = append(buf, '0', digits[16]) 405 } 406 } 407 if b != nil { 408 c = b[i] // Take a byte from the input byte slice. 409 } else { 410 c = s[i] // Take a byte from the input string. 411 } 412 // Encode each byte as two hexadecimal digits. 413 buf = append(buf, digits[c>>4], digits[c&0xF]) 414 } 415 *f.buf = buf 416 // Handle padding to the right. 417 if f.widPresent && f.wid > width && f.minus { 418 f.writePadding(f.wid - width) 419 } 420} 421 422// fmtSx formats a string as a hexadecimal encoding of its bytes. 423func (f *fmt) fmtSx(s, digits string) { 424 f.fmtSbx(s, nil, digits) 425} 426 427// fmtBx formats a byte slice as a hexadecimal encoding of its bytes. 428func (f *fmt) fmtBx(b []byte, digits string) { 429 f.fmtSbx("", b, digits) 430} 431 432// fmtQ formats a string as a double-quoted, escaped Go string constant. 433// If f.sharp is set a raw (backquoted) string may be returned instead 434// if the string does not contain any control characters other than tab. 435func (f *fmt) fmtQ(s string) { 436 s = f.truncateString(s) 437 if f.sharp && strconv.CanBackquote(s) { 438 f.padString("`" + s + "`") 439 return 440 } 441 buf := f.intbuf[:0] 442 if f.plus { 443 f.pad(strconv.AppendQuoteToASCII(buf, s)) 444 } else { 445 f.pad(strconv.AppendQuote(buf, s)) 446 } 447} 448 449// fmtC formats an integer as a Unicode character. 450// If the character is not valid Unicode, it will print '\ufffd'. 451func (f *fmt) fmtC(c uint64) { 452 r := rune(c) 453 if c > utf8.MaxRune { 454 r = utf8.RuneError 455 } 456 buf := f.intbuf[:0] 457 w := utf8.EncodeRune(buf[:utf8.UTFMax], r) 458 f.pad(buf[:w]) 459} 460 461// fmtQc formats an integer as a single-quoted, escaped Go character constant. 462// If the character is not valid Unicode, it will print '\ufffd'. 463func (f *fmt) fmtQc(c uint64) { 464 r := rune(c) 465 if c > utf8.MaxRune { 466 r = utf8.RuneError 467 } 468 buf := f.intbuf[:0] 469 if f.plus { 470 f.pad(strconv.AppendQuoteRuneToASCII(buf, r)) 471 } else { 472 f.pad(strconv.AppendQuoteRune(buf, r)) 473 } 474} 475 476// fmtFloat formats a float64. It assumes that verb is a valid format specifier 477// for strconv.AppendFloat and therefore fits into a byte. 478func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) { 479 // Explicit precision in format specifier overrules default precision. 480 if f.precPresent { 481 prec = f.prec 482 } 483 // Format number, reserving space for leading + sign if needed. 484 num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size) 485 if num[1] == '-' || num[1] == '+' { 486 num = num[1:] 487 } else { 488 num[0] = '+' 489 } 490 // f.space means to add a leading space instead of a "+" sign unless 491 // the sign is explicitly asked for by f.plus. 492 if f.space && num[0] == '+' && !f.plus { 493 num[0] = ' ' 494 } 495 // Special handling for infinities and NaN, 496 // which don't look like a number so shouldn't be padded with zeros. 497 if num[1] == 'I' || num[1] == 'N' { 498 oldZero := f.zero 499 f.zero = false 500 // Remove sign before NaN if not asked for. 501 if num[1] == 'N' && !f.space && !f.plus { 502 num = num[1:] 503 } 504 f.pad(num) 505 f.zero = oldZero 506 return 507 } 508 // The sharp flag forces printing a decimal point for non-binary formats 509 // and retains trailing zeros, which we may need to restore. 510 if f.sharp && verb != 'b' { 511 digits := 0 512 switch verb { 513 case 'v', 'g', 'G': 514 digits = prec 515 // If no precision is set explicitly use a precision of 6. 516 if digits == -1 { 517 digits = 6 518 } 519 } 520 521 // Buffer pre-allocated with enough room for 522 // exponent notations of the form "e+123". 523 var tailBuf [5]byte 524 tail := tailBuf[:0] 525 526 hasDecimalPoint := false 527 // Starting from i = 1 to skip sign at num[0]. 528 for i := 1; i < len(num); i++ { 529 switch num[i] { 530 case '.': 531 hasDecimalPoint = true 532 case 'e', 'E': 533 tail = append(tail, num[i:]...) 534 num = num[:i] 535 default: 536 digits-- 537 } 538 } 539 if !hasDecimalPoint { 540 num = append(num, '.') 541 } 542 for digits > 0 { 543 num = append(num, '0') 544 digits-- 545 } 546 num = append(num, tail...) 547 } 548 // We want a sign if asked for and if the sign is not positive. 549 if f.plus || num[0] != '+' { 550 // If we're zero padding to the left we want the sign before the leading zeros. 551 // Achieve this by writing the sign out and then padding the unsigned number. 552 if f.zero && f.widPresent && f.wid > len(num) { 553 f.buf.WriteByte(num[0]) 554 f.writePadding(f.wid - len(num)) 555 f.buf.Write(num[1:]) 556 return 557 } 558 f.pad(num) 559 return 560 } 561 // No sign to show and the number is positive; just print the unsigned number. 562 f.pad(num[1:]) 563} 564