package jsoniter

import (
	
	
)

// ReadString read string from iterator
func ( *Iterator) () ( string) {
	 := .nextToken()
	if  == '"' {
		for  := .head;  < .tail; ++ {
			 := .buf[]
			if  == '"' {
				 = string(.buf[.head:])
				.head =  + 1
				return 
			} else if  == '\\' {
				break
			} else if  < ' ' {
				.ReportError("ReadString",
					fmt.Sprintf(`invalid control character found: %d`, ))
				return
			}
		}
		return .readStringSlowPath()
	} else if  == 'n' {
		.skipThreeBytes('u', 'l', 'l')
		return ""
	}
	.ReportError("ReadString", `expects " or n, but found `+string([]byte{}))
	return
}

func ( *Iterator) () ( string) {
	var  []byte
	var  byte
	for .Error == nil {
		 = .readByte()
		if  == '"' {
			return string()
		}
		if  == '\\' {
			 = .readByte()
			 = .readEscapedChar(, )
		} else {
			 = append(, )
		}
	}
	.ReportError("readStringSlowPath", "unexpected end of input")
	return
}

func ( *Iterator) ( byte,  []byte) []byte {
	switch  {
	case 'u':
		 := .readU4()
		if utf16.IsSurrogate() {
			 = .readByte()
			if .Error != nil {
				return nil
			}
			if  != '\\' {
				.unreadByte()
				 = appendRune(, )
				return 
			}
			 = .readByte()
			if .Error != nil {
				return nil
			}
			if  != 'u' {
				 = appendRune(, )
				return .(, )
			}
			 := .readU4()
			if .Error != nil {
				return nil
			}
			 := utf16.DecodeRune(, )
			if  == '\uFFFD' {
				 = appendRune(, )
				 = appendRune(, )
			} else {
				 = appendRune(, )
			}
		} else {
			 = appendRune(, )
		}
	case '"':
		 = append(, '"')
	case '\\':
		 = append(, '\\')
	case '/':
		 = append(, '/')
	case 'b':
		 = append(, '\b')
	case 'f':
		 = append(, '\f')
	case 'n':
		 = append(, '\n')
	case 'r':
		 = append(, '\r')
	case 't':
		 = append(, '\t')
	default:
		.ReportError("readEscapedChar",
			`invalid escape char after \`)
		return nil
	}
	return 
}

// ReadStringAsSlice read string from iterator without copying into string form.
// The []byte can not be kept, as it will change after next iterator call.
func ( *Iterator) () ( []byte) {
	 := .nextToken()
	if  == '"' {
		for  := .head;  < .tail; ++ {
			// require ascii string and no escape
			// for: field name, base64, number
			if .buf[] == '"' {
				// fast path: reuse the underlying buffer
				 = .buf[.head:]
				.head =  + 1
				return 
			}
		}
		 := .tail - .head
		 := make([]byte, , *2)
		copy(, .buf[.head:.tail])
		.head = .tail
		for .Error == nil {
			 := .readByte()
			if  == '"' {
				return 
			}
			 = append(, )
		}
		return 
	}
	.ReportError("ReadStringAsSlice", `expects " or n, but found `+string([]byte{}))
	return
}

func ( *Iterator) () ( rune) {
	for  := 0;  < 4; ++ {
		 := .readByte()
		if .Error != nil {
			return
		}
		if  >= '0' &&  <= '9' {
			 = *16 + rune(-'0')
		} else if  >= 'a' &&  <= 'f' {
			 = *16 + rune(-'a'+10)
		} else if  >= 'A' &&  <= 'F' {
			 = *16 + rune(-'A'+10)
		} else {
			.ReportError("readU4", "expects 0~9 or a~f, but found "+string([]byte{}))
			return
		}
	}
	return 
}

const (
	t1 = 0x00 // 0000 0000
	tx = 0x80 // 1000 0000
	t2 = 0xC0 // 1100 0000
	t3 = 0xE0 // 1110 0000
	t4 = 0xF0 // 1111 0000
	t5 = 0xF8 // 1111 1000

	maskx = 0x3F // 0011 1111
	mask2 = 0x1F // 0001 1111
	mask3 = 0x0F // 0000 1111
	mask4 = 0x07 // 0000 0111

	rune1Max = 1<<7 - 1
	rune2Max = 1<<11 - 1
	rune3Max = 1<<16 - 1

	surrogateMin = 0xD800
	surrogateMax = 0xDFFF

	maxRune   = '\U0010FFFF' // Maximum valid Unicode code point.
	runeError = '\uFFFD'     // the "error" Rune or "Unicode replacement character"
)

func appendRune( []byte,  rune) []byte {
	// Negative values are erroneous. Making it unsigned addresses the problem.
	switch  := uint32(); {
	case  <= rune1Max:
		 = append(, byte())
		return 
	case  <= rune2Max:
		 = append(, t2|byte(>>6))
		 = append(, tx|byte()&maskx)
		return 
	case  > maxRune, surrogateMin <=  &&  <= surrogateMax:
		 = runeError
		fallthrough
	case  <= rune3Max:
		 = append(, t3|byte(>>12))
		 = append(, tx|byte(>>6)&maskx)
		 = append(, tx|byte()&maskx)
		return 
	default:
		 = append(, t4|byte(>>18))
		 = append(, tx|byte(>>12)&maskx)
		 = append(, tx|byte(>>6)&maskx)
		 = append(, tx|byte()&maskx)
		return 
	}
}