5 * Sweep and mark reachable objects
8 static fz_error
*sweepref(pdf_xref
*xref
, fz_obj
*ref
);
11 sweepobj(pdf_xref
*xref
, fz_obj
*obj
)
18 for (i
= 0; i
< fz_dictlen(obj
); i
++)
20 error
= sweepobj(xref
, fz_dictgetval(obj
, i
));
28 for (i
= 0; i
< fz_arraylen(obj
); i
++)
30 error
= sweepobj(xref
, fz_arrayget(obj
, i
));
36 if (fz_isindirect(obj
))
37 return sweepref(xref
, obj
);
43 sweepref(pdf_xref
*xref
, fz_obj
*ref
)
51 if (oid
< 0 || oid
>= xref
->len
)
52 return fz_throw("rangecheck: object number out of range");
54 if (xref
->table
[oid
].mark
)
57 xref
->table
[oid
].mark
= 1;
59 error
= pdf_loadindirect(&obj
, xref
, ref
);
63 error
= sweepobj(xref
, obj
);
69 * Garbage collect objects not reachable from
70 * the trailer dictionary
74 pdf_garbagecollect(pdf_xref
*xref
)
79 pdf_logxref("garbage collect {\n");
81 for (i
= 0; i
< xref
->len
; i
++)
82 xref
->table
[i
].mark
= 0;
84 error
= sweepobj(xref
, xref
->trailer
);
88 for (i
= 0; i
< xref
->len
; i
++)
90 pdf_xrefentry
*x
= xref
->table
+ i
;
94 if (!x
->mark
&& x
->type
!= 'f' && x
->type
!= 'd')
95 pdf_deleteobject(xref
, i
, g
);
104 * Transplant (copy) objects and streams from one file to another
114 remaprefs(fz_obj
**newp
, fz_obj
*old
, struct pair
*map
, int n
)
120 if (fz_isindirect(old
))
124 for (i
= 0; i
< n
; i
++)
125 if (map
[i
].soid
== o
&& map
[i
].sgen
== g
)
126 return fz_newindirect(newp
, map
[i
].doid
, map
[i
].dgen
);
129 else if (fz_isarray(old
))
131 error
= fz_newarray(newp
, fz_arraylen(old
));
134 for (i
= 0; i
< fz_arraylen(old
); i
++)
136 tmp
= fz_arrayget(old
, i
);
137 error
= remaprefs(&tmp
, tmp
, map
, n
);
140 error
= fz_arraypush(*newp
, tmp
);
147 else if (fz_isdict(old
))
149 error
= fz_newdict(newp
, fz_dictlen(old
));
152 for (i
= 0; i
< fz_dictlen(old
); i
++)
154 key
= fz_dictgetkey(old
, i
);
155 tmp
= fz_dictgetval(old
, i
);
156 error
= remaprefs(&tmp
, tmp
, map
, n
);
159 error
= fz_dictput(*newp
, key
, tmp
);
168 *newp
= fz_keepobj(old
);
179 * Recursively copy objects from src to dst xref.
180 * Start with root object in src xref.
181 * Put the dst copy of root into newp.
184 pdf_transplant(pdf_xref
*dst
, pdf_xref
*src
, fz_obj
**newp
, fz_obj
*root
)
192 pdf_logxref("transplant {\n");
194 for (i
= 0; i
< src
->len
; i
++)
195 src
->table
[i
].mark
= 0;
197 error
= sweepobj(src
, root
);
201 for (n
= 0, i
= 0; i
< src
->len
; i
++)
202 if (src
->table
[i
].mark
)
205 pdf_logxref("marked %d\n", n
);
207 map
= fz_malloc(sizeof(struct pair
) * n
);
211 for (n
= 0, i
= 0; i
< src
->len
; i
++)
213 if (src
->table
[i
].mark
)
216 map
[n
].sgen
= src
->table
[i
].gen
;
217 if (src
->table
[i
].type
== 'o')
219 error
= pdf_allocobject(dst
, &map
[n
].doid
, &map
[n
].dgen
);
226 error
= remaprefs(newp
, root
, map
, n
);
230 for (i
= 0; i
< n
; i
++)
232 pdf_logxref("copyfrom %d %d to %d %d\n",
233 map
[i
].soid
, map
[i
].sgen
,
234 map
[i
].doid
, map
[i
].dgen
);
236 error
= pdf_loadobject(&old
, src
, map
[i
].soid
, map
[i
].sgen
);
240 if (pdf_isstream(src
, map
[i
].soid
, map
[i
].sgen
))
242 error
= pdf_loadrawstream(&stm
, src
, map
[i
].soid
, map
[i
].sgen
);
245 pdf_updatestream(dst
, map
[i
].doid
, map
[i
].dgen
, stm
);
249 error
= remaprefs(&new, old
, map
, n
);
254 pdf_updateobject(dst
, map
[i
].doid
, map
[i
].dgen
, new);