Minor refactoring to more easily add in object stream support (Issue #101)

This commit is contained in:
Michael R Sweet
2026-01-18 19:29:17 -05:00
parent a818dee123
commit e61e08b5d2
6 changed files with 78 additions and 68 deletions

View File

@@ -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, "]"));
}

View File

@@ -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, ">>"));
}

View File

@@ -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;

View File

@@ -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"));

View File

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

View File

@@ -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));
}
}