From e61e08b5d2d5d55f66f413dc36ab9c9006955f1e Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Sun, 18 Jan 2026 19:29:17 -0500 Subject: [PATCH] Minor refactoring to more easily add in object stream support (Issue #101) --- pdfio-array.c | 14 ++++---- pdfio-dict.c | 24 +++++++------ pdfio-file.c | 2 +- pdfio-object.c | 2 +- pdfio-private.h | 10 +++--- pdfio-value.c | 94 +++++++++++++++++++++++++------------------------ 6 files changed, 78 insertions(+), 68 deletions(-) diff --git a/pdfio-array.c b/pdfio-array.c index 7e48570..6a734f0 100644 --- a/pdfio-array.c +++ b/pdfio-array.c @@ -670,27 +670,29 @@ pdfioArrayRemove(pdfio_array_t *a, // I - Array // bool // O - `true` on success, `false` otherwise -_pdfioArrayWrite(pdfio_array_t *a, // I - Array - pdfio_obj_t *obj) // I - Object, if any +_pdfioArrayWrite( + _pdfio_printf_t cb, // I - Printf callback function + void *cbdata, // I - Printf callback data + pdfio_obj_t *obj, // I - Object, if any + pdfio_array_t *a) // I - Array { - pdfio_file_t *pdf = a->pdf; // PDF file size_t i; // Looping var _pdfio_value_t *v; // Current value // Arrays are surrounded by square brackets ([ ... ]) - if (!_pdfioFilePuts(pdf, "[")) + if (!(cb)(cbdata, "[")) return (false); // Write each value... for (i = a->num_values, v = a->values; i > 0; i --, v ++) { - if (!_pdfioValueWrite(pdf, obj, v, NULL)) + if (!_pdfioValueWrite(cb, cbdata, obj, v, NULL)) return (false); } // Closing bracket... - return (_pdfioFilePuts(pdf, "]")); + return ((cb)(cbdata, "]")); } diff --git a/pdfio-dict.c b/pdfio-dict.c index 95a1a36..53757cd 100644 --- a/pdfio-dict.c +++ b/pdfio-dict.c @@ -1073,11 +1073,13 @@ _pdfioDictSetValue( // bool // O - `true` on success, `false` on failure -_pdfioDictWrite(pdfio_dict_t *dict, // I - Dictionary - pdfio_obj_t *obj, // I - Object, if any - off_t *length) // I - Offset to length value +_pdfioDictWrite( + _pdfio_printf_t cb, // I - Printf callback function + void *cbdata, // I - Printf callback data + pdfio_obj_t *obj, // I - Object, if any + pdfio_dict_t *dict, // I - Dictionary + off_t *length) // I - Offset to length value { - pdfio_file_t *pdf = dict->pdf; // PDF file size_t i; // Looping var _pdfio_pair_t *pair; // Current key/value pair @@ -1086,28 +1088,30 @@ _pdfioDictWrite(pdfio_dict_t *dict, // I - Dictionary *length = 0; // Dictionaries are bounded by "<<" and ">>"... - if (!_pdfioFilePuts(pdf, "<<")) + if (!(cb)(cbdata, "<<")) return (false); // Write all of the key/value pairs... for (i = dict->num_pairs, pair = dict->pairs; i > 0; i --, pair ++) { - if (!_pdfioFilePrintf(pdf, "%N", pair->key)) + if (!(cb)(cbdata, "%N", pair->key)) return (false); if (length && !strcmp(pair->key, "Length") && pair->value.type == PDFIO_VALTYPE_NUMBER && pair->value.value.number <= 0.0) { // Writing an object dictionary with an undefined length - *length = _pdfioFileTell(pdf) + 1; - if (!_pdfioFilePuts(pdf, " 9999999999")) + *length = _pdfioFileTell(dict->pdf) + 1; + if (!(cb)(cbdata, " 9999999999")) return (false); } - else if (!_pdfioValueWrite(pdf, obj, &pair->value, NULL)) + else if (!_pdfioValueWrite(cb, cbdata, obj, &pair->value, NULL)) + { return (false); + } } // Close it up... - return (_pdfioFilePuts(pdf, ">>")); + return ((cb)(cbdata, ">>")); } diff --git a/pdfio-file.c b/pdfio-file.c index 9461b39..515a415 100644 --- a/pdfio-file.c +++ b/pdfio-file.c @@ -3124,7 +3124,7 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file pdfioDictSetObj(pdf->trailer_dict, "Root", pdf->root_obj); pdfioDictSetNumber(pdf->trailer_dict, "Size", (double)(pdf->num_objs + 1)); - if (!_pdfioDictWrite(pdf->trailer_dict, NULL, NULL)) + if (!_pdfioDictWrite((_pdfio_printf_t)_pdfioFilePrintf, pdf, /*obj*/NULL, pdf->trailer_dict, /*length*/NULL)) { _pdfioFileError(pdf, "Unable to write trailer."); ret = false; diff --git a/pdfio-object.c b/pdfio-object.c index ac287d5..bd5bad0 100644 --- a/pdfio-object.c +++ b/pdfio-object.c @@ -608,7 +608,7 @@ _pdfioObjWriteHeader(pdfio_obj_t *obj) // I - Object if (!_pdfioFilePrintf(obj->pdf, "%lu %u obj\n", (unsigned long)obj->number, obj->generation)) return (false); - if (!_pdfioValueWrite(obj->pdf, obj, &obj->value, &obj->length_offset)) + if (!_pdfioValueWrite((_pdfio_printf_t)_pdfioFilePrintf, obj->pdf, obj, &obj->value, &obj->length_offset)) return (false); return (_pdfioFilePuts(obj->pdf, "\n")); diff --git a/pdfio-private.h b/pdfio-private.h index 3e81e67..a1841eb 100644 --- a/pdfio-private.h +++ b/pdfio-private.h @@ -96,8 +96,10 @@ # define PDFIO_MAX_DEPTH 32 // Maximum nesting depth for values # define PDFIO_MAX_STRING 131072 // Maximum length of string -typedef void (*_pdfio_extfree_t)(void *); +typedef void (*_pdfio_extfree_t)(void *p); // Extension data free function +typedef bool (*_pdfio_printf_t)(void *data, const char *format, ...); + // "printf" function typedef enum _pdfio_mode_e // Read/write mode { @@ -408,7 +410,7 @@ extern void _pdfioArrayDebug(pdfio_array_t *a, FILE *fp) _PDFIO_INTERNAL; extern void _pdfioArrayDelete(pdfio_array_t *a) _PDFIO_INTERNAL; extern _pdfio_value_t *_pdfioArrayGetValue(pdfio_array_t *a, size_t n) _PDFIO_INTERNAL; extern pdfio_array_t *_pdfioArrayRead(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_token_t *ts, size_t depth) _PDFIO_INTERNAL; -extern bool _pdfioArrayWrite(pdfio_array_t *a, pdfio_obj_t *obj) _PDFIO_INTERNAL; +extern bool _pdfioArrayWrite(_pdfio_printf_t cb, void *cbdata, pdfio_obj_t *obj, pdfio_array_t *a) _PDFIO_INTERNAL; extern void _pdfioCryptoAESInit(_pdfio_aes_t *ctx, const uint8_t *key, size_t keylen, const uint8_t *iv) _PDFIO_INTERNAL; extern size_t _pdfioCryptoAESDecrypt(_pdfio_aes_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL; @@ -433,7 +435,7 @@ extern void _pdfioDictDelete(pdfio_dict_t *dict) _PDFIO_INTERNAL; extern _pdfio_value_t *_pdfioDictGetValue(pdfio_dict_t *dict, const char *key) _PDFIO_INTERNAL; extern pdfio_dict_t *_pdfioDictRead(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_token_t *ts, size_t depth) _PDFIO_INTERNAL; extern bool _pdfioDictSetValue(pdfio_dict_t *dict, const char *key, _pdfio_value_t *value) _PDFIO_INTERNAL; -extern bool _pdfioDictWrite(pdfio_dict_t *dict, pdfio_obj_t *obj, off_t *length) _PDFIO_INTERNAL; +extern bool _pdfioDictWrite(_pdfio_printf_t cb, void *cbdata, pdfio_obj_t *obj, pdfio_dict_t *dict, off_t *length) _PDFIO_INTERNAL; extern bool _pdfioFileAddMappedObj(pdfio_file_t *pdf, pdfio_obj_t *dst_obj, pdfio_obj_t *src_obj) _PDFIO_INTERNAL; extern bool _pdfioFileAddPage(pdfio_file_t *pdf, pdfio_obj_t *obj) _PDFIO_INTERNAL; @@ -482,7 +484,7 @@ extern bool _pdfioValueDecrypt(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_valu extern void _pdfioValueDebug(_pdfio_value_t *v, FILE *fp) _PDFIO_INTERNAL; extern void _pdfioValueDelete(_pdfio_value_t *v) _PDFIO_INTERNAL; extern _pdfio_value_t *_pdfioValueRead(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_token_t *ts, _pdfio_value_t *v, size_t depth) _PDFIO_INTERNAL; -extern bool _pdfioValueWrite(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_value_t *v, off_t *length) _PDFIO_INTERNAL; +extern bool _pdfioValueWrite(_pdfio_printf_t cb, void *cbdata, pdfio_obj_t *obj, _pdfio_value_t *v, off_t *length) _PDFIO_INTERNAL; #endif // !PDFIO_PRIVATE_H diff --git a/pdfio-value.c b/pdfio-value.c index 7efc38f..7d0eb13 100644 --- a/pdfio-value.c +++ b/pdfio-value.c @@ -603,10 +603,12 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file // bool // O - `true` on success, `false` on failure -_pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file - pdfio_obj_t *obj, // I - Object, if any - _pdfio_value_t *v, // I - Value - off_t *length)// O - Offset to /Length value, if any +_pdfioValueWrite( + _pdfio_printf_t cb, // I - Printf callback function + void *cbdata, // I - Printf callback data + pdfio_obj_t *obj, // I - Object, if any + _pdfio_value_t *v, // I - Value + off_t *length) // O - Offset to /Length value, if any { switch (v->type) { @@ -614,7 +616,7 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file return (false); case PDFIO_VALTYPE_ARRAY : - return (_pdfioArrayWrite(v->value.array, obj)); + return (_pdfioArrayWrite(cb, cbdata, obj, v->value.array)); case PDFIO_VALTYPE_BINARY : { @@ -624,26 +626,26 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file bool ret = false; // Return value - if (obj && pdf->encryption) + if (obj && obj->pdf->encryption) { // Write encrypted string... _pdfio_crypto_ctx_t ctx; // Encryption context - _pdfio_crypto_cb_t cb; // Encryption callback + _pdfio_crypto_cb_t ccb; // Encryption callback size_t ivlen; // Number of initialization vector bytes if (v->value.binary.datalen > PDFIO_MAX_STRING) { - _pdfioFileError(pdf, "Unable to write encrypted binary string - too long."); + _pdfioFileError(obj->pdf, "Unable to write encrypted binary string - too long."); return (false); } - else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL) + else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(obj->pdf)) == NULL) { - _pdfioFileError(pdf, "Unable to write encrypted binary string - out of memory."); + _pdfioFileError(obj->pdf, "Unable to write encrypted binary string - out of memory."); return (false); } - cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen); - databytes = (cb)(&ctx, temp + ivlen, v->value.binary.data, v->value.binary.datalen) + ivlen; + ccb = _pdfioCryptoMakeWriter(obj->pdf, obj, &ctx, temp, &ivlen); + databytes = (ccb)(&ctx, temp + ivlen, v->value.binary.data, v->value.binary.datalen) + ivlen; dataptr = temp; } else @@ -652,33 +654,33 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file databytes = v->value.binary.datalen; } - if (!_pdfioFilePuts(pdf, "<")) + if (!(cb)(cbdata, "<")) goto bindone; for (; databytes > 1; databytes -= 2, dataptr += 2) { - if (!_pdfioFilePrintf(pdf, "%02X%02X", dataptr[0], dataptr[1])) + if (!(cb)(cbdata, "%02X%02X", dataptr[0], dataptr[1])) goto bindone; } - if (databytes > 0 && !_pdfioFilePrintf(pdf, "%02X", dataptr[0])) + if (databytes > 0 && !(cb)(cbdata, "%02X", dataptr[0])) goto bindone; - ret = _pdfioFilePuts(pdf, ">"); + ret = (cb)(cbdata, ">"); bindone: if (temp) - _pdfioStringFreeBuffer(pdf, (char *)temp); + _pdfioStringFreeBuffer(obj->pdf, (char *)temp); return (ret); } case PDFIO_VALTYPE_BOOLEAN : if (v->value.boolean) - return (_pdfioFilePuts(pdf, " true")); + return ((cb)(cbdata, " true")); else - return (_pdfioFilePuts(pdf, " false")); + return ((cb)(cbdata, " false")); case PDFIO_VALTYPE_DATE : { @@ -693,64 +695,64 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file snprintf(datestr, sizeof(datestr), "D:%04d%02d%02d%02d%02d%02dZ", date.tm_year + 1900, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec); - if (obj && pdf->encryption) + if (obj && obj->pdf->encryption) { // Write encrypted string... uint8_t temp[64], // Encrypted bytes *tempptr; // Pointer into encrypted bytes _pdfio_crypto_ctx_t ctx; // Encryption context - _pdfio_crypto_cb_t cb; // Encryption callback + _pdfio_crypto_cb_t ccb; // Encryption callback size_t len = strlen(datestr), // Length of value ivlen, // Number of initialization vector bytes tempbytes; // Number of output bytes - cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen); - tempbytes = (cb)(&ctx, temp + ivlen, (const uint8_t *)datestr, len) + ivlen; + ccb = _pdfioCryptoMakeWriter(obj->pdf, obj, &ctx, temp, &ivlen); + tempbytes = (ccb)(&ctx, temp + ivlen, (const uint8_t *)datestr, len) + ivlen; - if (!_pdfioFilePuts(pdf, "<")) + if (!(cb)(cbdata, "<")) return (false); for (tempptr = temp; tempbytes > 1; tempbytes -= 2, tempptr += 2) { - if (!_pdfioFilePrintf(pdf, "%02X%02X", tempptr[0], tempptr[1])) + if (!(cb)(cbdata, "%02X%02X", tempptr[0], tempptr[1])) return (false); } if (tempbytes > 0) - return (_pdfioFilePrintf(pdf, "%02X>", *tempptr)); + return ((cb)(cbdata, "%02X>", *tempptr)); else - return (_pdfioFilePuts(pdf, ">")); + return ((cb)(cbdata, ">")); } else { - return (_pdfioFilePrintf(pdf, "%S", datestr)); + return ((cb)(cbdata, "%S", datestr)); } } case PDFIO_VALTYPE_DICT : - return (_pdfioDictWrite(v->value.dict, obj, length)); + return (_pdfioDictWrite(cb, cbdata, obj, v->value.dict, length)); case PDFIO_VALTYPE_INDIRECT : - return (_pdfioFilePrintf(pdf, " %lu %u R", (unsigned long)v->value.indirect.number, v->value.indirect.generation)); + return ((cb)(cbdata, " %lu %u R", (unsigned long)v->value.indirect.number, v->value.indirect.generation)); case PDFIO_VALTYPE_NAME : - return (_pdfioFilePrintf(pdf, "%N", v->value.name)); + return ((cb)(cbdata, "%N", v->value.name)); case PDFIO_VALTYPE_NULL : - return (_pdfioFilePuts(pdf, " null")); + return ((cb)(cbdata, " null")); case PDFIO_VALTYPE_NUMBER : - return (_pdfioFilePrintf(pdf, " %.6f", v->value.number)); + return ((cb)(cbdata, " %.6f", v->value.number)); case PDFIO_VALTYPE_STRING : - if (obj && pdf->encryption) + if (obj && obj->pdf->encryption) { // Write encrypted string... uint8_t *temp = NULL, // Encrypted bytes *tempptr; // Pointer into encrypted bytes _pdfio_crypto_ctx_t ctx; // Encryption context - _pdfio_crypto_cb_t cb; // Encryption callback + _pdfio_crypto_cb_t ccb; // Encryption callback size_t len = strlen(v->value.string), // Length of value ivlen, // Number of initialization vector bytes @@ -759,42 +761,42 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file if (len > PDFIO_MAX_STRING) { - _pdfioFileError(pdf, "Unable to write encrypted string - too long."); + _pdfioFileError(obj->pdf, "Unable to write encrypted string - too long."); return (false); } - else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL) + else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(obj->pdf)) == NULL) { - _pdfioFileError(pdf, "Unable to write encrypted string - out of memory."); + _pdfioFileError(obj->pdf, "Unable to write encrypted string - out of memory."); return (false); } - cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen); - tempbytes = (cb)(&ctx, temp + ivlen, (const uint8_t *)v->value.string, len) + ivlen; + ccb = _pdfioCryptoMakeWriter(obj->pdf, obj, &ctx, temp, &ivlen); + tempbytes = (ccb)(&ctx, temp + ivlen, (const uint8_t *)v->value.string, len) + ivlen; - if (!_pdfioFilePuts(pdf, "<")) + if (!(cb)(cbdata, "<")) goto strdone; for (tempptr = temp; tempbytes > 1; tempbytes -= 2, tempptr += 2) { - if (!_pdfioFilePrintf(pdf, "%02X%02X", tempptr[0], tempptr[1])) + if (!(cb)(cbdata, "%02X%02X", tempptr[0], tempptr[1])) goto strdone; } - if (tempbytes > 0 && !_pdfioFilePrintf(pdf, "%02X", *tempptr)) + if (tempbytes > 0 && !(cb)(cbdata, "%02X", *tempptr)) goto strdone; - ret = _pdfioFilePuts(pdf, ">"); + ret = (cb)(cbdata, ">"); strdone : - _pdfioStringFreeBuffer(pdf, (char *)temp); + _pdfioStringFreeBuffer(obj->pdf, (char *)temp); return (ret); } else { // Write unencrypted string... - return (_pdfioFilePrintf(pdf, "%S", v->value.string)); + return ((cb)(cbdata, "%S", v->value.string)); } }