* Parses a C-style quoted filename as used by Git or GNU `diff -u`. * Returns the unescaped filename and the raw length consumed (including quotes).
(s: string)
| 352 | * Returns the unescaped filename and the raw length consumed (including quotes). |
| 353 | */ |
| 354 | function parseQuotedFileName(s: string): { fileName: string, rawLength: number } | null { |
| 355 | if (!s.startsWith('"')) { return null; } |
| 356 | let result = ''; |
| 357 | let j = 1; // skip opening quote |
| 358 | while (j < s.length) { |
| 359 | if (s[j] === '"') { |
| 360 | return { fileName: result, rawLength: j + 1 }; |
| 361 | } |
| 362 | if (s[j] === '\\' && j + 1 < s.length) { |
| 363 | j++; |
| 364 | switch (s[j]) { |
| 365 | case 'a': result += '\x07'; break; |
| 366 | case 'b': result += '\b'; break; |
| 367 | case 'f': result += '\f'; break; |
| 368 | case 'n': result += '\n'; break; |
| 369 | case 'r': result += '\r'; break; |
| 370 | case 't': result += '\t'; break; |
| 371 | case 'v': result += '\v'; break; |
| 372 | case '\\': result += '\\'; break; |
| 373 | case '"': result += '"'; break; |
| 374 | case '0': case '1': case '2': case '3': |
| 375 | case '4': case '5': case '6': case '7': { |
| 376 | // C-style octal escapes represent raw bytes. Collect |
| 377 | // consecutive octal-escaped bytes and decode as UTF-8. |
| 378 | // Validate that we have a full 3-digit octal escape |
| 379 | if (j + 2 >= s.length || s[j + 1] < '0' || s[j + 1] > '7' || s[j + 2] < '0' || s[j + 2] > '7') { |
| 380 | return null; |
| 381 | } |
| 382 | const bytes = [parseInt(s.substring(j, j + 3), 8)]; |
| 383 | j += 3; |
| 384 | while (s[j] === '\\' && s[j + 1] >= '0' && s[j + 1] <= '7') { |
| 385 | if (j + 3 >= s.length || s[j + 2] < '0' || s[j + 2] > '7' || s[j + 3] < '0' || s[j + 3] > '7') { |
| 386 | return null; |
| 387 | } |
| 388 | bytes.push(parseInt(s.substring(j + 1, j + 4), 8)); |
| 389 | j += 4; |
| 390 | } |
| 391 | result += new TextDecoder('utf-8').decode(new Uint8Array(bytes)); |
| 392 | continue; // j already points at the next character |
| 393 | } |
| 394 | // Note that in C, there are also three kinds of hex escape sequences: |
| 395 | // - \xhh |
| 396 | // - \uhhhh |
| 397 | // - \Uhhhhhhhh |
| 398 | // We do not bother to parse them here because, so far as we know, |
| 399 | // they are never emitted by any tools that generate unified diff |
| 400 | // format diffs, and so for now jsdiff does not consider them legal. |
| 401 | default: return null; |
| 402 | } |
| 403 | } else { |
| 404 | result += s[j]; |
| 405 | } |
| 406 | j++; |
| 407 | } |
| 408 | // Unterminated quote |
| 409 | return null; |
| 410 | } |
| 411 |
no outgoing calls
no test coverage detected