unescapeChar takes a string input and returns the following info: value - the escaped unicode rune at the front of the string. multibyte - whether the rune value might require multiple bytes to represent. tail - the remainder of the input string. err - error value, if the character could not be
(s string)
| 108 | // but a multibyte conversion is attempted which is more expensive than when the |
| 109 | // value is known to fit within one byte. |
| 110 | func unescapeChar(s string) (value rune, multibyte bool, tail string, err error) { |
| 111 | // 1. Character is not an escape sequence. |
| 112 | switch c := s[0]; { |
| 113 | case c >= utf8.RuneSelf: |
| 114 | r, size := utf8.DecodeRuneInString(s) |
| 115 | return r, true, s[size:], nil |
| 116 | case c != '\\': |
| 117 | return rune(s[0]), false, s[1:], nil |
| 118 | } |
| 119 | |
| 120 | // 2. Last character is the start of an escape sequence. |
| 121 | if len(s) <= 1 { |
| 122 | err = fmt.Errorf("unable to unescape string, found '\\' as last character") |
| 123 | return |
| 124 | } |
| 125 | |
| 126 | c := s[1] |
| 127 | s = s[2:] |
| 128 | // 3. Common escape sequences shared with Google SQL |
| 129 | switch c { |
| 130 | case 'a': |
| 131 | value = '\a' |
| 132 | case 'b': |
| 133 | value = '\b' |
| 134 | case 'f': |
| 135 | value = '\f' |
| 136 | case 'n': |
| 137 | value = '\n' |
| 138 | case 'r': |
| 139 | value = '\r' |
| 140 | case 't': |
| 141 | value = '\t' |
| 142 | case 'v': |
| 143 | value = '\v' |
| 144 | case '\\': |
| 145 | value = '\\' |
| 146 | case '\'': |
| 147 | value = '\'' |
| 148 | case '"': |
| 149 | value = '"' |
| 150 | case '`': |
| 151 | value = '`' |
| 152 | case '?': |
| 153 | value = '?' |
| 154 | |
| 155 | // 4. Unicode escape sequences, reproduced from `strconv/quote.go` |
| 156 | case 'x', 'X', 'u', 'U': |
| 157 | // Support Go/Rust-style variable-length form: \u{XXXXXX} |
| 158 | if c == 'u' && len(s) > 0 && s[0] == '{' { |
| 159 | // consume '{' |
| 160 | s = s[1:] |
| 161 | var v rune |
| 162 | digits := 0 |
| 163 | for len(s) > 0 && s[0] != '}' { |
| 164 | x, ok := unhex(s[0]) |
| 165 | if !ok { |
| 166 | err = fmt.Errorf("unable to unescape string") |
| 167 | return |