package fastjson

import (
	
	
	
)

// Validate validates JSON s.
func ( string) error {
	 = skipWS()

	,  := validateValue()
	if  != nil {
		return fmt.Errorf("cannot parse JSON: %s; unparsed tail: %q", , startEndString())
	}
	 = skipWS()
	if len() > 0 {
		return fmt.Errorf("unexpected tail: %q", startEndString())
	}
	return nil
}

// ValidateBytes validates JSON b.
func ( []byte) error {
	return Validate(b2s())
}

func ( string) (string, error) {
	if len() == 0 {
		return , fmt.Errorf("cannot parse empty string")
	}

	if [0] == '{' {
		,  := validateObject([1:])
		if  != nil {
			return , fmt.Errorf("cannot parse object: %s", )
		}
		return , nil
	}
	if [0] == '[' {
		,  := validateArray([1:])
		if  != nil {
			return , fmt.Errorf("cannot parse array: %s", )
		}
		return , nil
	}
	if [0] == '"' {
		, ,  := validateString([1:])
		if  != nil {
			return , fmt.Errorf("cannot parse string: %s", )
		}
		// Scan the string for control chars.
		for  := 0;  < len(); ++ {
			if [] < 0x20 {
				return , fmt.Errorf("string cannot contain control char 0x%02X", [])
			}
		}
		return , nil
	}
	if [0] == 't' {
		if len() < len("true") || [:len("true")] != "true" {
			return , fmt.Errorf("unexpected value found: %q", )
		}
		return [len("true"):], nil
	}
	if [0] == 'f' {
		if len() < len("false") || [:len("false")] != "false" {
			return , fmt.Errorf("unexpected value found: %q", )
		}
		return [len("false"):], nil
	}
	if [0] == 'n' {
		if len() < len("null") || [:len("null")] != "null" {
			return , fmt.Errorf("unexpected value found: %q", )
		}
		return [len("null"):], nil
	}

	,  := validateNumber()
	if  != nil {
		return , fmt.Errorf("cannot parse number: %s", )
	}
	return , nil
}

func ( string) (string, error) {
	 = skipWS()
	if len() == 0 {
		return , fmt.Errorf("missing ']'")
	}
	if [0] == ']' {
		return [1:], nil
	}

	for {
		var  error

		 = skipWS()
		,  = validateValue()
		if  != nil {
			return , fmt.Errorf("cannot parse array value: %s", )
		}

		 = skipWS()
		if len() == 0 {
			return , fmt.Errorf("unexpected end of array")
		}
		if [0] == ',' {
			 = [1:]
			continue
		}
		if [0] == ']' {
			 = [1:]
			return , nil
		}
		return , fmt.Errorf("missing ',' after array value")
	}
}

func ( string) (string, error) {
	 = skipWS()
	if len() == 0 {
		return , fmt.Errorf("missing '}'")
	}
	if [0] == '}' {
		return [1:], nil
	}

	for {
		var  error

		// Parse key.
		 = skipWS()
		if len() == 0 || [0] != '"' {
			return , fmt.Errorf(`cannot find opening '"" for object key`)
		}

		var  string
		, ,  = validateKey([1:])
		if  != nil {
			return , fmt.Errorf("cannot parse object key: %s", )
		}
		// Scan the key for control chars.
		for  := 0;  < len(); ++ {
			if [] < 0x20 {
				return , fmt.Errorf("object key cannot contain control char 0x%02X", [])
			}
		}
		 = skipWS()
		if len() == 0 || [0] != ':' {
			return , fmt.Errorf("missing ':' after object key")
		}
		 = [1:]

		// Parse value
		 = skipWS()
		,  = validateValue()
		if  != nil {
			return , fmt.Errorf("cannot parse object value: %s", )
		}
		 = skipWS()
		if len() == 0 {
			return , fmt.Errorf("unexpected end of object")
		}
		if [0] == ',' {
			 = [1:]
			continue
		}
		if [0] == '}' {
			return [1:], nil
		}
		return , fmt.Errorf("missing ',' after object value")
	}
}

// validateKey is similar to validateString, but is optimized
// for typical object keys, which are quite small and have no escape sequences.
func ( string) (string, string, error) {
	for  := 0;  < len(); ++ {
		if [] == '"' {
			// Fast path - the key doesn't contain escape sequences.
			return [:], [+1:], nil
		}
		if [] == '\\' {
			// Slow path - the key contains escape sequences.
			return validateString()
		}
	}
	return "", , fmt.Errorf(`missing closing '"'`)
}

func ( string) (string, string, error) {
	// Try fast path - a string without escape sequences.
	if  := strings.IndexByte(, '"');  >= 0 && strings.IndexByte([:], '\\') < 0 {
		return [:], [+1:], nil
	}

	// Slow path - escape sequences are present.
	, ,  := parseRawString()
	if  != nil {
		return , , 
	}
	for {
		 := strings.IndexByte(, '\\')
		if  < 0 {
			return , , nil
		}
		++
		if  >= len() {
			return , , fmt.Errorf("BUG: parseRawString returned invalid string with trailing backslash: %q", )
		}
		 := []
		 = [+1:]
		switch  {
		case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
			// Valid escape sequences - see http://json.org/
			break
		case 'u':
			if len() < 4 {
				return , , fmt.Errorf(`too short escape sequence: \u%s`, )
			}
			 := [:4]
			,  := strconv.ParseUint(, 16, 16)
			if  != nil {
				return , , fmt.Errorf(`invalid escape sequence \u%s: %s`, , )
			}
			 = [4:]
		default:
			return , , fmt.Errorf(`unknown escape sequence \%c`, )
		}
	}
}

func ( string) (string, error) {
	if len() == 0 {
		return , fmt.Errorf("zero-length number")
	}
	if [0] == '-' {
		 = [1:]
		if len() == 0 {
			return , fmt.Errorf("missing number after minus")
		}
	}
	 := 0
	for  < len() {
		if [] < '0' || [] > '9' {
			break
		}
		++
	}
	if  <= 0 {
		return , fmt.Errorf("expecting 0..9 digit, got %c", [0])
	}
	if [0] == '0' &&  != 1 {
		return , fmt.Errorf("unexpected number starting from 0")
	}
	if  >= len() {
		return "", nil
	}
	if [] == '.' {
		// Validate fractional part
		 = [+1:]
		if len() == 0 {
			return , fmt.Errorf("missing fractional part")
		}
		 = 0
		for  < len() {
			if [] < '0' || [] > '9' {
				break
			}
			++
		}
		if  == 0 {
			return , fmt.Errorf("expecting 0..9 digit in fractional part, got %c", [0])
		}
		if  >= len() {
			return "", nil
		}
	}
	if [] == 'e' || [] == 'E' {
		// Validate exponent part
		 = [+1:]
		if len() == 0 {
			return , fmt.Errorf("missing exponent part")
		}
		if [0] == '-' || [0] == '+' {
			 = [1:]
			if len() == 0 {
				return , fmt.Errorf("missing exponent part")
			}
		}
		 = 0
		for  < len() {
			if [] < '0' || [] > '9' {
				break
			}
			++
		}
		if  == 0 {
			return , fmt.Errorf("expecting 0..9 digit in exponent part, got %c", [0])
		}
		if  >= len() {
			return "", nil
		}
	}
	return [:], nil
}