Object loading

This commit is contained in:
Jakub Melka
2018-11-25 14:48:08 +01:00
parent 8c93c82228
commit 89d4ee606b
12 changed files with 234 additions and 18 deletions

View File

@ -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)
{