// 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 strconv

import 

// lower(c) is a lower-case letter if and only if
// c is either that lower-case letter or the equivalent upper-case letter.
// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'.
// Note that lower of non-letters can produce other non-letters.
func lower( byte) byte {
	return  | ('x' - 'X')
}

// ErrRange indicates that a value is out of range for the target type.
var ErrRange = errors.New("value out of range")

// ErrSyntax indicates that a value does not have the right syntax for the target type.
var ErrSyntax = errors.New("invalid syntax")

// A NumError records a failed conversion.
type NumError struct {
	Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat, ParseComplex)
	Num  string // the input
	Err  error  // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
}

func ( *NumError) () string {
	return "strconv." + .Func + ": " + "parsing " + Quote(.Num) + ": " + .Err.Error()
}

func ( *NumError) () error { return .Err }

// cloneString returns a string copy of x.
//
// All ParseXXX functions allow the input string to escape to the error value.
// This hurts strconv.ParseXXX(string(b)) calls where b is []byte since
// the conversion from []byte must allocate a string on the heap.
// If we assume errors are infrequent, then we can avoid escaping the input
// back to the output by copying it first. This allows the compiler to call
// strconv.ParseXXX without a heap allocation for most []byte to string
// conversions, since it can now prove that the string cannot escape Parse.
//
// TODO: Use strings.Clone instead? However, we cannot depend on "strings"
// since it incurs a transitive dependency on "unicode".
// Either move strings.Clone to an internal/bytealg or make the
// "strings" to "unicode" dependency lighter (see https://go.dev/issue/54098).
func cloneString( string) string { return string([]byte()) }

func syntaxError(,  string) *NumError {
	return &NumError{, cloneString(), ErrSyntax}
}

func rangeError(,  string) *NumError {
	return &NumError{, cloneString(), ErrRange}
}

func baseError(,  string,  int) *NumError {
	return &NumError{, cloneString(), errors.New("invalid base " + Itoa())}
}

func bitSizeError(,  string,  int) *NumError {
	return &NumError{, cloneString(), errors.New("invalid bit size " + Itoa())}
}

const intSize = 32 << (^uint(0) >> 63)

// IntSize is the size in bits of an int or uint value.
const IntSize = intSize

const maxUint64 = 1<<64 - 1

// ParseUint is like ParseInt but for unsigned numbers.
//
// A sign prefix is not permitted.
func ( string,  int,  int) (uint64, error) {
	const  = "ParseUint"

	if  == "" {
		return 0, syntaxError(, )
	}

	 :=  == 0

	 := 
	switch {
	case 2 <=  &&  <= 36:
		// valid base; nothing to do

	case  == 0:
		// Look for octal, hex prefix.
		 = 10
		if [0] == '0' {
			switch {
			case len() >= 3 && lower([1]) == 'b':
				 = 2
				 = [2:]
			case len() >= 3 && lower([1]) == 'o':
				 = 8
				 = [2:]
			case len() >= 3 && lower([1]) == 'x':
				 = 16
				 = [2:]
			default:
				 = 8
				 = [1:]
			}
		}

	default:
		return 0, baseError(, , )
	}

	if  == 0 {
		 = IntSize
	} else if  < 0 ||  > 64 {
		return 0, bitSizeError(, , )
	}

	// Cutoff is the smallest number such that cutoff*base > maxUint64.
	// Use compile-time constants for common cases.
	var  uint64
	switch  {
	case 10:
		 = maxUint64/10 + 1
	case 16:
		 = maxUint64/16 + 1
	default:
		 = maxUint64/uint64() + 1
	}

	 := uint64(1)<<uint() - 1

	 := false
	var  uint64
	for ,  := range []byte() {
		var  byte
		switch {
		case  == '_' && :
			 = true
			continue
		case '0' <=  &&  <= '9':
			 =  - '0'
		case 'a' <= lower() && lower() <= 'z':
			 = lower() - 'a' + 10
		default:
			return 0, syntaxError(, )
		}

		if  >= byte() {
			return 0, syntaxError(, )
		}

		if  >=  {
			// n*base overflows
			return , rangeError(, )
		}
		 *= uint64()

		 :=  + uint64()
		if  <  ||  >  {
			// n+d overflows
			return , rangeError(, )
		}
		 = 
	}

	if  && !underscoreOK() {
		return 0, syntaxError(, )
	}

	return , nil
}

