mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Object loading
This commit is contained in:
@ -26,6 +26,7 @@
|
||||
#include <regex>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <execution>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
@ -170,6 +171,96 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer)
|
||||
PDFXRefTable xrefTable;
|
||||
xrefTable.readXRefTable(nullptr, buffer, firstXrefTableOffset);
|
||||
|
||||
PDFParsingContext context;
|
||||
|
||||
// This lambda function fetches object from the buffer from the specified offset.
|
||||
// Can throw exception, returns a pair of scanned reference and object content.
|
||||
auto getObject = [&buffer, &context](PDFInteger offset, PDFObjectReference reference) -> PDFObject
|
||||
{
|
||||
PDFParsingContext::PDFParsingContextGuard guard(&context, reference);
|
||||
|
||||
PDFParser parser(buffer, &context, PDFParser::AllowStreams);
|
||||
parser.seek(offset);
|
||||
|
||||
PDFObject objectNumber = parser.getObject();
|
||||
PDFObject generation = parser.getObject();
|
||||
|
||||
if (!objectNumber.isInt() || !generation.isInt())
|
||||
{
|
||||
throw PDFParserException(tr("Can't read object at position %1.").arg(offset));
|
||||
}
|
||||
|
||||
if (!parser.fetchCommand(PDF_OBJECT_START_MARK))
|
||||
{
|
||||
throw PDFParserException(tr("Can't read object at position %1.").arg(offset));
|
||||
}
|
||||
|
||||
PDFObject object = parser.getObject();
|
||||
|
||||
if (!parser.fetchCommand(PDF_OBJECT_END_MARK))
|
||||
{
|
||||
throw PDFParserException(tr("Can't read object at position %1.").arg(offset));
|
||||
}
|
||||
|
||||
PDFObjectReference scannedReference(objectNumber.getInteger(), generation.getInteger());
|
||||
if (scannedReference != reference)
|
||||
{
|
||||
throw PDFParserException(tr("Can't read object at position %1.").arg(offset));
|
||||
}
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
auto objectFetcher = [&getObject, &xrefTable](PDFObjectReference reference) -> PDFObject
|
||||
{
|
||||
const PDFXRefTable::Entry& entry = xrefTable.getEntry(reference);
|
||||
switch (entry.type)
|
||||
{
|
||||
case PDFXRefTable::EntryType::Free:
|
||||
return PDFObject();
|
||||
|
||||
case PDFXRefTable::EntryType::Occupied:
|
||||
{
|
||||
Q_ASSERT(entry.reference == reference);
|
||||
return getObject(entry.offset, reference);
|
||||
}
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return PDFObject();
|
||||
};
|
||||
context.setObjectFetcher(objectFetcher);
|
||||
|
||||
PDFObjectStorage::PDFObjects objects;
|
||||
objects.resize(xrefTable.getSize());
|
||||
|
||||
std::vector<PDFXRefTable::Entry> occupiedEntries = xrefTable.getOccupiedEntries();
|
||||
|
||||
auto processEntry = [this, &getObject, &objects](const PDFXRefTable::Entry& entry)
|
||||
{
|
||||
Q_ASSERT(entry.type == PDFXRefTable::EntryType::Occupied);
|
||||
|
||||
if (m_successfull)
|
||||
{
|
||||
try
|
||||
{
|
||||
objects[entry.reference.objectNumber] = PDFObjectStorage::Entry(entry.reference.generation, getObject(entry.offset, entry.reference));
|
||||
}
|
||||
catch (PDFParserException exception)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
m_successfull = false;
|
||||
m_errorMessage = exception.getMessage();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Now, we are ready to scan all objects
|
||||
//std::for_each<std::execution::parallel_policy, std::vector<PDFXRefTable::Entry>::const_iterator, decltype(processEntry)>(occupiedEntries.cbegin(), occupiedEntries.cend(), processEntry);
|
||||
std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), processEntry);
|
||||
}
|
||||
catch (PDFParserException parserException)
|
||||
{
|
||||
|
Reference in New Issue
Block a user