pdfobjects::XRefWriter Class Reference

#include <xrefwriter.h>

Inheritance diagram for pdfobjects::XRefWriter:
pdfobjects::CXref

List of all members.

Public Types

enum  writerMode { easy, paranoid }

Public Member Functions

 XRefWriter (StreamWriter *stream, CPdf *_pdf)
 ~XRefWriter ()
utils::IPdfWritersetPdfWriter (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 CPdfpdf
unsigned revision
RevisionStorage revisions
size_t storePos
utils::IPdfWriterpdfWriter
bool linearized

Detailed Description

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.


Member Typedef Documentation

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.


Member Enumeration Documentation

Mode for XRefWriter. This controls behaviour. Following values are possible:

  • easy - no checking is performed when some change is done.
  • paranoid - type safety and reference existance is checked.
Enumerator:
easy 
paranoid 

Constructor & Destructor Documentation

pdfobjects::XRefWriter::XRefWriter (  )  [inline, private]
pdfobjects::XRefWriter::XRefWriter ( StreamWriter stream,
CPdf _pdf 
)

Initialize constructor with file stream writer.

Parameters:
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.

Exceptions:
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.


Member Function Documentation

void pdfobjects::XRefWriter::changeObject ( int  num,
int  gen,
::Object *  obj 
)

Inserts new object.

Parameters:
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.

Exceptions:
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.

Parameters:
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.

Exceptions:
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.

Parameters:
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.

Exceptions:
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).
Returns:
Previous value of object or 0 if previous revision not available (new name value pair in trailer).

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.

Parameters:
file File handle where to copy content.

Clone contains everything from stream starting from 0 position until getRevisionEnd.

See also:
XRefWriter::getRevisionEnd for limitations.

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.

Parameters:
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.

Exceptions:
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.

Parameters:
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.

Returns:
Revision number.

References revision.

Referenced by pdfobjects::CPdf::getActualRevision().

writerMode pdfobjects::XRefWriter::getMode (  )  const [inline]

Initialize constructor with cache.

Parameters:
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).

Exceptions:
MalformedFormatExeption if XRef creation fails (instance is unusable in such situation). Gets mode.
Returns:
Actualy set 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.

Returns:
number of objects.

Reimplemented from pdfobjects::CXref.

References revision.

int pdfobjects::XRefWriter::getOldStyleTrailer ( Object *  trailer,
size_t  off 
) [protected]

Parses old style trailer from given position.

Parameters:
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).

Returns:
0 on success, -1 otherwise.

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.

Returns:
Number 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.

Parameters:
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.

Returns:
Offset immediately after last information for this revision.

References STARTXREF_KEYWORD.

Referenced by cloneRevision(), and getRevisionSize().

size_t pdfobjects::XRefWriter::getRevisionSize ( unsigned  rev,
bool  includeXref = false 
) const

Returns size of given revision.

Parameters:
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.

See also:
XRefWriter::getRevisionEnd for limitations.
Returns:
number of bytes used for current revision (see for includeXref paramter specific behaviour).

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.

Parameters:
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.

Returns:
0 on success, -1 otherwise.

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.

Returns:
true if file is linearized, false otherwise.

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.

Parameters:
ref Indirect reference to check.

Gets xpdf Ref value and delegates to knowsRef(Ref).

See also:
RefState
Returns:
Reference state.

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.

Parameters:
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).

See also:
RefState
Returns:
Reference state.

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.

Parameters:
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).

Returns:
true if all checks are ok, false otherwise.

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.

Exceptions:
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.

Parameters:
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).

Exceptions:
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]

Sets mode.

Parameters:
_mode Mode to set.

References mode.

Referenced by pdfobjects::CPdf::CPdf().

utils::IPdfWriter * pdfobjects::XRefWriter::setPdfWriter ( utils::IPdfWriter writer  ) 

Sets new pdf writer implementator.

Parameters:
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.

Returns:
Previous pdf writer implemetator (if not NULL, caller is responsible for deallocation).

References pdfWriter.

Referenced by pdfobjects::CPdf::getPdfWriter().


Member Data Documentation

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().

Mode for checking.

Referenced by changeTrailer(), getMode(), paranoidCheck(), and setMode().

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().

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().

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().


The documentation for this class was generated from the following files: