// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fmt

import (
	
	
)

const (
	ldigits = "0123456789abcdefx"
	udigits = "0123456789ABCDEFX"
)

const (
	signed   = true
	unsigned = false
)

// flags placed in a separate struct for easy clearing.
type fmtFlags struct {
	widPresent  bool
	precPresent bool
	minus       bool
	plus        bool
	sharp       bool
	space       bool
	zero        bool

	// For the formats %+v %#v, we set the plusV/sharpV flags
	// and clear the plus/sharp flags since %+v and %#v are in effect
	// different, flagless formats set at the top level.
	plusV  bool
	sharpV bool
}

// A fmt is the raw formatter used by Printf etc.
// It prints into a buffer that must be set up separately.
type fmt struct {
	buf *buffer

	fmtFlags

	wid  int // width
	prec int // precision

	// intbuf is large enough to store %b of an int64 with a sign and
	// avoids padding at the end of the struct on 32 bit architectures.
	intbuf [68]byte
}

func ( *fmt) () {
	.fmtFlags = fmtFlags{}
}

func ( *fmt) ( *buffer) {
	.buf = 
	.clearflags()
}

// writePadding generates n bytes of padding.
func ( *fmt) ( int) {
	if  <= 0 { // No padding bytes needed.
		return
	}
	 := *.buf
	 := len()
	 :=  + 
	// Make enough room for padding.
	if  > cap() {
		 = make(buffer, cap()*2+)
		copy(, *.buf)
	}
	// Decide which byte the padding should be filled with.
	 := byte(' ')
	if .zero {
		 = byte('0')
	}
	// Fill padding with padByte.
	 := [:]
	for  := range  {
		[] = 
	}
	*.buf = [:]
}

// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus).
func ( *fmt) ( []byte) {
	if !.widPresent || .wid == 0 {
		.buf.write()
		return
	}
	 := .wid - utf8.RuneCount()
	if !.minus {
		// left padding
		.writePadding()
		.buf.write()
	} else {
		// right padding
		.buf.write()
		.writePadding()
	}
}

// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus).
func ( *fmt) ( string) {
	if !.widPresent || .wid == 0 {
		.buf.writeString()
		return
	}
	 := .wid - utf8.RuneCountInString()
	if !.minus {
		// left padding
		.writePadding()
		.buf.writeString()
	} else {
		// right padding
		.buf.writeString()
		.writePadding()
	}
}

// fmtBoolean formats a boolean.
func ( *fmt) ( bool) {
	if  {
		.padString("true")
	} else {
		.padString("false")
	}
}

// fmtUnicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'".
func ( *fmt) ( uint64) {
	 := .intbuf[0:]

	// With default precision set the maximum needed buf length is 18
	// for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits
	// into the already allocated intbuf with a capacity of 68 bytes.
	 := 4
	if .precPresent && .prec > 4 {
		 = .prec
		// Compute space needed for "U+" , number, " '", character, "'".
		 := 2 +  + 2 + utf8.UTFMax + 1
		if  > len() {
			 = make([]byte, )
		}
	}

	// Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
	 := len()

	// For %#U we want to add a space and a quoted character at the end of the buffer.
	if .sharp &&  <= utf8.MaxRune && strconv.IsPrint(rune()) {
		--
		[] = '\''
		 -= utf8.RuneLen(rune())
		utf8.EncodeRune([:], rune())
		--
		[] = '\''
		--
		[] = ' '
	}
	// Format the Unicode code point u as a hexadecimal number.
	for  >= 16 {
		--
		[] = udigits[&0xF]
		--
		 >>= 4
	}
	--
	[] = udigits[]
	--
	// Add zeros in front of the number until requested precision is reached.
	for  > 0 {
		--
		[] = '0'
		--
	}
	// Add a leading "U+".
	--
	[] = '+'
	--
	[] = 'U'

	 := .zero
	.zero = false
	.pad([:])
	.zero = 
}

