Coverage Report

Created: 2025-11-07 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/pdf/pdf-store.c
Line
Count
Source
1
// Copyright (C) 2004-2021 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
#include "mupdf/pdf.h"
25
26
#include <assert.h>
27
28
static int
29
pdf_make_hash_key(fz_context *ctx, fz_store_hash *hash, void *key_)
30
38
{
31
38
  pdf_obj *key = (pdf_obj *)key_;
32
33
38
  if (!pdf_is_indirect(ctx, key))
34
0
    return 0;
35
38
  hash->u.pi.i = pdf_to_num(ctx, key);
36
38
  hash->u.pi.ptr = pdf_get_indirect_document(ctx, key);
37
38
  return 1;
38
38
}
39
40
static void *
41
pdf_keep_key(fz_context *ctx, void *key)
42
6
{
43
6
  return (void *)pdf_keep_obj(ctx, (pdf_obj *)key);
44
6
}
45
46
static void
47
pdf_drop_key(fz_context *ctx, void *key)
48
6
{
49
6
  pdf_drop_obj(ctx, (pdf_obj *)key);
50
6
}
51
52
static int
53
pdf_cmp_key(fz_context *ctx, void *k0, void *k1)
54
0
{
55
0
  return pdf_objcmp(ctx, (pdf_obj *)k0, (pdf_obj *)k1);
56
0
}
57
58
static void
59
pdf_format_key(fz_context *ctx, char *s, size_t n, void *key_)
60
0
{
61
0
  pdf_obj *key = (pdf_obj *)key_;
62
0
  if (pdf_is_indirect(ctx, key))
63
0
    fz_snprintf(s, n, "(%d 0 R)", pdf_to_num(ctx, key));
64
0
  else
65
0
  {
66
0
    size_t t;
67
0
    char *p = pdf_sprint_obj(ctx, s, n, &t, key, 1, 0);
68
0
    if (p != s) {
69
0
      fz_strlcpy(s, p, n);
70
0
      fz_free(ctx, p);
71
0
    }
72
0
  }
73
0
}
74
75
static const fz_store_type pdf_obj_store_type =
76
{
77
  "pdf_obj",
78
  pdf_make_hash_key,
79
  pdf_keep_key,
80
  pdf_drop_key,
81
  pdf_cmp_key,
82
  pdf_format_key,
83
  NULL
84
};
85
86
void
87
pdf_store_item(fz_context *ctx, pdf_obj *key, void *val, size_t itemsize)
88
6
{
89
6
  void *existing;
90
91
6
  assert(pdf_is_name(ctx, key) || pdf_is_array(ctx, key) || pdf_is_dict(ctx, key) || pdf_is_indirect(ctx, key));
92
6
  existing = fz_store_item(ctx, key, val, itemsize, &pdf_obj_store_type);
93
6
  if (existing)
94
0
    fz_warn(ctx, "unexpectedly replacing entry in PDF store");
95
6
}
96
97
void *
98
pdf_find_item(fz_context *ctx, fz_store_drop_fn *drop, pdf_obj *key)
99
26
{
100
26
  return fz_find_item(ctx, drop, key, &pdf_obj_store_type);
101
26
}
102
103
void
104
pdf_remove_item(fz_context *ctx, fz_store_drop_fn *drop, pdf_obj *key)
105
0
{
106
0
  fz_remove_item(ctx, drop, key, &pdf_obj_store_type);
107
0
}
108
109
static int
110
pdf_filter_store(fz_context *ctx, void *doc_, void *key)
111
6
{
112
6
  pdf_document *doc = (pdf_document *)doc_;
113
6
  pdf_obj *obj = (pdf_obj *)key;
114
6
  pdf_document *key_doc = pdf_get_bound_document(ctx, obj);
115
116
6
  return (doc == key_doc);
117
6
}
118
119
void
120
pdf_empty_store(fz_context *ctx, pdf_document *doc)
121
16
{
122
16
  fz_filter_store(ctx, pdf_filter_store, doc, &pdf_obj_store_type);
123
16
  fz_drop_drawn_tiles_for_document(ctx, (fz_document *)doc);
124
16
}
125
126
static int
127
pdf_filter_locals(fz_context *ctx, void *doc_, void *key)
128
0
{
129
0
  pdf_document *doc = (pdf_document *)doc_;
130
0
  pdf_obj *obj = (pdf_obj *)key;
131
0
  pdf_document *key_doc = pdf_get_bound_document(ctx, obj);
132
133
0
  return (doc == key_doc && pdf_is_local_object(ctx, doc, obj));
134
0
}
135
136
void pdf_purge_locals_from_store(fz_context *ctx, pdf_document *doc)
137
16
{
138
16
  fz_filter_store(ctx, pdf_filter_locals, doc, &pdf_obj_store_type);
139
16
}
140
141
struct doc_num_info {
142
  pdf_document *doc;
143
  int num;
144
};
145
146
static int
147
pdf_filter_object_number(fz_context *ctx, void *ref_, void *key_)
148
0
{
149
0
  struct doc_num_info *ref = ref_;
150
0
  pdf_obj *key_obj = (pdf_obj *)key_;
151
0
  pdf_document *key_doc = pdf_get_bound_document(ctx, key_obj);
152
0
  return (ref->doc == key_doc && ref->num == pdf_to_num(ctx, key_obj));
153
0
}
154
155
void pdf_purge_object_from_store(fz_context *ctx, pdf_document *doc, int num)
156
0
{
157
0
  struct doc_num_info ref = { doc, num };
158
0
  fz_filter_store(ctx, pdf_filter_object_number, &ref, &pdf_obj_store_type);
159
0
}