summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_dict.c')
-rw-r--r--pdf/pdf_dict.c223
1 files changed, 152 insertions, 71 deletions
diff --git a/pdf/pdf_dict.c b/pdf/pdf_dict.c
index 34356dfe..217cb6db 100644
--- a/pdf/pdf_dict.c
+++ b/pdf/pdf_dict.c
@@ -140,7 +140,7 @@ int pdfi_dict_from_stack(pdf_context *ctx, uint32_t indirect_num, uint32_t indir
i = (index / 2) - 1;
/* In PDF keys are *required* to be names, so we ought to check that here */
- if (((pdf_obj *)ctx->stack_top[-2])->type == PDF_NAME) {
+ if (pdfi_type_of((pdf_obj *)ctx->stack_top[-2]) == PDF_NAME) {
d->list[i].key = ctx->stack_top[-2];
pdfi_countup(d->list[i].key);
#if DEBUG_DICT
@@ -149,7 +149,7 @@ int pdfi_dict_from_stack(pdf_context *ctx, uint32_t indirect_num, uint32_t indir
d->list[i].value = ctx->stack_top[-1];
pdfi_countup(d->list[i].value);
} else {
- if (convert_string_keys && ((pdf_obj *)ctx->stack_top[-2])->type == PDF_STRING) {
+ if (convert_string_keys && (pdfi_type_of((pdf_obj *)ctx->stack_top[-2]) == PDF_STRING)) {
pdf_name *n;
code = pdfi_dict_name_from_string(ctx, (pdf_string *)ctx->stack_top[-2], &n);
if (code < 0) {
@@ -266,7 +266,7 @@ static int pdfi_dict_find_unsorted(pdf_context *ctx, pdf_dict *d, const char *Ke
for (i=0;i< d->entries;i++) {
t = (pdf_name *)d->list[i].key;
- if (t && t->type == PDF_NAME) {
+ if (t && pdfi_type_of(t) == PDF_NAME) {
if (pdfi_name_is((pdf_name *)t, Key)) {
return i;
}
@@ -315,14 +315,14 @@ int pdfi_dict_get_common(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj
*o = NULL;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
index = pdfi_dict_find(ctx, d, Key, true);
if (index < 0)
return index;
- if (d->list[index].value->type == PDF_INDIRECT) {
+ if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
if (r->ref_object_num == d->object_num)
@@ -340,8 +340,11 @@ int pdfi_dict_get_common(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj
* referencing and never counts down to 0, leading to a memory leak.
* This is clearly an error, so flag it and don't replace the indirect reference.
*/
- if ((*o)->object_num == 0 || (*o)->object_num != d->object_num)
- {
+ if ((*o) < (pdf_obj *)(uintptr_t)(TOKEN__LAST_KEY)) {
+ /* "FAST" object, therefore can't be a problem. */
+ pdfi_countdown(d->list[index].value);
+ d->list[index].value = *o;
+ } else if ((*o)->object_num == 0 || (*o)->object_num != d->object_num) {
pdfi_countdown(d->list[index].value);
d->list[index].value = *o;
} else {
@@ -364,7 +367,7 @@ int pdfi_dict_get_no_deref(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, p
*o = NULL;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
index = pdfi_dict_find_key(ctx, d, Key, true);
@@ -386,14 +389,14 @@ int pdfi_dict_get_by_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf
*o = NULL;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
index = pdfi_dict_find_key(ctx, d, Key, true);
if (index < 0)
return index;
- if (d->list[index].value->type == PDF_INDIRECT) {
+ if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
code = pdfi_deref_loop_detect(ctx, r->ref_object_num, r->ref_generation_num, o);
@@ -414,14 +417,14 @@ int pdfi_dict_get_ref(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_indire
*o = NULL;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
index = pdfi_dict_find(ctx, d, Key, true);
if (index < 0)
return index;
- if (d->list[index].value->type == PDF_INDIRECT) {
+ if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
*o = (pdf_indirect_ref *)d->list[index].value;
pdfi_countup(*o);
return 0;
@@ -444,7 +447,7 @@ static int pdfi_dict_get_no_store_R_inner(pdf_context *ctx, pdf_dict *d, const c
*o = NULL;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
if (strKey == NULL)
@@ -455,7 +458,7 @@ static int pdfi_dict_get_no_store_R_inner(pdf_context *ctx, pdf_dict *d, const c
if (index < 0)
return index;
- if (d->list[index].value->type == PDF_INDIRECT) {
+ if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, o);
@@ -500,7 +503,7 @@ int pdfi_dict_get_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_t
if (code < 0)
return code;
- if ((*o)->type != type) {
+ if (pdfi_type_of(*o) != type) {
pdfi_countdown(*o);
*o = NULL;
return_error(gs_error_typecheck);
@@ -524,15 +527,14 @@ pdfi_dict_get_int2(pdf_context *ctx, pdf_dict *d, const char *Key1,
int pdfi_dict_get_int(pdf_context *ctx, pdf_dict *d, const char *Key, int64_t *i)
{
int code;
- pdf_num *n;
+ pdf_obj *n;
- code = pdfi_dict_get_type(ctx, d, Key, PDF_INT, (pdf_obj **)&n);
+ code = pdfi_dict_get(ctx, d, Key, &n);
if (code < 0)
return code;
-
- *i = n->value.i;
+ code = pdfi_obj_to_int(ctx, n, i);
pdfi_countdown(n);
- return 0;
+ return code;
}
/* Get an int from dict, and if undefined, return provided default */
@@ -566,15 +568,24 @@ pdfi_dict_get_bool2(pdf_context *ctx, pdf_dict *d, const char *Key1,
int pdfi_dict_get_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *val)
{
int code;
- pdf_bool *b;
+ pdf_obj *b;
- code = pdfi_dict_get_type(ctx, d, Key, PDF_BOOL, (pdf_obj **)&b);
+ code = pdfi_dict_get(ctx, d, Key, &b);
if (code < 0)
return code;
- *val = b->value;
+ if (b == PDF_TRUE_OBJ) {
+ *val = 1;
+ return 0;
+ } else if (b == PDF_FALSE_OBJ) {
+ *val = 0;
+ return 0;
+ }
+
pdfi_countdown(b);
- return 0;
+
+ *val = 0; /* Be consistent at least! */
+ return_error(gs_error_typecheck);
}
int pdfi_dict_get_number2(pdf_context *ctx, pdf_dict *d, const char *Key1, const char *Key2, double *f)
@@ -590,23 +601,15 @@ int pdfi_dict_get_number2(pdf_context *ctx, pdf_dict *d, const char *Key1, const
int pdfi_dict_get_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f)
{
int code;
- pdf_num *o;
+ pdf_obj *o;
- code = pdfi_dict_get(ctx, d, Key, (pdf_obj **)&o);
+ code = pdfi_dict_get(ctx, d, Key, &o);
if (code < 0)
return code;
- if (o->type == PDF_INT) {
- *f = (double)(o->value.i);
- } else {
- if (o->type == PDF_REAL){
- *f = o->value.d;
- } else {
- pdfi_countdown(o);
- return_error(gs_error_typecheck);
- }
- }
+ code = pdfi_obj_to_real(ctx, o, f);
pdfi_countdown(o);
- return 0;
+
+ return code;
}
/* convenience functions for retrieving arrys, see shadings and functions */
@@ -627,7 +630,7 @@ int fill_domain_from_dict(pdf_context *ctx, float *parray, int size, pdf_dict *d
code = pdfi_dict_get(ctx, dict, "Domain", (pdf_obj **)&a);
if (code < 0)
return code;
- if (a->type != PDF_ARRAY) {
+ if (pdfi_type_of(a) != PDF_ARRAY) {
pdfi_countdown(a);
return_error(gs_error_typecheck);
}
@@ -659,7 +662,7 @@ int fill_float_array_from_dict(pdf_context *ctx, float *parray, int size, pdf_di
code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
if (code < 0)
return code;
- if (a->type != PDF_ARRAY) {
+ if (pdfi_type_of(a) != PDF_ARRAY) {
code = gs_note_error(gs_error_typecheck);
goto exit;
}
@@ -685,13 +688,13 @@ int fill_bool_array_from_dict(pdf_context *ctx, bool *parray, int size, pdf_dict
{
int code, i;
pdf_array *a = NULL;
- pdf_bool *o;
+ pdf_obj *o;
uint64_t array_size;
code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
if (code < 0)
return code;
- if (a->type != PDF_ARRAY) {
+ if (pdfi_type_of(a) != PDF_ARRAY) {
pdfi_countdown(a);
return_error(gs_error_typecheck);
}
@@ -700,13 +703,20 @@ int fill_bool_array_from_dict(pdf_context *ctx, bool *parray, int size, pdf_dict
return_error(gs_error_rangecheck);
for (i=0;i< array_size;i++) {
- code = pdfi_array_get_type(ctx, a, (uint64_t)i, PDF_BOOL, (pdf_obj **)&o);
+ code = pdfi_array_get(ctx, a, (uint64_t)i, (pdf_obj **)&o);
if (code < 0) {
pdfi_countdown(a);
return_error(code);
}
- parray[i] = o->value;
- pdfi_countdown(o);
+ if (o == PDF_TRUE_OBJ) {
+ parray[i] = 1;
+ } else if (o == PDF_FALSE_OBJ) {
+ parray[i] = 0;
+ } else {
+ pdfi_countdown(o);
+ pdfi_countdown(a);
+ return_error(gs_error_typecheck);
+ }
}
pdfi_countdown(a);
return array_size;
@@ -722,7 +732,7 @@ int fill_matrix_from_dict(pdf_context *ctx, float *parray, pdf_dict *dict)
code = pdfi_dict_get(ctx, dict, "Matrix", (pdf_obj **)&a);
if (code < 0)
return code;
- if (a->type != PDF_ARRAY) {
+ if (pdfi_type_of(a) != PDF_ARRAY) {
pdfi_countdown(a);
return_error(gs_error_typecheck);
}
@@ -758,7 +768,7 @@ int pdfi_make_float_array_from_dict(pdf_context *ctx, float **parray, pdf_dict *
code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
if (code < 0)
return code;
- if (a->type != PDF_ARRAY) {
+ if (pdfi_type_of(a) != PDF_ARRAY) {
pdfi_countdown(a);
return_error(gs_error_typecheck);
}
@@ -795,7 +805,7 @@ int pdfi_make_int_array_from_dict(pdf_context *ctx, int **parray, pdf_dict *dict
code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
if (code < 0)
return code;
- if (a->type != PDF_ARRAY) {
+ if (pdfi_type_of(a) != PDF_ARRAY) {
pdfi_countdown(a);
return_error(gs_error_typecheck);
}
@@ -828,10 +838,10 @@ int pdfi_dict_put_obj(pdf_context *ctx, pdf_dict *d, pdf_obj *Key, pdf_obj *valu
int i;
pdf_dict_entry *new_list;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
- if (Key->type != PDF_NAME)
+ if (pdfi_type_of(Key) != PDF_NAME)
return_error(gs_error_typecheck);
/* First, do we have a Key/value pair already ? */
@@ -883,6 +893,60 @@ int pdfi_dict_put_obj(pdf_context *ctx, pdf_dict *d, pdf_obj *Key, pdf_obj *valu
return 0;
}
+/*
+ * Be very cautious using this routine; it does not check to see if a key already exists
+ * in a dictionary!. This is initially at least intended for use by the font code, to build
+ * a CharStrings dictionary. We do that by adding each glyph individually with a name
+ * created from a loop counter, so we know there cannot be any duplicates, and the time
+ * taken to check that each of 64K names was unique was quite significant.
+ * See bug #705534, the old PDF interpreter (nullpage, 72 dpi) runs this file in ~20 seconds
+ * pdfi runs it in around 40 seconds. With this change it runs in around 3 seconds. THis is,
+ * of course, an extreme example.
+ */
+int pdfi_dict_put_unchecked(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value)
+{
+ int i, code = 0;
+ pdf_dict_entry *new_list;
+ pdf_obj *key = NULL;
+
+ code = pdfi_name_alloc(ctx, (byte *)Key, strlen(Key), &key);
+ if (code < 0)
+ return code;
+ pdfi_countup(key);
+
+ /* Nope, its a new Key */
+ if (d->size > d->entries) {
+ /* We have a hole, find and use it */
+ for (i=0;i< d->size;i++) {
+ if (d->list[i].key == NULL) {
+ d->list[i].key = key;
+ d->list[i].value = value;
+ pdfi_countup(value);
+ d->entries++;
+ return 0;
+ }
+ }
+ }
+
+ new_list = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (d->size + 1) * sizeof(pdf_dict_entry), "pdfi_dict_put reallocate dictionary key/values");
+ if (new_list == NULL) {
+ return_error(gs_error_VMerror);
+ }
+ memcpy(new_list, d->list, d->size * sizeof(pdf_dict_entry));
+
+ gs_free_object(ctx->memory, d->list, "pdfi_dict_put key/value reallocation");
+
+ d->list = new_list;
+
+ d->list[d->size].key = key;
+ d->list[d->size].value = value;
+ d->size++;
+ d->entries++;
+ pdfi_countup(value);
+
+ return 0;
+}
+
/* Put into dictionary with key as string */
int pdfi_dict_put(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value)
{
@@ -914,15 +978,9 @@ int pdfi_dict_put_int(pdf_context *ctx, pdf_dict *d, const char *key, int64_t va
int pdfi_dict_put_bool(pdf_context *ctx, pdf_dict *d, const char *key, bool value)
{
- int code;
- pdf_bool *obj = NULL;
-
- code = pdfi_object_alloc(ctx, PDF_BOOL, 0, (pdf_obj **)&obj);
- if (code < 0)
- return code;
+ pdf_obj *obj = (value ? PDF_TRUE_OBJ : PDF_FALSE_OBJ);
- obj->value = value;
- return pdfi_dict_put(ctx, d, key, (pdf_obj *)obj);
+ return pdfi_dict_put(ctx, d, key, obj);
}
int pdfi_dict_put_name(pdf_context *ctx, pdf_dict *d, const char *key, const char *name)
@@ -957,7 +1015,7 @@ int pdfi_dict_known(pdf_context *ctx, pdf_dict *d, const char *Key, bool *known)
{
int i;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
*known = false;
@@ -972,7 +1030,7 @@ int pdfi_dict_known_by_key(pdf_context *ctx, pdf_dict *d, pdf_name *Key, bool *k
{
int i;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
*known = false;
@@ -1030,6 +1088,25 @@ int pdfi_dict_knownget_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_
return 1;
}
+int pdfi_dict_knownget_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *b)
+{
+ bool known = false;
+ int code;
+
+ code = pdfi_dict_known(ctx, d, Key, &known);
+ if (code < 0)
+ return code;
+
+ if (known == false)
+ return 0;
+
+ code = pdfi_dict_get_bool(ctx, d, Key, b);
+ if (code < 0)
+ return code;
+
+ return 1;
+}
+
/* Like pdfi_dict_knownget_type() but retrieves numbers (two possible types)
*/
int pdfi_dict_knownget_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f)
@@ -1055,7 +1132,7 @@ int pdfi_dict_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value
{
int code;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
while (1) {
@@ -1078,7 +1155,7 @@ int pdfi_dict_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value
continue;
}
- if (d->list[*index].value->type == PDF_INDIRECT) {
+ if (pdfi_type_of(d->list[*index].value) == PDF_INDIRECT) {
pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[*index].value;
pdf_obj *o;
@@ -1113,7 +1190,7 @@ int pdfi_dict_key_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, uint64_t *i
{
uint64_t *i = index;
- if (d->type != PDF_DICT)
+ if (pdfi_type_of(d) != PDF_DICT)
return_error(gs_error_typecheck);
while (1) {
@@ -1169,7 +1246,7 @@ int64_t pdfi_stream_length(pdf_context *ctx, pdf_stream *stream)
int64_t Length = 0;
int code;
- if (stream->type != PDF_STREAM)
+ if (pdfi_type_of(stream) != PDF_STREAM)
return 0;
if (stream->length_valid)
@@ -1195,14 +1272,14 @@ int64_t pdfi_stream_length(pdf_context *ctx, pdf_stream *stream)
*/
gs_offset_t pdfi_stream_offset(pdf_context *ctx, pdf_stream *stream)
{
- if (stream->type != PDF_STREAM)
+ if (pdfi_type_of(stream) != PDF_STREAM)
return 0;
return stream->stream_offset;
}
pdf_stream *pdfi_stream_parent(pdf_context *ctx, pdf_stream *stream)
{
- if (stream->type != PDF_STREAM)
+ if (pdfi_type_of(stream) != PDF_STREAM)
return 0;
return (pdf_stream *)stream->parent_obj;
}
@@ -1233,11 +1310,15 @@ void pdfi_clear_stream_parent(pdf_context *ctx, pdf_stream *stream)
int pdfi_dict_from_obj(pdf_context *ctx, pdf_obj *obj, pdf_dict **dict)
{
*dict = NULL;
- if (obj->type == PDF_DICT)
- *dict = (pdf_dict *)obj;
- else if (obj->type == PDF_STREAM)
- *dict = ((pdf_stream *)obj)->stream_dict;
- else
- return_error(gs_error_typecheck);
+ switch (pdfi_type_of(obj)) {
+ case PDF_DICT:
+ *dict = (pdf_dict *)obj;
+ break;
+ case PDF_STREAM:
+ *dict = ((pdf_stream *)obj)->stream_dict;
+ break;
+ default:
+ return_error(gs_error_typecheck);
+ }
return 0;
}