//go:generate go run bytesconv_table_gen.go

package fasthttp

import (
	
	
	
	
	
	
	
	
	
)

// AppendHTMLEscape appends html-escaped s to dst and returns the extended dst.
func ( []byte,  string) []byte {
	var (
		 int
		  string
	)

	for ,  := 0, len();  < ; ++ {
		 = ""
		switch [] {
		case '&':
			 = "&amp;"
		case '<':
			 = "&lt;"
		case '>':
			 = "&gt;"
		case '"':
			 = "&#34;" // "&#34;" is shorter than "&quot;".
		case '\'':
			 = "&#39;" // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
		}
		if len() > 0 {
			 = append(, [:]...)
			 = append(, ...)
			 =  + 1
		}
	}
	return append(, [:]...)
}

// AppendHTMLEscapeBytes appends html-escaped s to dst and returns
// the extended dst.
func (,  []byte) []byte {
	return AppendHTMLEscape(, b2s())
}

// AppendIPv4 appends string representation of the given ip v4 to dst
// and returns the extended dst.
func ( []byte,  net.IP) []byte {
	 = .To4()
	if  == nil {
		return append(, "non-v4 ip passed to AppendIPv4"...)
	}

	 = AppendUint(, int([0]))
	for  := 1;  < 4; ++ {
		 = append(, '.')
		 = AppendUint(, int([]))
	}
	return 
}

var errEmptyIPStr = errors.New("empty ip address string")

// ParseIPv4 parses ip address from ipStr into dst and returns the extended dst.
func ( net.IP,  []byte) (net.IP, error) {
	if len() == 0 {
		return , errEmptyIPStr
	}
	if len() < net.IPv4len {
		 = make([]byte, net.IPv4len)
	}
	copy(, net.IPv4zero)
	 = .To4()
	if  == nil {
		// developer sanity-check
		panic("BUG: dst must not be nil")
	}

	 := 
	for  := 0;  < 3; ++ {
		 := bytes.IndexByte(, '.')
		if  < 0 {
			return , fmt.Errorf("cannot find dot in ipStr %q", )
		}
		,  := ParseUint([:])
		if  != nil {
			return , fmt.Errorf("cannot parse ipStr %q: %w", , )
		}
		if  > 255 {
			return , fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", , )
		}
		[] = byte()
		 = [+1:]
	}
	,  := ParseUint()
	if  != nil {
		return , fmt.Errorf("cannot parse ipStr %q: %w", , )
	}
	if  > 255 {
		return , fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", , )
	}
	[3] = byte()

	return , nil
}

// AppendHTTPDate appends HTTP-compliant (RFC1123) representation of date
// to dst and returns the extended dst.
func ( []byte,  time.Time) []byte {
	 = .In(time.UTC).AppendFormat(, time.RFC1123)
	copy([len()-3:], strGMT)
	return 
}

// ParseHTTPDate parses HTTP-compliant (RFC1123) date.
func ( []byte) (time.Time, error) {
	return time.Parse(time.RFC1123, b2s())
}

// AppendUint appends n to dst and returns the extended dst.
func ( []byte,  int) []byte {
	if  < 0 {
		// developer sanity-check
		panic("BUG: int must be positive")
	}

	var  [20]byte
	 := [:]
	 := len()
	var  int
	for  >= 10 {
		--
		 =  / 10
		[] = '0' + byte(-*10)
		 = 
	}
	--
	[] = '0' + byte()

	 = append(, [:]...)
	return 
}

// ParseUint parses uint from buf.
func ( []byte) (int, error) {
	, ,  := parseUintBuf()
	if  != len() {
		return -1, errUnexpectedTrailingChar
	}
	return , 
}

var (
	errEmptyInt               = errors.New("empty integer")
	errUnexpectedFirstChar    = errors.New("unexpected first char found. Expecting 0-9")
	errUnexpectedTrailingChar = errors.New("unexpected trailing char found. Expecting 0-9")
	errTooLongInt             = errors.New("too long int")
)