// fmtInteger formats signed and unsigned integers.
func ( *fmt) ( uint64,  int,  bool,  rune,  string) {
	 :=  && int64() < 0
	if  {
		 = -
	}

	 := .intbuf[0:]
	// The already allocated f.intbuf with a capacity of 68 bytes
	// is large enough for integer formatting when no precision or width is set.
	if .widPresent || .precPresent {
		// Account 3 extra bytes for possible addition of a sign and "0x".
		 := 3 + .wid + .prec // wid and prec are always positive.
		if  > len() {
			// We're going to need a bigger boat.
			 = make([]byte, )
		}
	}

	// Two ways to ask for extra leading zero digits: %.3d or %03d.
	// If both are specified the f.zero flag is ignored and
	// padding with spaces is used instead.
	 := 0
	if .precPresent {
		 = .prec
		// Precision of 0 and value of 0 means "print nothing" but padding.
		if  == 0 &&  == 0 {
			 := .zero
			.zero = false
			.writePadding(.wid)
			.zero = 
			return
		}
	} else if .zero && .widPresent {
		 = .wid
		if  || .plus || .space {
			-- // leave room for sign
		}
	}

	// Because printing is easier right-to-left: format u into buf, ending at buf[i].
	// We could make things marginally faster by splitting the 32-bit case out
	// into a separate block but it's not worth the duplication, so u has 64 bits.
	 := len()
	// Use constants for the division and modulo for more efficient code.
	// Switch cases ordered by popularity.
	switch  {
	case 10:
		for  >= 10 {
			--
			 :=  / 10
			[] = byte('0' +  - *10)
			 = 
		}
	case 16:
		for  >= 16 {
			--
			[] = [&0xF]
			 >>= 4
		}
	case 8:
		for  >= 8 {
			--
			[] = byte('0' + &7)
			 >>= 3
		}
	case 2:
		for  >= 2 {
			--
			[] = byte('0' + &1)
			 >>= 1
		}
	default:
		panic("fmt: unknown base; can't happen")
	}
	--
	[] = []
	for  > 0 &&  > len()- {
		--
		[] = '0'
	}

	// Various prefixes: 0x, -, etc.
	if .sharp {
		switch  {
		case 2:
			// Add a leading 0b.
			--
			[] = 'b'
			--
			[] = '0'
		case 8:
			if [] != '0' {
				--
				[] = '0'
			}
		case 16:
			// Add a leading 0x or 0X.
			--
			[] = [16]
			--
			[] = '0'
		}
	}
	if  == 'O' {
		--
		[] = 'o'
		--
		[] = '0'
	}

	if  {
		--
		[] = '-'
	} else if .plus {
		--
		[] = '+'
	} else if .space {
		--
		[] = ' '
	}

	// Left padding with zeros has already been handled like precision earlier
	// or the f.zero flag is ignored due to an explicitly set precision.
	 := .zero
	.zero = false
	.pad([:])
	.zero = 
}

// truncateString truncates the string s to the specified precision, if present.
func ( *fmt) ( string) string {
	if .precPresent {
		 := .prec
		for  := range  {
			--
			if  < 0 {
				return [:]
			}
		}
	}
	return 
}

// truncate truncates the byte slice b as a string of the specified precision, if present.
func ( *fmt) ( []byte) []byte {
	if .precPresent {
		 := .prec
		for  := 0;  < len(); {
			--
			if  < 0 {
				return [:]
			}
			 := 1
			if [] >= utf8.RuneSelf {
				_,  = utf8.DecodeRune([:])
			}
			 += 
		}
	}
	return 
}

// fmtS formats a string.
func ( *fmt) ( string) {
	 = .truncateString()
	.padString()
}

// fmtBs formats the byte slice b as if it was formatted as string with fmtS.
func ( *fmt) ( []byte) {
	 = .truncate()
	.pad()
}

// fmtSbx formats a string or byte slice as a hexadecimal encoding of its bytes.
func ( *fmt) ( string,  []byte,  string) {
	 := len()
	if  == nil {
		// No byte slice present. Assume string s should be encoded.
		 = len()
	}
	// Set length to not process more bytes than the precision demands.
	if .precPresent && .prec <  {
		 = .prec
	}
	// Compute width of the encoding taking into account the f.sharp and f.space flag.
	 := 2 * 
	if  > 0 {
		if .space {
			// Each element encoded by two hexadecimals will get a leading 0x or 0X.
			if .sharp {
				 *= 2
			}
			// Elements will be separated by a space.
			 +=  - 1
		} else if .sharp {
			// Only a leading 0x or 0X will be added for the whole string.
			 += 2
		}
	} else { // The byte slice or string that should be encoded is empty.
		if .widPresent {
			.writePadding(.wid)
		}
		return
	}
	// Handle padding to the left.
	if .widPresent && .wid >  && !.minus {
		.writePadding(.wid - )
	}
	// Write the encoding directly into the output buffer.
	 := *.buf
	if .sharp {
		// Add leading 0x or 0X.
		 = append(, '0', [16])
	}
	var  byte
	for  := 0;  < ; ++ {
		if .space &&  > 0 {
			// Separate elements with a space.
			 = append(, ' ')
			if .sharp {
				// Add leading 0x or 0X for each element.
				 = append(, '0', [16])
			}
		}
		if  != nil {
			 = [] // Take a byte from the input byte slice.
		} else {
			 = [] // Take a byte from the input string.
		}
		// Encode each byte as two hexadecimal digits.
		 = append(, [>>4], [&0xF])
	}
	*.buf = 
	// Handle padding to the right.
	if .widPresent && .wid >  && .minus {
		.writePadding(.wid - )
	}
}

