// Copyright 2018 The go-python 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 parser
import (
"bytes"
"strconv"
"github.com/go-python/gpython/py"
)
// DecodeEscape unescapes a backslash-escaped buffer
//
// byteMode indicates whether we are creating a unicode string or a bytes output
func DecodeEscape(in *bytes.Buffer, byteMode bool) (out *bytes.Buffer, err error) {
// Early exit if no escape sequences
// NB in.Bytes() is cheap
inBytes := in.Bytes()
if !bytes.ContainsRune(inBytes, '\\') {
return in, nil
}
out = new(bytes.Buffer)
runes := bytes.Runes(inBytes)
decodeHex := func(what byte, i, size int) error {
i++
if i+size = len(runes) {
return nil, py.ExceptionNewf(py.ValueError, "Trailing \\ in string")
}
c = runes[i]
switch c {
case '\n':
case '\\':
out.WriteRune('\\')
case '\'':
out.WriteRune('\'')
case '"':
out.WriteRune('"')
case 'b':
out.WriteRune('\b')
case 'f':
out.WriteRune('\014') // FF
case 't':
out.WriteRune('\t')
case 'n':
out.WriteRune('\n')
case 'r':
out.WriteRune('\r')
case 'v':
out.WriteRune('\013') // VT
case 'a':
out.WriteRune('\007') // BEL, not classic C
case '0', '1', '2', '3', '4', '5', '6', '7':
// 1 to 3 characters of octal escape
cout := c - '0'
if i+1 < len(runes) && '0'