AST content stream'а с сохранением токенов
HPDFContentStream даёт ограниченную модель синтаксиса без потерь для точечных правок декодированных PDF content stream'ов
Разбор и инспекция
HPDFParseContentStreamAST создаёт THPDFContentStreamAST с лимитами по умолчанию: 4,194,304 лексем и 256 вложенных контейнеров; если нужны более жёсткие лимиты, вызывайте THPDFContentStreamAST.Create напрямую
THPDFContentLexemeKind различает пробелы, комментарии, числа, имена, literal- и hexadecimal-строки, булевы значения, null, слова, ограничители контейнеров, данные inline-изображений и повреждённые байты; каждый входной байт принадлежит ровно одному THPDFContentLexeme
THPDFContentSyntaxNodeKind различает корень, операции, операнды, массивы, словари, процедуры, inline-изображения и повреждённые регионы; каждый THPDFContentSyntaxNode хранит индексы parent, first-child, last-child и next-sibling, поэтому обход не выделяет массивы дочерних узлов
Используйте GetLexeme, GetLexemeBytes, GetLexemeText и GetNode вместе с LexemeCount и NodeCount; GetOriginalBytes возвращает независимую копию источника
Valid, ErrorOffset и ErrorMessage сообщают о повреждённом входе, сохраняя побайтово точную сериализацию, а GetStatistics заполняет THPDFContentASTStatistics размером источника, счётчиками, максимальной глубиной, числом inline-изображений и числом повреждённых узлов
Оверлей правок
ReplaceRange работает с полуоткрытыми байтовыми смещениями, а ReplaceLexeme, ReplaceNode, DeleteNode, InsertBeforeNode и InsertAfterNode выводят диапазоны из синтаксических записей
Каждый THPDFContentEdit копируется в отсортированный оверлей; конфликтующие правки отклоняются, смежные диапазоны остаются валидными, EditCount сообщает число принятых правок, а ClearEdits возвращает вывод no-op
Visitors операторов
HPDFVisitContentStreamOperators надстраивает над этим AST visitor'ы с подсчётом ссылок и Delphi event callback'и, даёт read-only представление операндов, соблюдает бюджеты на источник, операторы, лексемы, глубину и замены, а перед успехом перепарсит преобразованный вывод
Сериализация
Serialize собирает один выходной массив байтов после расчёта размера с проверкой переполнения, а WriteToStream пишет нетронутые диапазоны источника и диапазоны замен напрямую в TStream вызывающего кода
Без правок оба пути воспроизводят источник байт в байт, не трогая запись чисел, экранирование строк, комментарии, концы строк, разделители и данные inline-изображений
var
AST: THPDFContentStreamAST;
Output: TBytes;
begin
AST:= HPDFParseContentStreamAST(ContentBytes);
try
if AST.Valid and AST.ReplaceRange(StartOfs, EndOfs, ReplacementBytes) then
AST.Serialize(Output);
finally
AST.Free;
end;
end;