MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / parseObjects

Function parseObjects

src/tools/filesystem/pdf-read.ts:56–98  ·  view source on GitHub ↗

* Parse a PDF into its top-level objects. We do this with regex-style byte * scanning rather than a full parser because we only need object boundaries * and stream offsets — not type structure.

(data: Buffer)

Source from the content-addressed store, hash-verified

54 * and stream offsets — not type structure.
55 */
56function parseObjects(data: Buffer): PdfObject[] {
57 const objects: PdfObject[] = [];
58 const text = data.toString('latin1'); // PDF tokens are latin1-safe; binary stays in Buffer
59 const objRe = /(\d+)\s+(\d+)\s+obj\b/g;
60 let m: RegExpExecArray | null;
61 while ((m = objRe.exec(text))) {
62 const num = parseInt(m[1]!, 10);
63 const gen = parseInt(m[2]!, 10);
64 const startIdx = m.index;
65 const endIdx = text.indexOf('endobj', startIdx);
66 if (endIdx === -1) continue;
67 const body = text.slice(startIdx + m[0].length, endIdx);
68 // dict between << ... >> (greedy, may be nested — we don't care, only need text ops)
69 const dictMatch = body.match(/<<([\s\S]*?)>>/);
70 const dict = dictMatch ? dictMatch[1] ?? '' : '';
71 // stream marker
72 const streamMarker = body.indexOf('stream');
73 let streamStart: number | undefined;
74 let streamEnd: number | undefined;
75 if (streamMarker !== -1) {
76 // The actual stream starts after 'stream' + EOL (CRLF or LF)
77 let absStart = startIdx + m[0].length + streamMarker + 'stream'.length;
78 if (data[absStart] === 0x0D && data[absStart + 1] === 0x0A) absStart += 2;
79 else if (data[absStart] === 0x0A) absStart += 1;
80 const endStreamMarker = text.indexOf('endstream', streamMarker);
81 let absEnd = startIdx + m[0].length + endStreamMarker;
82 // Trim trailing EOL
83 if (data[absEnd - 1] === 0x0A) absEnd -= 1;
84 if (data[absEnd - 1] === 0x0D) absEnd -= 1;
85 streamStart = absStart;
86 streamEnd = absEnd;
87 }
88 objects.push({
89 num,
90 gen,
91 raw: data.subarray(startIdx, endIdx + 6),
92 dict,
93 streamStart,
94 streamEnd,
95 });
96 }
97 return objects;
98}
99
100/** Decode a stream based on its /Filter declarations. */
101async function decodeStream(data: Buffer, dict: string): Promise<Buffer | null> {

Callers 1

executeMethod · 0.85

Calls 1

pushMethod · 0.45

Tested by

no test coverage detected