package jx

import (
	
	
	

	
)

// StrAppend reads string and appends it to byte slice.
func ( *Decoder) ( []byte) ([]byte, error) {
	 := value{
		buf: ,
		raw: false,
	}
	var  error
	if ,  = .str();  != nil {
		return , 
	}
	return .buf, nil
}

type value struct {
	buf []byte
	raw bool // false forces buf reuse
}

func ( value) ( rune) value {
	return value{
		buf: appendRune(.buf, ),
		raw: .raw,
	}
}

func ( *Decoder) ( value) (value, error) {
	if  := .consume('"');  != nil {
		return value{}, 
	}
	var (
		 byte
		 int
	)
	for {
		 := .buf[.head:.tail]
		for len() >= 8 {
			 = [0]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [1]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [2]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [3]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [4]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [5]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [6]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [7]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [8:]
		}
		var  int
		for ,  = range  {
			if safeSet[] != 0 {
				 += 
				goto 
			}
		}
		return .strSlow()
	}
:
	 := .buf[.head:.tail]
	 := [:]

	switch {
	case  == '"':
		// Skip string + last quote.
		.head +=  + 1
		if .raw {
			return value{buf: , raw: true}, nil
		}
		return value{buf: append(.buf, ...)}, nil
	case  == '\\':
		// Skip only string, keep quote in buffer.
		.head += 
		// We need a copy anyway, because string is escaped.
		return .strSlow(value{buf: append(.buf, ...)})
	default:
		return , badToken(, .offset()+)
	}
}

func ( *Decoder) ( value) (value, error) {
	var (
		 byte
		 int
	)
:
	for {
		 = 0
		 := .buf[.head:.tail]
		for len() >= 8 {
			 = [0]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [1]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [2]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [3]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [4]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [5]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [6]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [7]
			if safeSet[] != 0 {
				goto 
			}
			++

			 = [8:]
		}
		for _,  = range  {
			if safeSet[] != 0 {
				goto 
			}
			++
		}

		.buf = append(.buf, .buf[.head:.head+]...)
		if  := .read();  != nil {
			if  == io.EOF {
				return value{}, io.ErrUnexpectedEOF
			}
			return value{}, 
		}
	}
:
	 := .buf[.head:.tail]
	 := [:]
	.head +=  + 1

	switch {
	case  == '"':
		return value{buf: append(.buf, ...)}, nil
	case  == '\\':
		.buf = append(.buf, ...)
		,  := .byte()
		if  != nil {
			return value{}, 
		}
		,  = .escapedChar(, )
		if  != nil {
			return , errors.Wrap(, "escape")
		}
	default:
		return , badToken(, .offset()-1)
	}
	goto 
}

// StrBytes returns string value as sub-slice of internal buffer.
//
// Bytes are valid only until next call to any Decoder method.
func ( *Decoder) () ([]byte, error) {
	,  := .str(value{raw: true})
	if  != nil {
		return nil, 
	}
	return .buf, nil
}

// Str reads string.
func ( *Decoder) () (string, error) {
	,  := .StrBytes()
	if  != nil {
		return "", 
	}
	return string(), nil
}

func ( *Decoder) ( value,  byte) (value, error) {
	switch  := escapedStrSet[];  {
	default:
		.buf = append(.buf, )
	case 'u':
		,  := .readU4()
		if  != nil {
			return value{}, errors.Wrap(, "read u4")
		}
		if utf16.IsSurrogate() {
			,  := .byte()
			if  != nil {
				return value{}, 
			}
			if  != '\\' {
				.unread()
				return .rune(), nil
			}
			,  = .byte()
			if  != nil {
				return value{}, 
			}
			if  != 'u' {
				return .(.rune(), )
			}
			,  := .readU4()
			if  != nil {
				return value{}, 
			}
			 := utf16.DecodeRune(, )
			if  == '\uFFFD' {
				 = .rune().rune()
			} else {
				 = .rune()
			}
		} else {
			 = .rune()
		}
	case 0:
		 := badToken(, .offset()-1)
		return , errors.Wrap(, "bad escape")
	}
	return , nil
}

func ( *Decoder) () ( rune,  error) {
	var (
		 = .offset()
		      [4]byte
	)
	if  := .readExact4(&);  != nil {
		return 0, 
	}
	for ,  := range  {
		 := hexSet[]
		if  == 0 {
			return 0, badToken(, +)
		}
		 = *16 + rune(-1)
	}
	return , nil
}

func ( []byte,  rune) []byte {
	 := make([]byte, 4)
	 := utf8.EncodeRune(, )
	return append(, [:]...)
}