}
dom_string_unref(data);
+
+ /* The only reference we retain to the newly-allocated "sheet"
+ * is via state.select_ctx->sheets. Eventually, we will
+ * destroy the sheet immediately prior to destroying the
+ * context. */
return svgtiny_OK;
}
static svgtiny_code finalise_parse_state(struct svgtiny_parse_state *state)
{
+ svgtiny_code code = svgtiny_OK;
css_error css_code;
svgtiny_cleanup_state_local(state);
lwc_string_unref(state->interned_svg_xmlns);
}
+ /* Clean up the select_ctx and any sheets that were appended
+ * to it along the way. These sheets are allocated in
+ * svgtiny_parse_style_element(), and the only references we
+ * have to them are the ones in state->select_ctx->sheets.
+ * Those are const, but we are indeed responsible for the
+ * resources, so the un-const cast below is kosher.
+ *
+ * Some of these destructors can fail, but we want to loop
+ * through the entire list regardless. */
+ unsigned int i;
+ uint32_t n_sheets;
+ const css_stylesheet* sheet;
+ css_select_ctx_count_sheets(state->select_ctx, &n_sheets);
+ for (i = 0; i < n_sheets; i++) {
+ /* Note the use of (n_sheets - 1 - i) below to
+ * remove/destroy the sheets in reverse order, last-in
+ * first-out. */
+ css_code = css_select_ctx_get_sheet(state->select_ctx,
+ n_sheets - 1 - i,
+ &sheet);
+ if (css_code != CSS_OK) {
+ /* The API just told us that there were n_sheets
+ * valid sheets. So while we attempt to handle
+ * the error gracefully in production builds,
+ * this should never happen. */
+ assert(0);
+ code = svgtiny_LIBCSS_ERROR;
+ /* If we didn't get a new sheet, don't try to
+ * remove/destroy whatever happens to live at
+ * the pointer. */
+ continue;
+ }
+ /* Remove the sheets from the context as well, since
+ * there is no promise that css_select_ctx_destroy()
+ * will not try to access them. */
+ css_code = css_select_ctx_remove_sheet(state->select_ctx, sheet);
+ if (css_code != CSS_OK) {
+ /* Same as the assert() above. This sheet arose
+ * from a call to css_select_ctx_get_sheet() a
+ * moment ago, it should be valid! */
+ assert(0);
+ code = svgtiny_LIBCSS_ERROR;
+ /* Don't try to destroy the sheet if removal
+ * failed, because that would suggest that our
+ * implied contract (that nobody else modifies
+ * our context) has been violated. */
+ continue;
+ }
+ css_code = css_stylesheet_destroy((css_stylesheet*)sheet);
+ if (css_code != CSS_OK) {
+ /* Once more, "sheet" should have been valid
+ * and un-destroyed. */
+ assert(0);
+ code = svgtiny_LIBCSS_ERROR;
+ }
+ }
+
css_code = css_select_ctx_destroy(state->select_ctx);
if (css_code != CSS_OK) {
- return svgtiny_LIBCSS_ERROR;
+ code = svgtiny_LIBCSS_ERROR;
}
- return svgtiny_OK;
+ return code;
}