MCPcopy Create free account
hub / github.com/LibPDF-js/core / readStream

Method readStream

src/parser/indirect-object-parser.ts:148–200  ·  view source on GitHub ↗

* Read stream data after the dict has been parsed. * The "stream" keyword has been detected by ObjectParser's lookahead, * and the scanner is positioned right after "stream".

(dict: PdfDict)

Source from the content-addressed store, hash-verified

146 * and the scanner is positioned right after "stream".
147 */
148 private readStream(dict: PdfDict): PdfStream {
149 // The scanner is positioned right after "stream" keyword
150 // (ObjectParser consumed it during lookahead but didn't use it)
151
152 // Skip EOL after "stream" (required: LF or CRLF)
153 this.skipStreamEOL();
154
155 const startPos = this.scanner.position;
156
157 // Try to resolve /Length from the dict. If that fails (e.g. indirect
158 // ref during brute-force recovery with no resolver), fall back to
159 // scanning for the "endstream" keyword to determine the length.
160 let length = -1;
161
162 try {
163 length = this.resolveLength(dict);
164 } catch {
165 length = -1;
166 }
167
168 // Validate /Length: the "endstream" keyword must follow the data.
169 // Malformed PDFs often carry a wrong /Length — recover by scanning
170 // for endstream instead of trusting the declared value.
171 if (length >= 0 && !this.isEndstreamAt(startPos + length)) {
172 this.warn(
173 `Stream /Length ${length} does not point at endstream, scanning for actual end`,
174 startPos,
175 );
176
177 length = -1;
178 }
179
180 length = length < 0 ? this.findEndStream(startPos) : length;
181
182 if (length < 0) {
183 throw new ObjectParseError("Stream has no valid /Length and no endstream found");
184 }
185
186 // Read exactly `length` bytes.
187 // Use subarray (zero-copy view) since the underlying PDF bytes
188 // are kept alive by the PDF object for the document's lifetime.
189 const data = this.scanner.bytes.subarray(startPos, startPos + length);
190
191 this.scanner.moveTo(startPos + length);
192
193 // Skip optional EOL before "endstream"
194 this.skipOptionalEOL();
195
196 // Consume "endstream" keyword directly from scanner
197 this.expectKeyword("endstream");
198
199 return new PdfStream(dict, data);
200 }
201
202 /**
203 * Check whether the "endstream" keyword appears at the given position,

Callers 1

parseObjectMethod · 0.95

Calls 8

skipStreamEOLMethod · 0.95
resolveLengthMethod · 0.95
isEndstreamAtMethod · 0.95
warnMethod · 0.95
findEndStreamMethod · 0.95
skipOptionalEOLMethod · 0.95
expectKeywordMethod · 0.95
moveToMethod · 0.65

Tested by

no test coverage detected