// Copyright 2015 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.

// This file implements int-to-string conversion functions.

package big

import (
	
	
	
)

// Text returns the string representation of x in the given base.
// Base must be between 2 and 62, inclusive. The result uses the
// lower-case letters 'a' to 'z' for digit values 10 to 35, and
// the upper-case letters 'A' to 'Z' for digit values 36 to 61.
// No prefix (such as "0x") is added to the string. If x is a nil
// pointer it returns "<nil>".
func ( *Int) ( int) string {
	if  == nil {
		return "<nil>"
	}
	return string(.abs.itoa(.neg, ))
}

// Append appends the string representation of x, as generated by
// x.Text(base), to buf and returns the extended buffer.
func ( *Int) ( []byte,  int) []byte {
	if  == nil {
		return append(, "<nil>"...)
	}
	return append(, .abs.itoa(.neg, )...)
}

// String returns the decimal representation of x as generated by
// x.Text(10).
func ( *Int) () string {
	return .Text(10)
}

// write count copies of text to s.
func writeMultiple( fmt.State,  string,  int) {
	if len() > 0 {
		 := []byte()
		for ;  > 0; -- {
			.Write()
		}
	}
}

var _ fmt.Formatter = intOne // *Int must implement fmt.Formatter

// Format implements [fmt.Formatter]. It accepts the formats
// 'b' (binary), 'o' (octal with 0 prefix), 'O' (octal with 0o prefix),
// 'd' (decimal), 'x' (lowercase hexadecimal), and
// 'X' (uppercase hexadecimal).
// Also supported are the full suite of package fmt's format
// flags for integral types, including '+' and ' ' for sign
// control, '#' for leading zero in octal and for hexadecimal,
// a leading "0x" or "0X" for "%#x" and "%#X" respectively,
// specification of minimum digits precision, output field
// width, space or zero padding, and '-' for left or right
// justification.
func ( *Int) ( fmt.State,  rune) {
	// determine base
	var  int
	switch  {
	case 'b':
		 = 2
	case 'o', 'O':
		 = 8
	case 'd', 's', 'v':
		 = 10
	case 'x', 'X':
		 = 16
	default:
		// unknown format
		fmt.Fprintf(, "%%!%c(big.Int=%s)", , .String())
		return
	}

	if  == nil {
		fmt.Fprint(, "<nil>")
		return
	}

	// determine sign character
	 := ""
	switch {
	case .neg:
		 = "-"
	case .Flag('+'): // supersedes ' ' when both specified
		 = "+"
	case .Flag(' '):
		 = " "
	}

	// determine prefix characters for indicating output base
	 := ""
	if .Flag('#') {
		switch  {
		case 'b': // binary
			 = "0b"
		case 'o': // octal
			 = "0"
		case 'x': // hexadecimal
			 = "0x"
		case 'X':
			 = "0X"
		}
	}
	if  == 'O' {
		 = "0o"
	}

	 := .abs.utoa()
	if  == 'X' {
		// faster than bytes.ToUpper
		for ,  := range  {
			if 'a' <=  &&  <= 'z' {
				[] = 'A' + ( - 'a')
			}
		}
	}

	// number of characters for the three classes of number padding
	var  int  // space characters to left of digits for right justification ("%8d")
	var  int // zero characters (actually cs[0]) as left-most digits ("%.8d")
	var  int // space characters to right of digits for left justification ("%-8d")

	// determine number padding from precision: the least number of digits to output
	,  := .Precision()
	if  {
		switch {
		case len() < :
			 =  - len() // count of zero padding
		case len() == 1 && [0] == '0' &&  == 0:
			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
		}
	}

	// determine field pad from width: the least number of characters to output
	 := len() + len() +  + len()
	if ,  := .Width();  &&  <  { // pad as specified
		switch  :=  - ; {
		case .Flag('-'):
			// pad on the right with spaces; supersedes '0' when both specified
			 = 
		case .Flag('0') && !:
			// pad with zeros unless precision also specified
			 = 
		default:
			// pad on the left with spaces
			 = 
		}
	}

	// print number as [left pad][sign][prefix][zero pad][digits][right pad]
	writeMultiple(, " ", )
	writeMultiple(, , 1)
	writeMultiple(, , 1)
	writeMultiple(, "0", )
	.Write()
	writeMultiple(, " ", )
}

// scan sets z to the integer value corresponding to the longest possible prefix
// read from r representing a signed integer number in a given conversion base.
// It returns z, the actual conversion base used, and an error, if any. In the
// error case, the value of z is undefined but the returned value is nil. The
// syntax follows the syntax of integer literals in Go.
//
// The base argument must be 0 or a value from 2 through MaxBase. If the base
// is 0, the string prefix determines the actual conversion base. A prefix of
// “0b” or “0B” selects base 2; a “0”, “0o”, or “0O” prefix selects
// base 8, and a “0x” or “0X” prefix selects base 16. Otherwise the selected
// base is 10.
func ( *Int) ( io.ByteScanner,  int) (*Int, int, error) {
	// determine sign
	,  := scanSign()
	if  != nil {
		return nil, 0, 
	}

	// determine mantissa
	.abs, , _,  = .abs.scan(, , false)
	if  != nil {
		return nil, , 
	}
	.neg = len(.abs) > 0 &&  // 0 has no sign

	return , , nil
}

func scanSign( io.ByteScanner) ( bool,  error) {
	var  byte
	if ,  = .ReadByte();  != nil {
		return false, 
	}
	switch  {
	case '-':
		 = true
	case '+':
		// nothing to do
	default:
		.UnreadByte()
	}
	return
}

// byteReader is a local wrapper around fmt.ScanState;
// it implements the ByteReader interface.
type byteReader struct {
	fmt.ScanState
}

func ( byteReader) () (byte, error) {
	, ,  := .ReadRune()
	if  != 1 &&  == nil {
		 = fmt.Errorf("invalid rune %#U", )
	}
	return byte(), 
}

func ( byteReader) () error {
	return .UnreadRune()
}

var _ fmt.Scanner = intOne // *Int must implement fmt.Scanner

// Scan is a support routine for [fmt.Scanner]; it sets z to the value of
// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
func ( *Int) ( fmt.ScanState,  rune) error {
	.SkipSpace() // skip leading space characters
	 := 0
	switch  {
	case 'b':
		 = 2
	case 'o':
		 = 8
	case 'd':
		 = 10
	case 'x', 'X':
		 = 16
	case 's', 'v':
		// let scan determine the base
	default:
		return errors.New("Int.Scan: invalid verb")
	}
	, ,  := .scan(byteReader{}, )
	return 
}