StringUnescape compiles out the escape codes in the string
(loc *ast.LocationRange, s string)
| 29 | |
| 30 | // StringUnescape compiles out the escape codes in the string |
| 31 | func StringUnescape(loc *ast.LocationRange, s string) (string, error) { |
| 32 | var buf bytes.Buffer |
| 33 | // read one rune at a time |
| 34 | for i := 0; i < len(s); { |
| 35 | r, w := utf8.DecodeRuneInString(s[i:]) |
| 36 | i += w |
| 37 | switch r { |
| 38 | case '\\': |
| 39 | if i >= len(s) { |
| 40 | return "", errors.MakeStaticError("Truncated escape sequence in string literal.", *loc) |
| 41 | } |
| 42 | r2, w := utf8.DecodeRuneInString(s[i:]) |
| 43 | i += w |
| 44 | switch r2 { |
| 45 | case '"': |
| 46 | buf.WriteRune('"') |
| 47 | case '\'': |
| 48 | buf.WriteRune('\'') |
| 49 | case '\\': |
| 50 | buf.WriteRune('\\') |
| 51 | case '/': |
| 52 | buf.WriteRune('/') // See json.org, \/ is a valid escape. |
| 53 | case 'b': |
| 54 | buf.WriteRune('\b') |
| 55 | case 'f': |
| 56 | buf.WriteRune('\f') |
| 57 | case 'n': |
| 58 | buf.WriteRune('\n') |
| 59 | case 'r': |
| 60 | buf.WriteRune('\r') |
| 61 | case 't': |
| 62 | buf.WriteRune('\t') |
| 63 | case 'u': |
| 64 | if i+4 > len(s) { |
| 65 | return "", errors.MakeStaticError("Truncated unicode escape sequence in string literal.", *loc) |
| 66 | } |
| 67 | codeBytes, err := hex.DecodeString(s[i : i+4]) |
| 68 | if err != nil { |
| 69 | return "", errors.MakeStaticError(fmt.Sprintf("Unicode escape sequence was malformed: %s", s[0:4]), *loc) |
| 70 | } |
| 71 | i += 4 |
| 72 | code := rune(int(codeBytes[0])*256 + int(codeBytes[1])) |
| 73 | if utf16.IsSurrogate(code) { |
| 74 | highSurrogate := code |
| 75 | if i+6 /*\uXXXX*/ > len(s) { |
| 76 | return "", errors.MakeStaticError("Truncated unicode surrogate pair escape sequence in string literal.", *loc) |
| 77 | } |
| 78 | if s[i:i+2] != "\\u" { |
| 79 | return "", errors.MakeStaticError("Unicode surrogate pair escape sequence missing low surrogate in string literal.", *loc) |
| 80 | } |
| 81 | i += 2 |
| 82 | codeBytes, err := hex.DecodeString(s[i : i+4]) |
| 83 | if err != nil { |
| 84 | return "", errors.MakeStaticError(fmt.Sprintf("Unicode low surrogate escape sequence was malformed: %s", s[0:4]), *loc) |
| 85 | } |
| 86 | i += 4 |
| 87 | lowSurrogate := rune(int(codeBytes[0])*256 + int(codeBytes[1])) |
| 88 | code = utf16.DecodeRune(highSurrogate, lowSurrogate) |
no test coverage detected
searching dependent graphs…