From f3b877ef70858a39846f2c206482703cd395d7d6 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 22 Nov 2015 12:04:43 +0000 Subject: Allow more than just bloom to be stored on nodes. We now have a css_node_data struct which is sored on nodes. It currently contians just the bloom filter. --- src/select/select.c | 129 ++++++++++++++++++++++++++++++++++------------------ src/select/select.h | 6 ++- 2 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index c8fdb45..30ea622 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -154,15 +154,41 @@ static void dump_chain(const css_selector *selector); #endif +static css_error css__create_node_data(struct css_node_data **node_data) +{ + struct css_node_data *nd; + + nd = calloc(sizeof(struct css_node_data), 1); + if (nd == NULL) { + return CSS_NOMEM; + } + + *node_data = nd; + + return CSS_OK; +} + +static void css__destroy_node_data(struct css_node_data *node_data) +{ + assert(node_data != NULL); + + if (node_data->bloom != NULL) { + free(node_data->bloom); + } + + free(node_data); +} + + /* Exported function documented in public select.h header. */ css_error css_libcss_node_data_handler(css_select_handler *handler, css_node_data_action action, void *pw, void *node, void *clone_node, void *libcss_node_data) { - css_bloom *bloom = libcss_node_data; - css_bloom *clone_bloom = NULL; + struct css_node_data *node_data = libcss_node_data; css_error error; - unsigned int i; + + UNUSED(clone_node); if (handler == NULL || libcss_node_data == NULL || handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) { @@ -171,7 +197,7 @@ css_error css_libcss_node_data_handler(css_select_handler *handler, switch (action) { case CSS_NODE_DELETED: - free(bloom); + css__destroy_node_data(node_data); break; case CSS_NODE_MODIFIED: @@ -180,9 +206,9 @@ css_error css_libcss_node_data_handler(css_select_handler *handler, return CSS_BADPARM; } - free(bloom); + css__destroy_node_data(node_data); - /* Don't bother rebuilding bloom here, it can be done + /* Don't bother rebuilding node_data, it can be done * when the node is selected for. Just ensure the * client drops its reference to the libcss_node_data. */ error = handler->set_libcss_node_data(pw, node, NULL); @@ -192,25 +218,10 @@ css_error css_libcss_node_data_handler(css_select_handler *handler, break; case CSS_NODE_CLONED: - if (node == NULL || clone_node == NULL) { - return CSS_BADPARM; - } - - clone_bloom = malloc(sizeof(css_bloom) * CSS_BLOOM_SIZE); - if (clone_bloom == NULL) { - return CSS_NOMEM; - } - - for (i = 0; i < CSS_BLOOM_SIZE; i++) { - clone_bloom[i] = bloom[i]; - } - - error = handler->set_libcss_node_data(pw, clone_node, - clone_bloom); - if (error != CSS_OK) { - free(clone_bloom); - return error; - } + /* TODO: is it worth cloning libcss data? We only store + * data on the nodes as an optimisation, which is + * unlikely to be valid for most cloning cases. + */ break; default: @@ -484,6 +495,7 @@ css_error css_select_default_style(css_select_ctx *ctx, return CSS_OK; } + /** * Get a bloom filter for the parent node * @@ -500,18 +512,25 @@ static css_error css__get_parent_bloom(void *parent, css_select_handler *handler, void *pw, css_bloom **parent_bloom) { - css_error error; + struct css_node_data *node_data = NULL; css_bloom *bloom = NULL; + css_error error; /* Get parent node's bloom filter */ if (parent != NULL) { /* Get parent bloom filter */ - /* Hideous casting to avoid warnings on all platforms - * we build for. */ + struct css_node_data *node_data; + + /* Hideous casting to avoid warnings on all platforms + * we build for. */ error = handler->get_libcss_node_data(pw, parent, - (void **) (void *) &bloom); - if (error != CSS_OK) + (void **) (void *) &node_data); + if (error != CSS_OK) { return error; + } + if (node_data != NULL) { + bloom = node_data->bloom; + } } if (bloom == NULL) { @@ -534,12 +553,21 @@ static css_error css__get_parent_bloom(void *parent, bloom[i] = ~0; } - /* Set parent node bloom filter */ - error = handler->set_libcss_node_data(pw, - parent, bloom); - if (error != CSS_OK) { - free(bloom); - return error; + if (node_data == NULL) { + error = css__create_node_data(&node_data); + if (error != CSS_OK) { + free(bloom); + return error; + } + node_data->bloom = bloom; + + /* Set parent node bloom filter */ + error = handler->set_libcss_node_data(pw, + parent, node_data); + if (error != CSS_OK) { + css__destroy_node_data(node_data); + return error; + } } } else { /* No ancestors; empty bloom filter */ @@ -554,14 +582,14 @@ static css_error css__get_parent_bloom(void *parent, } /** - * Set a node's bloom filter + * Set a node's data * - * \param parent Node to set bloom filter for + * \param parent Node to set node data for * \param handler Dispatch table of handler functions * \param pw Client-specific private data for handler functions * \return CSS_OK on success, appropriate error otherwise. */ -static css_error css__set_node_bloom(void *node, css_select_state *state, +static css_error css__set_node_data(void *node, css_select_state *state, css_select_handler *handler, void *pw) { css_error error; @@ -606,13 +634,16 @@ static css_error css__set_node_bloom(void *node, css_select_state *state, } /* Merge parent bloom into node bloom */ - css_bloom_merge(state->bloom, bloom); + css_bloom_merge(state->node_data->bloom, bloom); + state->node_data->bloom = bloom; /* Set node bloom filter */ - error = handler->set_libcss_node_data(pw, node, bloom); + error = handler->set_libcss_node_data(pw, node, state->node_data); if (error != CSS_OK) goto cleanup; + state->node_data = NULL; + return CSS_OK; cleanup: @@ -666,6 +697,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, state.media = media; state.handler = handler; state.pw = pw; + state.node_data = NULL; state.next_reject = state.reject_cache + (N_ELEMENTS(state.reject_cache) - 1); @@ -685,6 +717,11 @@ css_error css_select_style(css_select_ctx *ctx, void *node, return error; } + error = css__create_node_data(&state.node_data); + if (error != CSS_OK) { + goto cleanup; + } + error = handler->parent_node(pw, node, &parent); if (error != CSS_OK) goto cleanup; @@ -693,7 +730,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, if (error != CSS_OK) { goto cleanup; } - state.bloom = parent_bloom; + state.node_data->bloom = parent_bloom; /* Get node's name */ error = handler->node_name(pw, node, &state.element); @@ -844,7 +881,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, } } - error = css__set_node_bloom(node, &state, handler, pw); + error = css__set_node_data(node, &state, handler, pw); if (error != CSS_OK) { goto cleanup; } @@ -866,6 +903,10 @@ cleanup: free(parent_bloom); } + if (state.node_data != NULL) { + css__destroy_node_data(state.node_data); + } + if (state.classes != NULL) { for (i = 0; i < state.n_classes; i++) lwc_string_unref(state.classes[i]); @@ -1639,7 +1680,7 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx, /* Set up general selector chain requirments */ req.media = state->media; - req.node_bloom = state->bloom; + req.node_bloom = state->node_data->bloom; req.uni = ctx->universal; /* Find hash chain that applies to current node */ diff --git a/src/select/select.h b/src/select/select.h index fad86ac..196914d 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -31,6 +31,10 @@ typedef struct prop_state { inherit : 1; /* Property is set to inherit */ } prop_state; +struct css_node_data { + css_bloom *bloom; +}; + /** * Selection state */ @@ -58,7 +62,7 @@ typedef struct css_select_state { reject_item reject_cache[128]; /* Reject cache (filled from end) */ reject_item *next_reject; /* Next free slot in reject cache */ - const css_bloom *bloom; /* Bloom filter */ + struct css_node_data *node_data; /* Data we'll store on node */ prop_state props[CSS_N_PROPERTIES][CSS_PSEUDO_ELEMENT_COUNT]; } css_select_state; -- cgit v1.2.3