// Copyright 2018 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 text

import (
	
	
	
	
	
	

	
)

// parseStringValue parses string field token.
// This differs from parseString since the text format allows
// multiple back-to-back string literals where they are semantically treated
// as a single large string with all values concatenated.
//
// E.g., `"foo" "bar" "baz"` => "foobarbaz"
func ( *Decoder) () (Token, error) {
	// Note that the ending quote is sufficient to unambiguously mark the end
	// of a string. Thus, the text grammar does not require intervening
	// whitespace or control characters in-between strings.
	// Thus, the following is valid:
	//	`"foo"'bar'"baz"` => "foobarbaz"
	 := .in
	var  []string
	for len(.in) > 0 && (.in[0] == '"' || .in[0] == '\'') {
		,  := .parseString()
		if  != nil {
			return Token{}, 
		}
		 = append(, )
	}
	// d.in already points to the end of the value at this point.
	return Token{
		kind:  Scalar,
		attrs: stringValue,
		pos:   len(.orig) - len(),
		raw:   [:len()-len(.in)],
		str:   strings.Join(, ""),
	}, nil
}

// parseString parses a string value enclosed in " or '.
func ( *Decoder) () (string, error) {
	 := .in
	if len() == 0 {
		return "", ErrUnexpectedEOF
	}
	 := [0]
	 = [1:]
	 := indexNeedEscapeInBytes()
	,  := [:], [::] // set cap to prevent mutations
	for len() > 0 {
		switch ,  := utf8.DecodeRune(); {
		case  == utf8.RuneError &&  == 1:
			return "", .newSyntaxError("invalid UTF-8 detected")
		case  == 0 ||  == '\n':
			return "", .newSyntaxError("invalid character %q in string", )
		case  == rune():
			 = [1:]
			.consume(len(.in) - len())
			return string(), nil
		case  == '\\':
			if len() < 2 {
				return "", ErrUnexpectedEOF
			}
			switch  := [1];  {
			case '"', '\'', '\\', '?':
				,  = [2:], append(, )
			case 'a':
				,  = [2:], append(, '\a')
			case 'b':
				,  = [2:], append(, '\b')
			case 'n':
				,  = [2:], append(, '\n')
			case 'r':
				,  = [2:], append(, '\r')
			case 't':
				,  = [2:], append(, '\t')
			case 'v':
				,  = [2:], append(, '\v')
			case 'f':
				,  = [2:], append(, '\f')
			case '0', '1', '2', '3', '4', '5', '6', '7':
				// One, two, or three octal characters.
				 := len([1:]) - len(bytes.TrimLeft([1:], "01234567"))
				if  > 3 {
					 = 3
				}
				,  := strconv.ParseUint(string([1:1+]), 8, 8)
				if  != nil {
					return "", .newSyntaxError("invalid octal escape code %q in string", [:1+])
				}
				,  = [1+:], append(, byte())
			case 'x':
				// One or two hexadecimal characters.
				 := len([2:]) - len(bytes.TrimLeft([2:], "0123456789abcdefABCDEF"))
				if  > 2 {
					 = 2
				}
				,  := strconv.ParseUint(string([2:2+]), 16, 8)
				if  != nil {
					return "", .newSyntaxError("invalid hex escape code %q in string", [:2+])
				}
				,  = [2+:], append(, byte())
			case 'u', 'U':
				// Four or eight hexadecimal characters
				 := 6
				if  == 'U' {
					 = 10
				}
				if len() <  {
					return "", ErrUnexpectedEOF
				}
				,  := strconv.ParseUint(string([2:]), 16, 32)
				if utf8.MaxRune <  ||  != nil {
					return "", .newSyntaxError("invalid Unicode escape code %q in string", [:])
				}
				 = [:]

				 := rune()
				if utf16.IsSurrogate() {
					if len() < 6 {
						return "", ErrUnexpectedEOF
					}
					,  := strconv.ParseUint(string([2:6]), 16, 16)
					 = utf16.DecodeRune(, rune())
					if [0] != '\\' || [1] != 'u' ||  == unicode.ReplacementChar ||  != nil {
						return "", .newSyntaxError("invalid Unicode escape code %q in string", [:6])
					}
					 = [6:]
				}
				 = append(, string()...)
			default:
				return "", .newSyntaxError("invalid escape code %q in string", [:2])
			}
		default:
			 := indexNeedEscapeInBytes([:])
			,  = [+:], append(, [:+]...)
		}
	}
	return "", ErrUnexpectedEOF
}

// indexNeedEscapeInString returns the index of the character that needs
// escaping. If no characters need escaping, this returns the input length.
func ( []byte) int { return indexNeedEscapeInString(strs.UnsafeString()) }

// UnmarshalString returns an unescaped string given a textproto string value.
// String value needs to contain single or double quotes. This is only used by
// internal/encoding/defval package for unmarshaling bytes.
func ( string) (string, error) {
	 := NewDecoder([]byte())
	return .parseString()
}