#include <xrefwriter.h>
Public Types | |
| enum | writerMode { easy, paranoid } |
Public Member Functions | |
| XRefWriter (StreamWriter *stream, CPdf *_pdf) | |
| ~XRefWriter () | |
| utils::IPdfWriter * | setPdfWriter (utils::IPdfWriter *writer) |
| bool | isLinearized () const |
| writerMode | getMode () const |
| void | setMode (writerMode _mode) |
| void | changeObject (int num, int gen,::Object *obj) |
| ::Object * | changeTrailer (const char *name,::Object *value) |
| void | saveChanges (bool newRevision=false) |
| void | changeRevision (unsigned revNumber) |
| unsigned | getActualRevision () const |
| size_t | getRevisionCount () const |
| void | cloneRevision (FILE *file) const |
| size_t | getRevisionSize (unsigned rev, bool includeXref=false) const |
| virtual ::Object * | fetch (int num, int gen,::Object *obj) const |
| virtual RefState | knowsRef (const ::Ref &ref) const |
| virtual const Object * | getTrailerDict () const |
| virtual RefState | knowsRef (const IndiRef &ref) const |
| virtual ::Ref | reserveRef () |
| virtual ::Object * | createObject (::ObjType type,::Ref *ref) |
| virtual int | getNumObjects () const |
Protected Member Functions | |
| bool | paranoidCheck (const ::Ref &ref,::Object *obj) |
| int | getOldStyleTrailer (Object *trailer, size_t off) |
| int | getStreamTrailer (Object *trailer, size_t off,::Parser &parser) |
| void | collectRevisions () |
| size_t | getRevisionEnd (size_t xrefStart) const |
Private Types | |
| typedef std::vector< size_t > | RevisionStorage |
Private Member Functions | |
| XRefWriter () | |
Private Attributes | |
| writerMode | mode |
| const CPdf * | |
| unsigned | revision |
| RevisionStorage | revisions |
| size_t | storePos |
| utils::IPdfWriter * | pdfWriter |
| bool | linearized |
CXref writer class.
This wrapper of the CXref class enables:
Each public method which produces content changes checks whether associated pdf instance is not in ReadOnly mode and if it is, throws an exception to prevent from changes.
typedef std::vector<size_t> pdfobjects::XRefWriter::RevisionStorage [private] |
Type for revision storage.
Each element stands for revision with number same as index in array. The newest revision is first element (with index 0). Value stored in array is stream offset where xref section for such revision starts.
Mode for XRefWriter. This controls behaviour. Following values are possible:
| pdfobjects::XRefWriter::XRefWriter | ( | ) | [inline, private] |
| pdfobjects::XRefWriter::XRefWriter | ( | StreamWriter * | stream, | |
| CPdf * | _pdf | |||
| ) |
Initialize constructor with file stream writer.
| stream | File stream with pdf content. | |
| _pdf | Pdf instance which maintains this instance (may be also NULL, which means that instance is standalone). |
Sets mode to paranoid. Sets file to FILE handle from stream. Collects all revisions (uses collectRevisions method) and sets storePos to the %EOF position.
Allocates OldStylePdfWriter for pdfWriter field.
Stream is supplied to CXref constructor.
| MalformedFormatExeption | if XRef creation fails (instance is unusable in such situation). |
References pdfobjects::utils::checkLinearized(), collectRevisions(), debug::DBG_DBG, pdfobjects::CXref::disableInternalFetch(), pdfobjects::CXref::enableInternalFetch(), kernelPrintDbg, linearized, and storePos.
| pdfobjects::XRefWriter::~XRefWriter | ( | ) |
Destrucrtor.
Deallocates pdfWriter field if it is non NULL.
References debug::DBG_DBG, kernelPrintDbg, and pdfWriter.
| void pdfobjects::XRefWriter::changeObject | ( | int | num, | |
| int | gen, | |||
| ::Object * | obj | |||
| ) |
Inserts new object.
| num | Number of object. | |
| gen | Generation number of object. | |
| obj | Instance of object. |
If revision is 0 (most recent), delegates to the to the CXref::changeObject method. Otherwise deny to make chage, because it is not possible to do changes to a older release.
If mode is set to paranoid, checks the reference existence and after type safety. If tests are ok, operation is permitted otherwise operation fails.
| ReadOnlyDocumentException | if no changes can be done because actual revision is not the newest one or if pdf is in read-only mode. | |
| ElementBadTypeException | if mode is paranoid and paranoidCheck method fails for obj. | |
| NotImplementedException | if document is encrypted. |
References check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, xpdf::freeXpdfObject(), pdfobjects::CPdf::getMode(), pdfobjects::utils::isEncrypted(), pdfobjects::utils::isLatestRevision(), kernelPrintDbg, paranoidCheck(), pdf, pdfobjects::CPdf::ReadOnly, and revision.
Referenced by pdfobjects::CPdf::changeIndirectProperty(), and pdfobjects::CPdf::registerIndirectProperty().
| void pdfobjects::XRefWriter::changeRevision | ( | unsigned | revNumber | ) |
Changes revision of document.
| revNumber | Number of the revision. |
Jumps to the given revision. 0 stands for the oldest revision while newer revisions have higher number.
XRefWriter doesn't enable to make changes if revision is not the most recent one. This means that all methods producing changes are invalid and produces error when called.
This is because branching is not implementable in PDF structure.
| OutOfRange | if revNumber doesn't stand for any known revisions. | |
| NotImplementedException | if pdf content is linearized. |
References check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, debug::DBG_INFO, debug::DBG_WARN, isLinearized(), kernelPrintDbg, pdfobjects::CXref::reopen(), revision, and revisions.
Referenced by pdfobjects::CPdf::changeRevision().
| Object * pdfobjects::XRefWriter::changeTrailer | ( | const char * | name, | |
| ::Object * | value | |||
| ) |
Changes trailer entry.
| name | Name of the entry. | |
| value | New value. |
If revision is 0 (most recent), delegates to the CXref::changeTrailer method. Otherwise deny to make chage, because it is not possible to do changes to an older release.
If mode is set to paranoid, checks whether field with the given name is on banned list (canChangeTrailerEntry), reference existence and finally type safety. If tests are ok, operation is permitted otherwise operation fails.
| ReadOnlyDocumentException | if no changes can be done because actual revision is not the newest one or if pdf is in read-only mode. | |
| NotImplementedException | if document is encrypted or when trailer dictionary can't be cloned (because clone method failes). | |
| ElementBadTypeException | if the change is not allowed (either due to type safety or that given entry cannot be changed). |
Reimplemented from pdfobjects::CXref.
References pdfobjects::utils::canChangeTrailerEntry(), check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, pdfobjects::CPdf::getMode(), pdfobjects::utils::isEncrypted(), pdfobjects::utils::isLatestRevision(), kernelPrintDbg, mode, paranoid, pdf, pdfobjects::CPdf::ReadOnly, revision, and pdfobjects::utils::typeSafeTrailerEntry().
Referenced by pdfobjects::CPdf::changeTrailer().
| void pdfobjects::XRefWriter::cloneRevision | ( | FILE * | file | ) | const |
Clones content of stream until end of current position.
| file | File handle where to copy content. |
Clone contains everything from stream starting from 0 position until getRevisionEnd.
References check_need_credentials, StreamWriter::cloneToFile(), debug::DBG_DBG, debug::DBG_ERR, debug::DBG_WARN, EOFMARKER, getRevisionEnd(), pdfobjects::utils::isEncrypted(), kernelPrintDbg, revision, and revisions.
Referenced by pdfobjects::CPdf::clone().
| void pdfobjects::XRefWriter::collectRevisions | ( | ) | [protected] |
Collects all revisions information.
If linearized is set to true, immediately returns with warning message. Otherwise stores position of xref section start to the revisions storage. Parses Trailer dictionary and gets Prev field value. If not present, assumes no more revisions are available. Otherwise stores that position to revisions storage as later revision and continues same way.
Sets revision field to the most recent one as a side effect.
References debug::DBG_DBG, debug::DBG_ERR, debug::DBG_INFO, debug::DBG_WARN, pdfobjects::XPdfObjectFactory::getInstance(), getOldStyleTrailer(), pdfobjects::getPrevFromTrailer(), getStreamTrailer(), getTrailerDict(), isERR_OFFSET, isLinearized(), kernelPrintDbg, gui::parser, revision, revisions, and XREF_KEYWORD.
Referenced by XRefWriter().
| Object * pdfobjects::XRefWriter::createObject | ( | ::ObjType | type, | |
| ::Ref * | ref | |||
| ) |
Creates new indirect object.
| type | New object type. | |
| ref | Pointer where to store new object's reference. |
This is just wrapper for CXref::createObject method. Only thing which is done here is that revision field is checked and if the current revision is the most recent one, delegates to the to the CXref::createObject. Otherwise deny to make create, because it is not possible to do changes to a older release.
| ReadOnlyDocumentException | if no changes can be done because actual revision is not the newest one or if pdf is in read-only mode. | |
| NotImplementedException | if document is encrypted. |
Reimplemented from pdfobjects::CXref.
References check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, pdfobjects::CPdf::getMode(), pdfobjects::utils::isEncrypted(), pdfobjects::utils::isLatestRevision(), kernelPrintDbg, pdf, pdfobjects::CPdf::ReadOnly, and revision.
| virtual ::Object* pdfobjects::XRefWriter::fetch | ( | int | num, | |
| int | gen, | |||
| ::Object * | obj | |||
| ) | const [inline] |
Fetches indirect object.
| num | Object number. | |
| gen | Generation number. | |
| obj | Pointer to allocated object where to store fetched object (must be allocated by caller). |
This is just wrapper for CXref::fetch implementation and only checks wheter we are in the newest revision and if so delegates to the CXref::fetch method (this is because newest revision may contain changes). Otherwise delegates to the XRef::fetch method.
Reimplemented from pdfobjects::CXref.
References pdfobjects::utils::isLatestRevision().
Referenced by pdfobjects::CPdf::getIndirectProperty(), and paranoidCheck().
| unsigned pdfobjects::XRefWriter::getActualRevision | ( | ) | const [inline] |
Returns actual revision.
References revision.
Referenced by pdfobjects::CPdf::getActualRevision().
| writerMode pdfobjects::XRefWriter::getMode | ( | ) | const [inline] |
Initialize constructor with cache.
| stream | Stream with file data. | |
| c | Cache instance. |
Delegates to CXref constructor with the stream and cache parameter. Sets mode to paranoid. Collects all revisions (uses collectRevisions method).
| MalformedFormatExeption | if XRef creation fails (instance is unusable in such situation). Gets mode. |
References mode.
| virtual int pdfobjects::XRefWriter::getNumObjects | ( | ) | const [inline, virtual] |
Returns number of indirect objects.
If revision is 0 (the newest revision) delegates to the CXref::getNumObjects (because new object may have been created), otherwise delegates to XRef::getNumObjects.
Reimplemented from pdfobjects::CXref.
References revision.
| int pdfobjects::XRefWriter::getOldStyleTrailer | ( | Object * | trailer, | |
| size_t | off | |||
| ) | [protected] |
Parses old style trailer from given position.
| trailer | Previous trailer which will be filled with new data (note that original content will be destroyed). | |
| off | File offset where to start. |
Note that file offset is assumed to point to the first byte of the trailer object (exactly behind XREF_KEYWORD).
References debug::DBG_DBG, debug::DBG_ERR, kernelPrintDbg, gui::parser, STARTXREF_KEYWORD, and TRAILER_KEYWORD.
Referenced by collectRevisions().
| size_t pdfobjects::XRefWriter::getRevisionCount | ( | ) | const [inline] |
Returns count of revisions.
References revisions.
Referenced by pdfobjects::CPdf::getRevisionsCount().
| size_t pdfobjects::XRefWriter::getRevisionEnd | ( | size_t | xrefStart | ) | const [protected] |
Returns end of current revision offset.
| xrefStart | Stream offset of xref section start. |
Finds startxref from given position and returns offset to the first byte after xref offset number line or end of stream position if startxref has not been found.
Implementation notes:
This method assumes that revision has been added by incremental update and no object from this revision can be behind this position. This assumption is not fullfilled specially for linearized pdf documents.
References STARTXREF_KEYWORD.
Referenced by cloneRevision(), and getRevisionSize().
| size_t pdfobjects::XRefWriter::getRevisionSize | ( | unsigned | rev, | |
| bool | includeXref = false | |||
| ) | const |
Returns size of given revision.
| rev | Revision to examine. | |
| includeXref | Flag controling whether also xref section with trailer should be also considered. |
Gets size of data used for given revision. This means number of bytes starting from previous revision (or file start if no previous is exists) until start of given one's xref section if includeXref is false or end of whole given revision (return value from getRevisionEnd) if flag is true.
This implies that getRevisionSize with default behaviour returns number of bytes used for data of given revision meanwhile getRevisionSize(true) returns whole size of revision.
References debug::DBG_DBG, debug::DBG_ERR, getRevisionEnd(), kernelPrintDbg, and revisions.
Referenced by pdfobjects::CPdf::getRevisionSize().
| int pdfobjects::XRefWriter::getStreamTrailer | ( | Object * | trailer, | |
| size_t | off, | |||
| ::Parser & | parser | |||
| ) | [protected] |
Parses stream trailer from given position.
| trailer | Previous trailer which will be filled with new data (note that original content will be destroyed). | |
| off | File offset of the trailer start. | |
| parser | Parser for the trailer. |
Note that parser has to point right behind first (object) number. Then it assumes genereation number, `obj' keyword and trailer object definition.
References debug::DBG_DBG, debug::DBG_ERR, pdfobjects::XPdfObjectFactory::getInstance(), and kernelPrintDbg.
Referenced by collectRevisions().
| virtual const Object* pdfobjects::XRefWriter::getTrailerDict | ( | ) | const [inline, virtual] |
Returns current trailer dictionary.
Checks if the current revision is the newest one and delegates to CXref imlementation, because it can contain changed trailer. Otherwise delegates to XRef implementation.
Reimplemented from pdfobjects::CXref.
References pdfobjects::utils::isLatestRevision().
Referenced by collectRevisions(), pdfobjects::CPdf::getTrailer(), and saveChanges().
| bool pdfobjects::XRefWriter::isLinearized | ( | ) | const [inline] |
Returns linearized flag value.
References linearized.
Referenced by pdfobjects::CPdf::canChange(), changeRevision(), collectRevisions(), and pdfobjects::CPdf::isLinearized().
| RefState pdfobjects::XRefWriter::knowsRef | ( | const IndiRef & | ref | ) | const [virtual] |
Checks if given reference is known.
| ref | Indirect reference to check. |
Gets xpdf Ref value and delegates to knowsRef(Ref).
Reimplemented from pdfobjects::CXref.
References pdfobjects::IndiRef::gen, knowsRef(), and pdfobjects::IndiRef::num.
| virtual RefState pdfobjects::XRefWriter::knowsRef | ( | const ::Ref & | ref | ) | const [inline, virtual] |
Checks if given reference is known.
| ref | Reference to check. |
Checks if the current revision is the newest one and delegates to CXref implementation if this is true, because there can be also new referencies. Otherwise searches only in XRef::entries (only referencies from document).
Reimplemented from pdfobjects::CXref.
References pdfobjects::utils::isLatestRevision().
Referenced by knowsRef(), paranoidCheck(), and pdfobjects::CPdf::registerIndirectProperty().
| bool pdfobjects::XRefWriter::paranoidCheck | ( | const ::Ref & | ref, | |
| ::Object * | obj | |||
| ) | [protected] |
Checking for paranoid mode.
| ref | Reference of object. | |
| obj | Object to check. |
Checks if we are in paranoid mode. If not immediately returns with success. Otherwise checks if given reference exists (uses knowsRef method). Then checks whether replacing with given object is type safe (uses typeSafe method).
References debug::DBG_DBG, debug::DBG_WARN, fetch(), pdfobjects::XPdfObjectFactory::getInstance(), kernelPrintDbg, knowsRef(), mode, paranoid, and pdfobjects::CXref::typeSafe().
Referenced by changeObject().
| Ref pdfobjects::XRefWriter::reserveRef | ( | ) |
Registers new reference.
This is just wrapper for CXref::reference method. Only thing which is done here is that revision field is checked and if the current revision is the most recent one, delegates to the to the CXref::reserveRef.
Otherwise deny to create, because it is not possible to do changes to a older release.
| ReadOnlyDocumentException | if no changes can be done because actual revision is not the newest one or if pdf is in read-only mode. |
Reimplemented from pdfobjects::CXref.
References check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, pdfobjects::CPdf::getMode(), pdfobjects::utils::isLatestRevision(), kernelPrintDbg, pdf, pdfobjects::CPdf::ReadOnly, and revision.
Referenced by pdfobjects::CPdf::addIndirectProperty(), and pdfobjects::createMapping().
| void pdfobjects::XRefWriter::saveChanges | ( | bool | newRevision = false |
) |
Saves changed objects and new xref and trailer.
| newRevision | Flag controlling new revision creation. |
Checks all objects which are changed (in CXref::changeStorage) and stores them from actual storePos file offset. Also append new xref table for changed objects and finally new trailer is added. Trailer's Prev field is set to contain file offset to previous xref position.
Revision handling:
Method gets also newRevision flag parameter which says whether to save changes as new revision. If new revision is created, storePos is moved after stored data (more precisely after new trailer) and CXref super type is forced to reopen (CXref::reopen method is called) to handle new revision creation. Otherwise storePos is not moved and all objects from changeStorage are kept as they are. This means that default behaviour doens't have any influence on internal structure.
By default no new revision is set. This implies that each call of this method overwrittes previous save (from same storePos).
Use default behaviour if you want to be sure that you don't lose your changes and create new revision if you want to have certain set of changes grouped together (e. g. when changes have some significancy).
NOE: if document is linearized prints warning but continue with saving even if output may brake linearization rules and content is still marked as linearized (Linearized dictionary is kept because we never change original content and all changes are strictly appended). Method should be called with linearized documents very carefully (especially when braking linearization can confuse pdf reader - e. g. xpdf doesn't care for linearized pdfs special handling and reads file allways from the end).
| ReadOnlyDocumentException | if no changes can be done because actual revision is not the newest one. |
References ObjectStorage< K, V, Comp >::begin(), pdfobjects::CXref::changedStorage, check_need_credentials, debug::DBG_DBG, debug::DBG_ERR, debug::DBG_INFO, debug::DBG_WARN, ObjectStorage< K, V, Comp >::end(), xpdf::freeXpdfObject(), getTrailerDict(), kernelPrintDbg, linearized, pdfWriter, pdfobjects::CXref::reopen(), revision, revisions, ObjectStorage< K, V, Comp >::size(), storePos, pdfobjects::utils::IPdfWriter::writeContent(), and pdfobjects::utils::IPdfWriter::writeTrailer().
Referenced by pdfobjects::CPdf::save().
| void pdfobjects::XRefWriter::setMode | ( | writerMode | _mode | ) | [inline] |
| utils::IPdfWriter * pdfobjects::XRefWriter::setPdfWriter | ( | utils::IPdfWriter * | writer | ) |
Sets new pdf writer implementator.
| writer | Implementation of IPdfWriter (must be non NULL). |
Sets writer (if parameter is non NULL) and returns current implementation. If parameter is NULL, just returns current implementator.
Given parameter has to be allocated by new operator, because it is deallocated in destructor by delete operator.
References pdfWriter.
Referenced by pdfobjects::CPdf::getPdfWriter().
bool pdfobjects::XRefWriter::linearized [private] |
Flag for linearized pdf content. This value is set in constructor and it tells whether file is linearized. Some operations are not implemented for those files (e. g. revision handling, ... - it is always described in method if it is problem)
Referenced by isLinearized(), saveChanges(), and XRefWriter().
writerMode pdfobjects::XRefWriter::mode [private] |
Mode for checking.
Referenced by changeTrailer(), getMode(), paranoidCheck(), and setMode().
const CPdf* pdfobjects::XRefWriter::pdf [private] |
Pdf instance which maintains this xref writer.
Instance is used to get higher level information whether making changes is allowed.
Value is initialized in constructor and doesn't change during instance life cycle.
Referenced by changeObject(), changeTrailer(), createObject(), and reserveRef().
Pdf writer implementator.
Uses OldStylePdfWriter by default. This can be changed by setPdfWriter method.
Referenced by saveChanges(), setPdfWriter(), and ~XRefWriter().
unsigned pdfobjects::XRefWriter::revision [private] |
Actual revision.
Latest revision is represented by 0 and each older one has bigger number.
Instance is created in 0 revision number and this can be changed by changeRevision method.
Referenced by changeObject(), changeRevision(), changeTrailer(), cloneRevision(), collectRevisions(), createObject(), getActualRevision(), getNumObjects(), reserveRef(), and saveChanges().
Array of all revisions. This array contains everytime at least one element. It is initialized in constructor from parsed information and new elements are appended when saveXref is called with newRevision flag.
Referenced by changeRevision(), cloneRevision(), collectRevisions(), getRevisionCount(), getRevisionSize(), and saveChanges().
size_t pdfobjects::XRefWriter::storePos [private] |
File offset for write changes.
This offset is used as file position where to start writing changes. It is used by saveChanges method which can move this offset depending on saving mode (it is moved if changes are saved as new revision).
The value is initialized by constructor to point to the PDF end of file marker %EOF. This invariant is allways kept.
Referenced by saveChanges(), and XRefWriter().