From 17f2cc213e7acf304bee493c106b7abf17b68805 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Thu, 13 May 2021 13:18:01 -0400 Subject: [PATCH] Implement object mapping framework. --- pdfio-file.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++- pdfio-private.h | 14 ++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/pdfio-file.c b/pdfio-file.c index d8dffdd..5ccc85e 100644 --- a/pdfio-file.c +++ b/pdfio-file.c @@ -22,6 +22,7 @@ // static pdfio_obj_t *add_obj(pdfio_file_t *pdf, size_t number, unsigned short generation, off_t offset); +static int compare_objmaps(_pdfio_objmap_t *a, _pdfio_objmap_t *b); static int compare_objs(pdfio_obj_t **a, pdfio_obj_t **b); static bool load_obj_stream(pdfio_obj_t *obj); static bool load_pages(pdfio_file_t *pdf, pdfio_obj_t *obj); @@ -29,6 +30,48 @@ static bool load_xref(pdfio_file_t *pdf, off_t xref_offset); static bool write_trailer(pdfio_file_t *pdf); +// +// '_pdfioFileAddMappedObject()' - Add a mapped object. +// + +bool // O - `true` on success, `false` on failure +_pdfioFileAddMappedObject( + pdfio_file_t *pdf, // I - Destination PDF file + pdfio_obj_t *dst_obj, // I - Destination object + pdfio_obj_t *src_obj) // I - Source object +{ + _pdfio_objmap_t *map; // Object map + + + // Allocate memory as needed... + if (pdf->num_objmaps >= pdf->alloc_objmaps) + { + if ((map = realloc(pdf->objmaps, (pdf->alloc_objmaps + 16) * sizeof(_pdfio_objmap_t))) == NULL) + { + _pdfioFileError(pdf, "Unable to allocate memory for object map."); + return (false); + } + + pdf->alloc_objmaps += 16; + pdf->objmaps = map; + } + + // Add an object to the end... + map = pdf->objmaps + pdf->num_objmaps; + pdf->num_objmaps ++; + + map->obj = dst_obj; + map->src_pdf = src_obj->pdf; + map->src_number = src_obj->number; + + // Sort as needed... + if (pdf->num_objmaps > 1 && compare_objmaps(map, pdf->objmaps + pdf->num_objmaps - 2) < 0) + qsort(pdf->objmaps, pdf->num_objmaps, sizeof(_pdfio_objmap_t), (int (*)(const void *, const void *))compare_objmaps); + + return (true); +} + + // // 'pdfioFileClose()' - Close a PDF file and free all memory used for it. // @@ -67,6 +110,8 @@ pdfioFileClose(pdfio_file_t *pdf) // I - PDF file _pdfioObjDelete(pdf->objs[i]); free(pdf->objs); + free(pdf->objmaps); + free(pdf->pages); for (i = 0; i < pdf->num_strings; i ++) @@ -225,6 +270,35 @@ pdfioFileCreatePage(pdfio_file_t *pdf, // I - PDF file } +// +// '_pdfioFileFindMappedObject()' - Find a mapped object. +// + +pdfio_obj_t * // O - Match object or `NULL` if none +_pdfioFileFindMappedObject( + pdfio_file_t *pdf, // I - Destination PDF file + pdfio_file_t *src_pdf, // I - Source PDF file + size_t src_number) // I - Source object number +{ + _pdfio_objmap_t key, // Search key + *match; // Matching object map + + + // If we have no mapped objects, return NULL immediately... + if (pdf->num_objmaps == 0) + return (NULL); + + // Otherwise search for a match... + key.src_pdf = src_pdf; + key.src_number = src_number; + + if ((match = (_pdfio_objmap_t *)bsearch(&key, pdf->objmaps, pdf->num_objmaps, sizeof(_pdfio_objmap_t), (int (*)(const void *, const void *))compare_objmaps)) != NULL) + return (match->obj); + else + return (NULL); +} + + // // 'pdfioFileFindObject()' - Find an object using its object number. // @@ -493,11 +567,32 @@ add_obj(pdfio_file_t *pdf, // I - PDF file } +// +// 'compare_objmaps()' - Compare two object maps... +// + +static int // O - Result of comparison +compare_objmaps(_pdfio_objmap_t *a, // I - First object map + _pdfio_objmap_t *b) // I - Second object map +{ + if (a->src_pdf < b->src_pdf) + return (-1); + else if (a->src_pdf > b->src_pdf) + return (1); + else if (a->src_number < b->src_number) + return (-1); + else if (a->src_number > b->src_number) + return (1); + else + return (0); +} + + // // 'compare_objs()' - Compare the object numbers of two objects. // -static int +static int // O - Result of comparison compare_objs(pdfio_obj_t **a, // I - First object pdfio_obj_t **b) // I - Second object { diff --git a/pdfio-private.h b/pdfio-private.h index a6f2980..f7100bd 100644 --- a/pdfio-private.h +++ b/pdfio-private.h @@ -135,7 +135,7 @@ typedef struct _pdfio_pair_s // Key/value pair _pdfio_value_t value; // Value } _pdfio_pair_t; -struct _pdfio_dict_s +struct _pdfio_dict_s // Dictionary { pdfio_file_t *pdf; // PDF file size_t num_pairs, // Number of pairs in use @@ -143,6 +143,13 @@ struct _pdfio_dict_s _pdfio_pair_t *pairs; // Array of pairs }; +typedef struct _pdfio_objmap_s // PDF object map +{ + pdfio_obj_t *obj; // Object for this file + pdfio_file_t *src_pdf; // Source PDF file + size_t src_number; // Source object number +} _pdfio_objmap_t; + struct _pdfio_file_s // PDF file structure { char *filename; // Filename @@ -173,6 +180,9 @@ struct _pdfio_file_s // PDF file structure size_t num_objs, // Number of objects alloc_objs; // Allocated objects pdfio_obj_t **objs; // Objects + size_t num_objmaps, // Number of object maps + alloc_objmaps; // Allocated object maps + _pdfio_objmap_t *objmaps; // Object maps size_t num_pages, // Number of pages alloc_pages; // Allocated pages pdfio_obj_t **pages; // Pages @@ -230,9 +240,11 @@ extern pdfio_dict_t *_pdfioDictRead(pdfio_file_t *pdf, _pdfio_token_t *ts) PDFIO extern bool _pdfioDictSetValue(pdfio_dict_t *dict, const char *key, _pdfio_value_t *value) PDFIO_INTERNAL; extern bool _pdfioDictWrite(pdfio_dict_t *dict, off_t *length) PDFIO_INTERNAL; +extern bool _pdfioFileAddMappedObject(pdfio_file_t *pdf, pdfio_obj_t *dst_obj, pdfio_obj_t *src_obj) PDFIO_INTERNAL; extern bool _pdfioFileConsume(pdfio_file_t *pdf, size_t bytes) PDFIO_INTERNAL; extern bool _pdfioFileDefaultError(pdfio_file_t *pdf, const char *message, void *data) PDFIO_INTERNAL; extern bool _pdfioFileError(pdfio_file_t *pdf, const char *format, ...) PDFIO_FORMAT(2,3) PDFIO_INTERNAL; +extern pdfio_obj_t *_pdfioFileFindMappedObject(pdfio_file_t *pdf, pdfio_file_t *src_pdf, size_t src_number) PDFIO_INTERNAL; extern bool _pdfioFileFlush(pdfio_file_t *pdf) PDFIO_INTERNAL; extern int _pdfioFileGetChar(pdfio_file_t *pdf) PDFIO_INTERNAL; extern bool _pdfioFileGets(pdfio_file_t *pdf, char *buffer, size_t bufsize) PDFIO_INTERNAL;