(data, errors="strict")
| 314 | |
| 315 | |
| 316 | def escape_decode(data, errors="strict"): |
| 317 | if isinstance(data, str): |
| 318 | data = data.encode("latin-1") |
| 319 | l = len(data) |
| 320 | i = 0 |
| 321 | res = bytearray() |
| 322 | while i < l: |
| 323 | if data[i] == 0x5C: # '\\' |
| 324 | i += 1 |
| 325 | if i >= l: |
| 326 | raise ValueError("Trailing \\ in string") |
| 327 | ch = data[i] |
| 328 | if ch == 0x5C: |
| 329 | res.append(0x5C) # \\ |
| 330 | elif ch == 0x27: |
| 331 | res.append(0x27) # \' |
| 332 | elif ch == 0x22: |
| 333 | res.append(0x22) # \" |
| 334 | elif ch == 0x61: |
| 335 | res.append(0x07) # \a |
| 336 | elif ch == 0x62: |
| 337 | res.append(0x08) # \b |
| 338 | elif ch == 0x66: |
| 339 | res.append(0x0C) # \f |
| 340 | elif ch == 0x6E: |
| 341 | res.append(0x0A) # \n |
| 342 | elif ch == 0x72: |
| 343 | res.append(0x0D) # \r |
| 344 | elif ch == 0x74: |
| 345 | res.append(0x09) # \t |
| 346 | elif ch == 0x76: |
| 347 | res.append(0x0B) # \v |
| 348 | elif ch == 0x0A: |
| 349 | pass # \<newline> continuation |
| 350 | elif 0x30 <= ch <= 0x37: # \0-\7 octal |
| 351 | val = ch - 0x30 |
| 352 | if i + 1 < l and 0x30 <= data[i + 1] <= 0x37: |
| 353 | i += 1 |
| 354 | val = (val << 3) | (data[i] - 0x30) |
| 355 | if i + 1 < l and 0x30 <= data[i + 1] <= 0x37: |
| 356 | i += 1 |
| 357 | val = (val << 3) | (data[i] - 0x30) |
| 358 | res.append(val & 0xFF) |
| 359 | elif ch == 0x78: # \x hex |
| 360 | hex_count = 0 |
| 361 | for j in range(1, 3): |
| 362 | if i + j < l and _is_hex_digit(data[i + j]): |
| 363 | hex_count += 1 |
| 364 | else: |
| 365 | break |
| 366 | if hex_count < 2: |
| 367 | if errors == "strict": |
| 368 | raise ValueError("invalid \\x escape at position %d" % (i - 1)) |
| 369 | elif errors == "replace": |
| 370 | res.append(0x3F) # '?' |
| 371 | i += hex_count |
| 372 | else: |
| 373 | res.append(int(bytes(data[i + 1 : i + 3]), 16)) |
nothing calls this directly
no test coverage detected