// ParseInt interprets a string s in the given base (0, 2 to 36) and
// bit size (0 to 64) and returns the corresponding value i.
//
// The string may begin with a leading sign: "+" or "-".
//
// If the base argument is 0, the true base is implied by the string's
// prefix following the sign (if present): 2 for "0b", 8 for "0" or "0o",
// 16 for "0x", and 10 otherwise. Also, for argument base 0 only,
// underscore characters are permitted as defined by the Go syntax for
// [integer literals].
//
// The bitSize argument specifies the integer type
// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
// correspond to int, int8, int16, int32, and int64.
// If bitSize is below 0 or above 64, an error is returned.
//
// The errors that ParseInt returns have concrete type *NumError
// and include err.Num = s. If s is empty or contains invalid
// digits, err.Err = ErrSyntax and the returned value is 0;
// if the value corresponding to s cannot be represented by a
// signed integer of the given size, err.Err = ErrRange and the
// returned value is the maximum magnitude integer of the
// appropriate bitSize and sign.
//
// [integer literals]: https://go.dev/ref/spec#Integer_literals
func ( string,  int,  int) ( int64,  error) {
	const  = "ParseInt"

	if  == "" {
		return 0, syntaxError(, )
	}

	// Pick off leading sign.
	 := 
	 := false
	if [0] == '+' {
		 = [1:]
	} else if [0] == '-' {
		 = true
		 = [1:]
	}

	// Convert unsigned and check range.
	var  uint64
	,  = ParseUint(, , )
	if  != nil && .(*NumError).Err != ErrRange {
		.(*NumError).Func = 
		.(*NumError).Num = cloneString()
		return 0, 
	}

	if  == 0 {
		 = IntSize
	}

	 := uint64(1 << uint(-1))
	if ! &&  >=  {
		return int64( - 1), rangeError(, )
	}
	if  &&  >  {
		return -int64(), rangeError(, )
	}
	 := int64()
	if  {
		 = -
	}
	return , nil
}

// Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.
func ( string) (int, error) {
	const  = "Atoi"

	 := len()
	if intSize == 32 && (0 <  &&  < 10) ||
		intSize == 64 && (0 <  &&  < 19) {
		// Fast path for small integers that fit int type.
		 := 
		if [0] == '-' || [0] == '+' {
			 = [1:]
			if len() < 1 {
				return 0, syntaxError(, )
			}
		}

		 := 0
		for ,  := range []byte() {
			 -= '0'
			if  > 9 {
				return 0, syntaxError(, )
			}
			 = *10 + int()
		}
		if [0] == '-' {
			 = -
		}
		return , nil
	}

	// Slow path for invalid, big, or underscored integers.
	,  := ParseInt(, 10, 0)
	if ,  := .(*NumError);  {
		.Func = 
	}
	return int(), 
}

// underscoreOK reports whether the underscores in s are allowed.
// Checking them in this one function lets all the parsers skip over them simply.
// Underscore must appear only between digits or between a base prefix and a digit.
func underscoreOK( string) bool {
	// saw tracks the last character (class) we saw:
	// ^ for beginning of number,
	// 0 for a digit or base prefix,
	// _ for an underscore,
	// ! for none of the above.
	 := '^'
	 := 0

	// Optional sign.
	if len() >= 1 && ([0] == '-' || [0] == '+') {
		 = [1:]
	}

	// Optional base prefix.
	 := false
	if len() >= 2 && [0] == '0' && (lower([1]) == 'b' || lower([1]) == 'o' || lower([1]) == 'x') {
		 = 2
		 = '0' // base prefix counts as a digit for "underscore as digit separator"
		 = lower([1]) == 'x'
	}

	// Number proper.
	for ;  < len(); ++ {
		// Digits are always okay.
		if '0' <= [] && [] <= '9' ||  && 'a' <= lower([]) && lower([]) <= 'f' {
			 = '0'
			continue
		}
		// Underscore must follow digit.
		if [] == '_' {
			if  != '0' {
				return false
			}
			 = '_'
			continue
		}
		// Underscore must also be followed by digit.
		if  == '_' {
			return false
		}
		// Saw non-digit, non-underscore.
		 = '!'
	}
	return  != '_'
}