Rework debug functions, start xref stream support.

This commit is contained in:
Michael R Sweet 2021-05-06 09:51:48 -04:00
parent c0b18a7e4f
commit d2a0484d93
No known key found for this signature in database
GPG Key ID: 999559A027815955
5 changed files with 244 additions and 122 deletions

View File

@ -305,6 +305,26 @@ pdfioArrayCreate(pdfio_file_t *pdf) // I - PDF file
}
#ifdef DEBUG
//
// '_pdfioArrayDebug()' - Print the contents of an array.
//
void
_pdfioArrayDebug(pdfio_array_t *a) // I - Array
{
size_t i; // Looping var
_pdfio_value_t *v; // Current value
PDFIO_DEBUG("[");
for (i = a->num_values, v = a->values; i > 0; i --, v ++)
_pdfioValueDebug(v);
PDFIO_DEBUG("]");
}
#endif // DEBUG
//
// '_pdfioArrayDelete()' - Free the memory used by an array.
//

View File

@ -113,8 +113,7 @@ pdfioDictCreate(pdfio_file_t *pdf) // I - PDF file
//
void
_pdfioDictDebug(pdfio_dict_t *dict, // I - Dictionary
const char *prefix) // I - Prefix for each line
_pdfioDictDebug(pdfio_dict_t *dict) // I - Dictionary
{
size_t i; // Looping var
_pdfio_pair_t *pair; // Current pair
@ -122,30 +121,8 @@ _pdfioDictDebug(pdfio_dict_t *dict, // I - Dictionary
for (i = dict->num_pairs, pair = dict->pairs; i > 0; i --, pair ++)
{
switch (pair->value.type)
{
case PDFIO_VALTYPE_INDIRECT :
PDFIO_DEBUG("%s: /%s %u %u R\n", prefix, pair->key, (unsigned)pair->value.value.indirect.number, pair->value.value.indirect.generation);
break;
case PDFIO_VALTYPE_NUMBER :
PDFIO_DEBUG("%s: /%s %g\n", prefix, pair->key, pair->value.value.number);
break;
case PDFIO_VALTYPE_BOOLEAN :
PDFIO_DEBUG("%s: /%s %s\n", prefix, pair->key, pair->value.value.boolean ? "true" : "false");
break;
case PDFIO_VALTYPE_NULL :
PDFIO_DEBUG("%s: /%s null\n", prefix, pair->key);
break;
case PDFIO_VALTYPE_ARRAY :
PDFIO_DEBUG("%s: /%s [...]\n", prefix, pair->key);
break;
case PDFIO_VALTYPE_DICT :
PDFIO_DEBUG("%s: /%s <<...>>\n", prefix, pair->key);
break;
default :
PDFIO_DEBUG("%s: /%s ...\n", prefix, pair->key);
break;
}
PDFIO_DEBUG("/%s", pair->key);
_pdfioValueDebug(&pair->value);
}
}
#endif // DEBUG
@ -773,7 +750,9 @@ _pdfioDictSetValue(
#ifdef DEBUG
PDFIO_DEBUG("_pdfioDictSetValue: %lu pairs\n", (unsigned long)dict->num_pairs);
PDFIO_DEBUG_DICT(dict, "_pdfioDictSetValue");
PDFIO_DEBUG("_pdfioDictSetValue: ");
PDFIO_DEBUG_DICT(dict);
PDFIO_DEBUG("\n");
#endif // DEBUG
return (true);

View File

@ -517,6 +517,10 @@ load_xref(pdfio_file_t *pdf, // I - PDF file
char line[1024], // Line from file
*ptr; // Pointer into line
_pdfio_value_t trailer; // Trailer dictionary
intmax_t number, // Object number
num_objects, // Number of objects
offset; // Offset in file
int generation; // Generation number
while (!done)
@ -533,103 +537,153 @@ load_xref(pdfio_file_t *pdf, // I - PDF file
return (false);
}
if (strcmp(line, "xref"))
if (isdigit(line[0] & 255) && strlen(line) > 4 && !strcmp(line + strlen(line) - 4, " obj"))
{
// Cross-reference stream
pdfio_obj_t *obj; // Object
pdfio_array_t *w_array; // W array
size_t w[3]; // Size of each cross-reference field
size_t w_total; // Total length
pdfio_stream_t *st; // Stream with
unsigned char buffer[32]; // Read buffer
if ((number = strtoimax(line, &ptr, 10)) < 1)
{
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
return (false);
}
if ((generation = (int)strtol(ptr, &ptr, 10)) < 0 || generation > 65535)
{
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
return (false);
}
while (isspace(*ptr & 255))
ptr ++;
if (strcmp(ptr, "obj"))
{
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
return (false);
}
if ((obj = add_obj(pdf, (size_t)number, (unsigned short)generation, xref_offset)) == NULL)
{
_pdfioFileError(pdf, "Unable to allocate memory for object.");
return (false);
}
if (!_pdfioValueRead(pdf, &trailer))
{
_pdfioFileError(pdf, "Unable to read cross-reference stream dictionary.");
return (false);
}
else if (trailer.type != PDFIO_VALTYPE_DICT)
{
_pdfioFileError(pdf, "Cross-reference stream does not have a dictionary.");
return (false);
}
obj->value = trailer;
// TODO: read stream
}
else if (!strcmp(line, "xref"))
{
// Read the xref tables
while (_pdfioFileGets(pdf, line, sizeof(line)))
{
if (!strcmp(line, "trailer"))
break;
if (sscanf(line, "%jd%jd", &number, &num_objects) != 2)
{
_pdfioFileError(pdf, "Malformed xref table section '%s'.", line);
return (false);
}
// Read this group of objects...
for (; num_objects > 0; num_objects --, number ++)
{
// Read a line from the file and validate it...
if (_pdfioFileRead(pdf, line, 20) != 20)
return (false);
line[20] = '\0';
if (strcmp(line + 18, "\r\n") && strcmp(line + 18, " \n") && strcmp(line + 18, " \r"))
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
line[18] = '\0';
// Parse the line
if ((offset = strtoimax(line, &ptr, 10)) < 0)
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
if ((generation = (int)strtol(ptr, &ptr, 10)) < 0 || generation > 65535)
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
if (*ptr != ' ')
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
ptr ++;
if (*ptr != 'f' && *ptr != 'n')
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
if (*ptr == 'f')
continue; // Don't care about free objects...
// Create a placeholder for the object in memory...
if (pdfioFileFindObject(pdf, (size_t)number))
continue; // Don't replace newer object...
if (!add_obj(pdf, (size_t)number, (unsigned short)generation, offset))
return (false);
}
}
if (strcmp(line, "trailer"))
{
_pdfioFileError(pdf, "Missing trailer.");
return (false);
}
if (!_pdfioValueRead(pdf, &trailer))
{
_pdfioFileError(pdf, "Unable to read trailer dictionary.");
return (false);
}
else if (trailer.type != PDFIO_VALTYPE_DICT)
{
_pdfioFileError(pdf, "Trailer is not a dictionary.");
return (false);
}
}
else
{
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
return (false);
}
// Read the xref tables
while (_pdfioFileGets(pdf, line, sizeof(line)))
{
intmax_t number, // Object number
num_objects; // Number of objects
if (!strcmp(line, "trailer"))
break;
if (sscanf(line, "%jd%jd", &number, &num_objects) != 2)
{
_pdfioFileError(pdf, "Malformed xref table section '%s'.", line);
return (false);
}
// Read this group of objects...
for (; num_objects > 0; num_objects --, number ++)
{
intmax_t offset; // Offset in file
int generation; // Generation number
// Read a line from the file and validate it...
if (_pdfioFileRead(pdf, line, 20) != 20)
return (false);
line[20] = '\0';
if (strcmp(line + 18, "\r\n") && strcmp(line + 18, " \n") && strcmp(line + 18, " \r"))
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
line[18] = '\0';
// Parse the line
if ((offset = strtoimax(line, &ptr, 10)) < 0)
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
if ((generation = (int)strtol(ptr, &ptr, 10)) < 0 || generation > 65535)
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
if (*ptr != ' ')
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
ptr ++;
if (*ptr != 'f' && *ptr != 'n')
{
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
return (false);
}
if (*ptr == 'f')
continue; // Don't care about free objects...
// Create a placeholder for the object in memory...
if (pdfioFileFindObject(pdf, (size_t)number))
continue; // Don't replace newer object...
if (!add_obj(pdf, (size_t)number, (unsigned short)generation, offset))
return (false);
}
}
if (strcmp(line, "trailer"))
{
_pdfioFileError(pdf, "Missing trailer.");
return (false);
}
if (!_pdfioValueRead(pdf, &trailer))
{
_pdfioFileError(pdf, "Unable to read trailer dictionary.");
return (false);
}
else if (trailer.type != PDFIO_VALTYPE_DICT)
{
_pdfioFileError(pdf, "Trailer is not a dictionary.");
return (false);
}
PDFIO_DEBUG("load_xref: Contents of trailer dictionary:\n");
PDFIO_DEBUG_DICT(trailer.value.dict, "load_xref");
PDFIO_DEBUG("load_xref: ");
PDFIO_DEBUG_VALUE(&trailer);
PDFIO_DEBUG("\n");
if (!pdf->trailer)
{
@ -648,7 +702,7 @@ load_xref(pdfio_file_t *pdf, // I - PDF file
pdf->id_array = pdfioDictGetArray(pdf->trailer, "ID");
}
if ((xref_offset = (off_t)pdfioDictGetNumber(pdf->trailer, "Prev")) <= 0)
if ((xref_offset = (off_t)pdfioDictGetNumber(trailer.value.dict, "Prev")) <= 0)
done = true;
}

View File

@ -48,10 +48,14 @@
# ifdef DEBUG
# define PDFIO_DEBUG(...) fprintf(stderr, __VA_ARGS__)
# define PDFIO_DEBUG_DICT(dict,prefix) _pdfioDictDebug(dict, prefix)
# define PDFIO_DEBUG_ARRAY(array) _pdfioArrayDebug(array)
# define PDFIO_DEBUG_DICT(dict) _pdfioDictDebug(dict)
# define PDFIO_DEBUG_VALUE(value) _pdfioValueDebug(value)
# else
# define PDFIO_DEBUG(...)
# define PDFIO_DEBUG_DICT(dict,prefix)
# define PDFIO_DEBUG_ARRAY(array)
# define PDFIO_DEBUG_DICT(dict)
# define PDFIO_DEBUG_VALUE(value)
# endif // DEBUG
@ -183,13 +187,16 @@ typedef ssize_t (*_pdfio_tpeek_cb_t)(void *data, void *buffer, size_t bytes);
// Functions...
//
# ifdef DEBUG
extern void _pdfioArrayDebug(pdfio_array_t *a) PDFIO_INTERNAL;
# endif // DEBUG
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_INTERNAL;
extern bool _pdfioArrayWrite(pdfio_array_t *a) PDFIO_INTERNAL;
# ifdef DEBUG
extern void _pdfioDictDebug(pdfio_dict_t *dict, const char *prefix) PDFIO_INTERNAL;
extern void _pdfioDictDebug(pdfio_dict_t *dict) PDFIO_INTERNAL;
# endif // DEBUG
extern void _pdfioDictDelete(pdfio_dict_t *dict) PDFIO_INTERNAL;
extern _pdfio_value_t *_pdfioDictGetValue(pdfio_dict_t *dict, const char *key) PDFIO_INTERNAL;
@ -224,6 +231,9 @@ extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) PDFIO_INT
extern bool _pdfioTokenRead(pdfio_file_t *pdf, char *buffer, size_t bufsize, _pdfio_tpeek_cb_t peek_cb, _pdfio_tconsume_cb_t consume_cb, void *data);
extern _pdfio_value_t *_pdfioValueCopy(pdfio_file_t *pdfdst, _pdfio_value_t *vdst, pdfio_file_t *pdfsrc, _pdfio_value_t *vsrc) PDFIO_INTERNAL;
# ifdef DEBUG
extern void _pdfioValueDebug(_pdfio_value_t *v) PDFIO_INTERNAL;
# endif // DEBUG
extern void _pdfioValueDelete(_pdfio_value_t *v) PDFIO_INTERNAL;
extern _pdfio_value_t *_pdfioValueRead(pdfio_file_t *pdf, _pdfio_value_t *v) PDFIO_INTERNAL;
extern bool _pdfioValueWrite(pdfio_file_t *pdf, _pdfio_value_t *v) PDFIO_INTERNAL;

View File

@ -80,6 +80,65 @@ _pdfioValueCopy(pdfio_file_t *pdfdst, // I - Destination PDF file
}
#ifdef DEBUG
//
// '_pdfioValueDebug()' - Print the contents of a value.
//
void
_pdfioValueDebug(_pdfio_value_t *v) // I - Value
{
switch (v->type)
{
case PDFIO_VALTYPE_ARRAY :
_pdfioArrayDebug(v->value.array);
break;
case PDFIO_VALTYPE_BINARY :
{
size_t i; // Looping var
unsigned char *ptr; // Pointer into data
PDFIO_DEBUG("<");
for (i = v->value.binary.datalen, ptr = v->value.binary.data; i > 0; i --, ptr ++)
PDFIO_DEBUG("%02X", *ptr);
PDFIO_DEBUG(">");
}
break;
case PDFIO_VALTYPE_BOOLEAN :
PDFIO_DEBUG(v->value.boolean ? "true" : "false");
break;
case PDFIO_VALTYPE_DATE :
// TODO: Implement date value support
PDFIO_DEBUG("(D:YYYYMMDDhhmmssZ)");
break;
case PDFIO_VALTYPE_DICT :
PDFIO_DEBUG("<<");
_pdfioDictDebug(v->value.dict);
PDFIO_DEBUG(">>");
break;
case PDFIO_VALTYPE_INDIRECT :
PDFIO_DEBUG(" %lu %u R", (unsigned long)v->value.indirect.number, v->value.indirect.generation);
break;
case PDFIO_VALTYPE_NAME :
PDFIO_DEBUG("/%s", v->value.name);
break;
case PDFIO_VALTYPE_NULL :
PDFIO_DEBUG(" null");
break;
case PDFIO_VALTYPE_NUMBER :
PDFIO_DEBUG(" %g", v->value.number);
break;
case PDFIO_VALTYPE_STRING :
PDFIO_DEBUG("(%s)", v->value.string);
break;
default :
break;
}
}
#endif // DEBUG
//
// '_pdfioValueDelete()' - Free the memory used by a value.
//