* Scan forward from startPos looking for the "endstream" keyword. * Returns the stream data length (excluding any EOL before endstream), * or -1 if not found.
(startPos: number)
| 308 | * or -1 if not found. |
| 309 | */ |
| 310 | private findEndStream(startPos: number): number { |
| 311 | const bytes = this.scanner.bytes; |
| 312 | const len = bytes.length; |
| 313 | |
| 314 | // "endstream" as byte values |
| 315 | const sig = [0x65, 0x6e, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d]; |
| 316 | const sigLen = sig.length; |
| 317 | |
| 318 | for (let i = startPos; i <= len - sigLen; i++) { |
| 319 | let match = true; |
| 320 | |
| 321 | for (let j = 0; j < sigLen; j++) { |
| 322 | if (bytes[i + j] !== sig[j]) { |
| 323 | match = false; |
| 324 | break; |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | if (match) { |
| 329 | // Found "endstream" at position i. |
| 330 | // Strip the optional EOL that precedes it (part of stream framing, |
| 331 | // not stream data — per PDF spec 7.3.8.1). |
| 332 | let end = i; |
| 333 | |
| 334 | if (end > startPos && bytes[end - 1] === LF) { |
| 335 | end--; |
| 336 | |
| 337 | if (end > startPos && bytes[end - 1] === CR) { |
| 338 | end--; |
| 339 | } |
| 340 | } else if (end > startPos && bytes[end - 1] === CR) { |
| 341 | end--; |
| 342 | } |
| 343 | |
| 344 | return end - startPos; |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | return -1; |
| 349 | } |
| 350 | |
| 351 | /** |
| 352 | * Resolve the /Length value from the stream dict. |