func parseUintBuf( []byte) (int, int, error) {
	 := len()
	if  == 0 {
		return -1, 0, errEmptyInt
	}
	 := 0
	for  := 0;  < ; ++ {
		 := []
		 :=  - '0'
		if  > 9 {
			if  == 0 {
				return -1, , errUnexpectedFirstChar
			}
			return , , nil
		}
		 := 10* + int()
		// Test for overflow.
		if  <  {
			return -1, , errTooLongInt
		}
		 = 
	}
	return , , nil
}

var (
	errEmptyFloat           = errors.New("empty float number")
	errDuplicateFloatPoint  = errors.New("duplicate point found in float number")
	errUnexpectedFloatEnd   = errors.New("unexpected end of float number")
	errInvalidFloatExponent = errors.New("invalid float number exponent")
	errUnexpectedFloatChar  = errors.New("unexpected char found in float number")
)

// ParseUfloat parses unsigned float from buf.
func ( []byte) (float64, error) {
	if len() == 0 {
		return -1, errEmptyFloat
	}
	 := 
	var  uint64
	 := 1.0
	var  bool
	for ,  := range  {
		if  < '0' ||  > '9' {
			if  == '.' {
				if  {
					return -1, errDuplicateFloatPoint
				}
				 = true
				continue
			}
			if  == 'e' ||  == 'E' {
				if +1 >= len() {
					return -1, errUnexpectedFloatEnd
				}
				 = [+1:]
				 := -1
				switch [0] {
				case '+':
					 = [1:]
					 = 1
				case '-':
					 = [1:]
				default:
					 = 1
				}
				,  := ParseUint()
				if  != nil {
					return -1, errInvalidFloatExponent
				}
				return float64() *  * math.Pow10(*), nil
			}
			return -1, errUnexpectedFloatChar
		}
		 = 10* + uint64(-'0')
		if  {
			 /= 10
		}
	}
	return float64() * , nil
}

var (
	errEmptyHexNum    = errors.New("empty hex number")
	errTooLargeHexNum = errors.New("too large hex number")
)

func readHexInt( *bufio.Reader) (int, error) {
	var , ,  int
	for {
		,  := .ReadByte()
		if  != nil {
			if  == io.EOF &&  > 0 {
				return , nil
			}
			return -1, 
		}
		 = int(hex2intTable[])
		if  == 16 {
			if  == 0 {
				return -1, errEmptyHexNum
			}
			if  := .UnreadByte();  != nil {
				return -1, 
			}
			return , nil
		}
		if  >= maxHexIntChars {
			return -1, errTooLargeHexNum
		}
		 = ( << 4) | 
		++
	}
}

var hexIntBufPool sync.Pool

func writeHexInt( *bufio.Writer,  int) error {
	if  < 0 {
		// developer sanity-check
		panic("BUG: int must be positive")
	}

	 := hexIntBufPool.Get()
	if  == nil {
		 = make([]byte, maxHexIntChars+1)
	}
	 := .([]byte)
	 := len() - 1
	for {
		[] = lowerhex[&0xf]
		 >>= 4
		if  == 0 {
			break
		}
		--
	}
	,  := .Write([:])
	hexIntBufPool.Put()
	return 
}

const (
	upperhex = "0123456789ABCDEF"
	lowerhex = "0123456789abcdef"
)

func lowercaseBytes( []byte) {
	for  := 0;  < len(); ++ {
		 := &[]
		* = toLowerTable[*]
	}
}

// AppendUnquotedArg appends url-decoded src to dst and returns appended dst.
//
// dst may point to src. In this case src will be overwritten.
func (,  []byte) []byte {
	return decodeArgAppend(, )
}

// AppendQuotedArg appends url-encoded src to dst and returns appended dst.
func (,  []byte) []byte {
	for ,  := range  {
		switch {
		case  == ' ':
			 = append(, '+')
		case quotedArgShouldEscapeTable[int()] != 0:
			 = append(, '%', upperhex[>>4], upperhex[&0xf])
		default:
			 = append(, )
		}
	}
	return 
}

func appendQuotedPath(,  []byte) []byte {
	// Fix issue in https://github.com/golang/go/issues/11202
	if len() == 1 && [0] == '*' {
		return append(, '*')
	}

	for ,  := range  {
		if quotedPathShouldEscapeTable[int()] != 0 {
			 = append(, '%', upperhex[>>4], upperhex[&0xf])
		} else {
			 = append(, )
		}
	}
	return 
}