DecodeString accepts a raw string as it might be found in some JavaScript source code, and converts any escape sequences. E.g: foo\x3dbar -> foo=bar // Hex escapes foo\u003Dbar -> foo=bar // Unicode escapes foo\u{003D}bar -> foo=bar // Braced unicode escapes foo\075bar -> foo=bar // Octal escape foo
(in string)
| 187 | // foo\075bar -> foo=bar // Octal escape |
| 188 | // foo\"bar -> foo"bar // Single character escapes |
| 189 | func DecodeString(in string) string { |
| 190 | in = dequote(in) |
| 191 | l := newStringLexer(in) |
| 192 | |
| 193 | validHex := "0123456789abcdefABCDEF" |
| 194 | |
| 195 | for !l.done { |
| 196 | l.AcceptUntil('\\') |
| 197 | l.Emit(itemString) |
| 198 | |
| 199 | if l.done { |
| 200 | break |
| 201 | } |
| 202 | |
| 203 | // Ignore the backslash |
| 204 | l.Next() |
| 205 | l.Ignore() |
| 206 | |
| 207 | switch l.Next() { |
| 208 | case 'b', 'f', 'n', 'r', 't', 'v', '\'', '"', '\\': |
| 209 | l.Emit(itemSingleEscape) |
| 210 | case '0': |
| 211 | // It's a \0 (null) |
| 212 | if !unicode.IsDigit(l.Peek()) { |
| 213 | l.Emit(itemSingleEscape) |
| 214 | continue |
| 215 | } |
| 216 | // It's an octal escape |
| 217 | l.AcceptRun("01234567") |
| 218 | l.Emit(itemOctalEscape) |
| 219 | case 'x': |
| 220 | // ignore the x |
| 221 | l.Ignore() |
| 222 | |
| 223 | // Exactly 2 hex digits |
| 224 | if l.AcceptN(validHex, 2) { |
| 225 | l.Emit(itemHexEscape) |
| 226 | } |
| 227 | case 'u': |
| 228 | // ignore the u |
| 229 | l.Ignore() |
| 230 | |
| 231 | // e.g. \u{00003d} |
| 232 | if l.Accept("{") { |
| 233 | l.Ignore() |
| 234 | l.AcceptRun(validHex) |
| 235 | l.Emit(itemCodepointEscape) |
| 236 | if l.Accept("}") { |
| 237 | l.Ignore() |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | // e.g. \u003d |
| 242 | if l.AcceptN(validHex, 4) { |
| 243 | l.Emit(itemUnicodeEscape) |
| 244 | } |
| 245 | |
| 246 | } |