// fmtSx formats a string as a hexadecimal encoding of its bytes.
func ( *fmt) (,  string) {
	.fmtSbx(, nil, )
}

// fmtBx formats a byte slice as a hexadecimal encoding of its bytes.
func ( *fmt) ( []byte,  string) {
	.fmtSbx("", , )
}

// fmtQ formats a string as a double-quoted, escaped Go string constant.
// If f.sharp is set a raw (backquoted) string may be returned instead
// if the string does not contain any control characters other than tab.
func ( *fmt) ( string) {
	 = .truncateString()
	if .sharp && strconv.CanBackquote() {
		.padString("`" +  + "`")
		return
	}
	 := .intbuf[:0]
	if .plus {
		.pad(strconv.AppendQuoteToASCII(, ))
	} else {
		.pad(strconv.AppendQuote(, ))
	}
}

// fmtC formats an integer as a Unicode character.
// If the character is not valid Unicode, it will print '\ufffd'.
func ( *fmt) ( uint64) {
	// Explicitly check whether c exceeds utf8.MaxRune since the conversion
	// of a uint64 to a rune may lose precision that indicates an overflow.
	 := rune()
	if  > utf8.MaxRune {
		 = utf8.RuneError
	}
	 := .intbuf[:0]
	.pad(utf8.AppendRune(, ))
}

// fmtQc formats an integer as a single-quoted, escaped Go character constant.
// If the character is not valid Unicode, it will print '\ufffd'.
func ( *fmt) ( uint64) {
	 := rune()
	if  > utf8.MaxRune {
		 = utf8.RuneError
	}
	 := .intbuf[:0]
	if .plus {
		.pad(strconv.AppendQuoteRuneToASCII(, ))
	} else {
		.pad(strconv.AppendQuoteRune(, ))
	}
}

// fmtFloat formats a float64. It assumes that verb is a valid format specifier
// for strconv.AppendFloat and therefore fits into a byte.
func ( *fmt) ( float64,  int,  rune,  int) {
	// Explicit precision in format specifier overrules default precision.
	if .precPresent {
		 = .prec
	}
	// Format number, reserving space for leading + sign if needed.
	 := strconv.AppendFloat(.intbuf[:1], , byte(), , )
	if [1] == '-' || [1] == '+' {
		 = [1:]
	} else {
		[0] = '+'
	}
	// f.space means to add a leading space instead of a "+" sign unless
	// the sign is explicitly asked for by f.plus.
	if .space && [0] == '+' && !.plus {
		[0] = ' '
	}
	// Special handling for infinities and NaN,
	// which don't look like a number so shouldn't be padded with zeros.
	if [1] == 'I' || [1] == 'N' {
		 := .zero
		.zero = false
		// Remove sign before NaN if not asked for.
		if [1] == 'N' && !.space && !.plus {
			 = [1:]
		}
		.pad()
		.zero = 
		return
	}
	// The sharp flag forces printing a decimal point for non-binary formats
	// and retains trailing zeros, which we may need to restore.
	if .sharp &&  != 'b' {
		 := 0
		switch  {
		case 'v', 'g', 'G', 'x':
			 = 
			// If no precision is set explicitly use a precision of 6.
			if  == -1 {
				 = 6
			}
		}

		// Buffer pre-allocated with enough room for
		// exponent notations of the form "e+123" or "p-1023".
		var  [6]byte
		 := [:0]

		 := false
		 := false
		// Starting from i = 1 to skip sign at num[0].
		for  := 1;  < len(); ++ {
			switch [] {
			case '.':
				 = true
			case 'p', 'P':
				 = append(, [:]...)
				 = [:]
			case 'e', 'E':
				if  != 'x' &&  != 'X' {
					 = append(, [:]...)
					 = [:]
					break
				}
				fallthrough
			default:
				if [] != '0' {
					 = true
				}
				// Count significant digits after the first non-zero digit.
				if  {
					--
				}
			}
		}
		if ! {
			// Leading digit 0 should contribute once to digits.
			if len() == 2 && [1] == '0' {
				--
			}
			 = append(, '.')
		}
		for  > 0 {
			 = append(, '0')
			--
		}
		 = append(, ...)
	}
	// We want a sign if asked for and if the sign is not positive.
	if .plus || [0] != '+' {
		// If we're zero padding to the left we want the sign before the leading zeros.
		// Achieve this by writing the sign out and then padding the unsigned number.
		if .zero && .widPresent && .wid > len() {
			.buf.writeByte([0])
			.writePadding(.wid - len())
			.buf.write([1:])
			return
		}
		.pad()
		return
	}
	// No sign to show and the number is positive; just print the unsigned number.
	.pad([1:])
}