//UnquoteExtend is almost same as strconv.Unquote(), but it support parse single quotes as a string
517924
func UnquoteExtend(s string) (string, error) {
	n := len(s)
	if n < 2 {
		return "", ErrSyntax
	}
	quote := s[0]
	if quote != s[n-1] {
		return "", ErrSyntax
	}
	s = s[1 : n-1]

	if quote != '"' && quote != '\'' {
		return "", ErrSyntax
	}

	// Is it trivial?  Avoid allocation.
	if !contains(s, '\\') && !contains(s, quote) {
		return s, nil
	}

	var runeTmp [utf8.UTFMax]byte
	buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
	for len(s) > 0 {
		c, multibyte, ss, err := strconv.UnquoteChar(s, quote)
		if err != nil {
			return "", err
		}
		s = ss
		if c < utf8.RuneSelf || !multibyte {
			buf = append(buf, byte(c))
		} else {
			n := utf8.EncodeRune(runeTmp[:], c)
			buf = append(buf, runeTmp[:n]...)
		}
	}
	return string(buf), nil
}
430123
func literal(s string) *regexp.Regexp {
	re := match(regexp.QuoteMeta(s))

	if _, complete := re.LiteralPrefix(); !complete {
		panic("must be a literal")
	}

	return re
}
836395
func QuoteArray(s []string, sep string) string {
	quoted := make([]string, len(s))
	for i, value := range s {
		quoted[i] = strconv.Quote(value)
	}
	return strings.Join(quoted, sep)
}
242576
func UnquoteSingleQuoted(in []byte) (string, error) {
	out := string(swapQuotes(in))
	str, err := strconv.Unquote(out)
	if err != nil {
		return str, err
	}

	// s/'/"/g, s/"/'/g
	out = string(swapQuotes([]byte(str)))
	return out, nil
}
1194523
func quoteArgs(args []string) string {
	quoted := make([]string, len(args))
	for index, arg := range args {
		quoted[index] = quote(arg)
	}
	return strings.Join(quoted, " ")
}
435040
func formatQuoted(names ...string) string {
	quoted := make([]string, 0, len(names))
	for _, name := range names {
		quoted = append(quoted, fmt.Sprintf("%q", name))
	}
	return strings.Join(quoted, ",")
}
710958
func (d *decodeState) valueQuoted() interface{} {
	switch op := d.scanWhile(scanSkipSpace); op {
	default:
		d.error(errPhase)

	case scanBeginArray:
		d.array(reflect.Value{})

	case scanBeginObject:
		d.object(reflect.Value{})

	case scanBeginLiteral:
		switch v := d.literalInterface().(type) {
		case nil, string:
			return v
		}
	}
	return unquotedValue{}
}
333143
func (d *decodeState) valueQuoted() interface{} {
	switch op := d.scanWhile(ScanSkipSpace); op {
	default:
		d.error(errPhase)

	case ScanBeginArray:
		d.array(reflect.Value{})

	case ScanBeginObject:
		d.object(reflect.Value{})

	case ScanBeginLiteral:
		switch v := d.literalInterface().(type) {
		case nil, string:
			return v
		}
	}
	return unquotedValue{}
}
408310
func stripQuotes(s string) string {
	if s[0] == '"' {
		s = s[1:]
	}
	if s[len(s)-1] == '"' {
		s = s[:len(s)-1]
	}
	return s
}
832844
func quoteName(w io.Writer, s string) error {
	if _, err := w.Write(astBackquote); err != nil {
		return err
	}
	if _, err := io.WriteString(w, s); err != nil {
		return err
	}
	_, err := w.Write(astBackquote)
	return err
}
1287731
func LiteralQuoteEscape(quote rune, literal string) string {
	if len(literal) > 1 {
		quoteb := byte(quote)
		if literal[0] == quoteb && literal[len(literal)-1] == quoteb {
			// Already escaped??
			return literal
		}
	}
	var buf bytes.Buffer
	LiteralQuoteEscapeBuf(&buf, quote, literal)
	return buf.String()
}
851739
func QuoteMeta(s string) string {
	b := make([]byte, 2*len(s))

	// a byte loop is correct because all meta characters are ASCII
	j := 0
	for i := 0; i < len(s); i++ {
		if syntax.Special(s[i]) {
			b[j] = '\\'
			j++
		}
		b[j] = s[i]
		j++
	}

	return string(b[0:j])
}
737060
func quote(s string) string {
	b, _ := json.Marshal(s)
	return string(b)
}
922237
func httpUnquote(raw string) (eaten int, result string) {
	buf := make([]byte, len(raw))
	if raw[0] != '"' {
		return -1, ""
	}
	eaten = 1
	j := 0 // # of bytes written in buf
	for i := 1; i < len(raw); i++ {
		switch b := raw[i]; b {
		case '"':
			eaten++
			buf = buf[0:j]
			return i + 1, string(buf)
		case '\\':
			if len(raw) < i+2 {
				return -1, ""
			}
			buf[j] = httpUnquotePair(raw[i+1])
			eaten += 2
			j++
			i++
		default:
			if isQdText(b) {
				buf[j] = b
			} else {
				buf[j] = '?'
			}
			eaten++
			j++
		}
	}
	return -1, ""
}
1003437
func (x *StringListExpr) UnmarshalJSON(data []byte) error {
	var v []*StringExpr
	err := json.Unmarshal(data, &v)
	if err == nil {
		x.Func = nil
		x.Literal = v
		return nil
	}

	// Perhaps we have a serialized function call (like `{"Ref": "Foo"}`)
	// so we'll try to unmarshal it with UnmarshalFunc. Not all Funcs also
	// implement StringListFunc, so we have to make sure that the referenced
	// function actually works in the boolean context
	funcCall, err2 := unmarshalFunc(data)
	if err2 == nil {
		stringFunc, ok := funcCall.(StringListFunc)
		if ok {
			x.Func = stringFunc
			return nil
		}

		// Possible that it's a Fn::GetAtt instance?
		getAttrFunc, ok := funcCall.(GetAttFunc)
		if ok {
			x.Func = StringList(getAttrFunc)
			return nil
		}
		return fmt.Errorf("%#v is not a StringListFunc", funcCall)
	}

	// Perhaps we have a single item, like "foo" which
	// occurs occasionally.
	var v2 StringExpr
	err3 := json.Unmarshal(data, &v2)
	if err3 == nil {
		x.Func = nil
		x.Literal = []*StringExpr{&v2}
		return nil
	}

	// Return the original error trying to unmarshal the literal expression,
	// which will be the most expressive.
	return err
}
811907
func unquote(s string) string {
	quote := s[0:1]
	s = s[1 : len(s)-1]
	s = strings.Replace(s, `\`+quote, quote, -1)
	return s
}
1085098
func TrimQuote(str string) (string, bool) {
	str = strings.TrimSpace(str)
	l := len(str)
	if l == 0 {
		return "", true
	}

	if s, e := str[0], str[l-1]; s == '\'' || s == '"' || s == '`' || e == '\'' || e == '"' || e == '`' {
		if l != 1 && s == e {
			str = str[1 : l-1]
		} else {
			return "", false
		}
	}

	return str, true
}