summaryrefslogtreecommitdiff
path: root/src/select
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2013-12-13 20:16:52 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2013-12-13 20:16:52 +0000
commit1b95fec601a3d006ba6b99e1dea3f61c3c8318fc (patch)
tree1a0c3a78afe1db919ff6b4c56a6c3f2e01d03607 /src/select
parente3372335ec1628e1d6ef1a4fd63b11bb47f2e0e6 (diff)
downloadlibcss-1b95fec601a3d006ba6b99e1dea3f61c3c8318fc.tar.gz
libcss-1b95fec601a3d006ba6b99e1dea3f61c3c8318fc.tar.bz2
Various changes which modify API and ABI:
- Remove client allocation function. - Change node_classes callback not to yield array ownership to libcss. - Node bloom filters now built by, during selection libcss. - Added selection callbacks to get and set data on document nodes. Test suite, example, and documentation updated to match.
Diffstat (limited to 'src/select')
-rw-r--r--src/select/bloom.h205
-rw-r--r--src/select/computed.c34
-rw-r--r--src/select/computed.h3
-rw-r--r--src/select/font_face.c20
-rw-r--r--src/select/font_face.h6
-rw-r--r--src/select/hash.c54
-rw-r--r--src/select/hash.h6
-rw-r--r--src/select/properties/content.c31
-rw-r--r--src/select/properties/counter_increment.c9
-rw-r--r--src/select/properties/counter_reset.c9
-rw-r--r--src/select/properties/cursor.c32
-rw-r--r--src/select/properties/font_family.c30
-rw-r--r--src/select/properties/helpers.c19
-rw-r--r--src/select/properties/quotes.c34
-rw-r--r--src/select/properties/voice_family.c22
-rw-r--r--src/select/propset.h18
-rw-r--r--src/select/select.c261
-rw-r--r--src/select/select.h4
18 files changed, 542 insertions, 255 deletions
diff --git a/src/select/bloom.h b/src/select/bloom.h
new file mode 100644
index 0000000..8c1da3f
--- /dev/null
+++ b/src/select/bloom.h
@@ -0,0 +1,205 @@
+/*
+ * This file is part of LibCSS.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2013 Michael Drake <tlsa@netsurf-browser.org>
+ */
+
+/** \file
+ * Bloom filter for CSS style selection optimisation.
+ *
+ * Attempting to match CSS rules by querying the client about DOM nodes via
+ * the selection callbacks is slow. To avoid this, clients may pass a node
+ * bloom filter to css_get_style. This bloom filter has bits set according
+ * to the node's ancestor element names, class names and id names.
+ *
+ * Generate the bloom filter by adding calling css_bloom_add_hash() on each
+ * ancestor element name, class name and id name for the node.
+ *
+ * Use the insesnsitive lwc_string:
+ *
+ * lwc_string_hash_value(str->insensitive)
+ */
+
+#ifndef libcss_bloom_h_
+#define libcss_bloom_h_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/* Size of bloom filter as multiple of 32 bits.
+ * Has to be 4, 8, or 16.
+ * Larger increases optimisation of style selection engine but uses more memory.
+ */
+#define CSS_BLOOM_SIZE 4
+
+
+
+/* Check valid bloom filter size */
+#if !(CSS_BLOOM_SIZE == 4 || CSS_BLOOM_SIZE == 8 || CSS_BLOOM_SIZE == 16)
+# error Unsupported bloom filter size. Size must be {4|8|16}.
+#endif
+
+/* Setup index bit mask */
+#define INDEX_BITS_N (CSS_BLOOM_SIZE - 1)
+
+
+
+/* type for bloom */
+typedef uint32_t css_bloom;
+
+
+/**
+ * Add a hash value to the bloom filter.
+ *
+ * \param bloom bloom filter to insert into
+ * \param hash libwapcaplet hash value to insert
+ */
+static inline void css_bloom_add_hash(css_bloom bloom[CSS_BLOOM_SIZE],
+ lwc_hash hash)
+{
+ unsigned int bit = hash & 0x1f; /* Top 5 bits */
+ unsigned int index = (hash >> 5) & INDEX_BITS_N; /* Next N bits */
+
+ bloom[index] |= (1 << bit);
+}
+
+
+/**
+ * Test whether bloom filter contains given hash value.
+ *
+ * \param bloom bloom filter to check inside
+ * \param hash libwapcaplet hash value to look for
+ * \return true hash value is already set in bloom
+ */
+static inline bool css_bloom_has_hash(const css_bloom bloom[CSS_BLOOM_SIZE],
+ lwc_hash hash)
+{
+ unsigned int bit = hash & 0x1f; /* Top 5 bits */
+ unsigned int index = (hash >> 5) & INDEX_BITS_N; /* Next N bits */
+
+ return (bloom[index] & (1 << bit));
+}
+
+
+/**
+ * Test whether bloom 'a' is a subset of bloom 'b'.
+ *
+ * \param a potential subset bloom to test
+ * \param b superset bloom
+ * \return true iff 'a' is subset of 'b'
+ */
+static inline bool css_bloom_in_bloom(const css_bloom a[CSS_BLOOM_SIZE],
+ const css_bloom b[CSS_BLOOM_SIZE])
+{
+ if ((a[0] & b[0]) != a[0])
+ return false;
+ if ((a[1] & b[1]) != a[1])
+ return false;
+ if ((a[2] & b[2]) != a[2])
+ return false;
+ if ((a[3] & b[3]) != a[3])
+ return false;
+#if (CSS_BLOOM_SIZE > 4)
+ if ((a[4] & b[4]) != a[4])
+ return false;
+ if ((a[5] & b[5]) != a[5])
+ return false;
+ if ((a[6] & b[6]) != a[6])
+ return false;
+ if ((a[7] & b[7]) != a[7])
+ return false;
+#endif
+#if (CSS_BLOOM_SIZE > 8)
+ if ((a[8] & b[8]) != a[8])
+ return false;
+ if ((a[9] & b[9]) != a[9])
+ return false;
+ if ((a[10] & b[10]) != a[10])
+ return false;
+ if ((a[11] & b[11]) != a[11])
+ return false;
+ if ((a[12] & b[12]) != a[12])
+ return false;
+ if ((a[13] & b[13]) != a[13])
+ return false;
+ if ((a[14] & b[14]) != a[14])
+ return false;
+ if ((a[15] & b[15]) != a[15])
+ return false;
+#endif
+ return true;
+}
+
+
+/**
+ * Merge bloom 'a' into bloom 'b'.
+ *
+ * \param a bloom to insert
+ * \param b target bloom
+ */
+static inline void css_bloom_merge(const css_bloom a[CSS_BLOOM_SIZE],
+ css_bloom b[CSS_BLOOM_SIZE])
+{
+ b[0] |= a[0];
+ b[1] |= a[1];
+ b[2] |= a[2];
+ b[3] |= a[3];
+#if (CSS_BLOOM_SIZE > 4)
+ b[4] |= a[4];
+ b[5] |= a[5];
+ b[6] |= a[6];
+ b[7] |= a[7];
+#endif
+#if (CSS_BLOOM_SIZE > 8)
+ b[8] |= a[8];
+ b[9] |= a[9];
+ b[10] |= a[10];
+ b[11] |= a[11];
+ b[12] |= a[12];
+ b[13] |= a[13];
+ b[14] |= a[14];
+ b[15] |= a[15];
+#endif
+}
+
+
+/**
+ * Initialise a bloom filter to 0
+ *
+ * \param bloom bloom filter to initialise
+ */
+static inline void css_bloom_init(css_bloom bloom[CSS_BLOOM_SIZE])
+{
+ bloom[0] = 0;
+ bloom[1] = 0;
+ bloom[2] = 0;
+ bloom[3] = 0;
+#if (CSS_BLOOM_SIZE > 4)
+ bloom[4] = 0;
+ bloom[5] = 0;
+ bloom[6] = 0;
+ bloom[7] = 0;
+#endif
+#if (CSS_BLOOM_SIZE > 8)
+ bloom[8] = 0;
+ bloom[9] = 0;
+ bloom[10] = 0;
+ bloom[11] = 0;
+ bloom[12] = 0;
+ bloom[13] = 0;
+ bloom[14] = 0;
+ bloom[15] = 0;
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/select/computed.c b/src/select/computed.c
index 059c76f..682fe05 100644
--- a/src/select/computed.c
+++ b/src/select/computed.c
@@ -77,30 +77,24 @@ static css_error compute_absolute_length_pair(css_computed_style *style,
/**
* Create a computed style
*
- * \param alloc Memory (de)allocation function
- * \param pw Pointer to client-specific data
* \param result Pointer to location to receive result
* \return CSS_OK on success,
* CSS_NOMEM on memory exhaustion,
* CSS_BADPARM on bad parameters.
*/
-css_error css_computed_style_create(css_allocator_fn alloc, void *pw,
- css_computed_style **result)
+css_error css_computed_style_create(css_computed_style **result)
{
css_computed_style *s;
- if (alloc == NULL || result == NULL)
+ if (result == NULL)
return CSS_BADPARM;
- s = alloc(NULL, sizeof(css_computed_style), pw);
+ s = malloc(sizeof(css_computed_style));
if (s == NULL)
return CSS_NOMEM;
memset(s, 0, sizeof(css_computed_style));
- s->alloc = alloc;
- s->pw = pw;
-
*result = s;
return CSS_OK;
@@ -126,8 +120,7 @@ css_error css_computed_style_destroy(css_computed_style *style)
lwc_string_unref(c->name);
}
- style->alloc(style->uncommon->counter_increment, 0,
- style->pw);
+ free(style->uncommon->counter_increment);
}
if (style->uncommon->counter_reset != NULL) {
@@ -138,8 +131,7 @@ css_error css_computed_style_destroy(css_computed_style *style)
lwc_string_unref(c->name);
}
- style->alloc(style->uncommon->counter_reset, 0,
- style->pw);
+ free(style->uncommon->counter_reset);
}
if (style->uncommon->cursor != NULL) {
@@ -149,7 +141,7 @@ css_error css_computed_style_destroy(css_computed_style *style)
lwc_string_unref(*s);
}
- style->alloc(style->uncommon->cursor, 0, style->pw);
+ free(style->uncommon->cursor);
}
if (style->uncommon->content != NULL) {
@@ -180,18 +172,18 @@ css_error css_computed_style_destroy(css_computed_style *style)
}
}
- style->alloc(style->uncommon->content, 0, style->pw);
+ free(style->uncommon->content);
}
- style->alloc(style->uncommon, 0, style->pw);
+ free(style->uncommon);
}
if (style->page != NULL) {
- style->alloc(style->page, 0, style->pw);
+ free(style->page);
}
if (style->aural != NULL) {
- style->alloc(style->aural, 0, style->pw);
+ free(style->aural);
}
if (style->font_family != NULL) {
@@ -201,7 +193,7 @@ css_error css_computed_style_destroy(css_computed_style *style)
lwc_string_unref(*s);
}
- style->alloc(style->font_family, 0, style->pw);
+ free(style->font_family);
}
if (style->quotes != NULL) {
@@ -211,7 +203,7 @@ css_error css_computed_style_destroy(css_computed_style *style)
lwc_string_unref(*s);
}
- style->alloc(style->quotes, 0, style->pw);
+ free(style->quotes);
}
if (style->list_style_image != NULL)
@@ -220,7 +212,7 @@ css_error css_computed_style_destroy(css_computed_style *style)
if (style->background_image != NULL)
lwc_string_unref(style->background_image);
- style->alloc(style, 0, style->pw);
+ free(style);
return CSS_OK;
}
diff --git a/src/select/computed.h b/src/select/computed.h
index 8be3873..1f2cded 100644
--- a/src/select/computed.h
+++ b/src/select/computed.h
@@ -285,9 +285,6 @@ struct css_computed_style {
css_computed_uncommon *uncommon;/**< Uncommon properties */
void *aural; /**< Aural properties */
css_computed_page *page; /**< Page properties */
-
- css_allocator_fn alloc;
- void *pw;
};
css_error css__compute_absolute_values(const css_computed_style *parent,
diff --git a/src/select/font_face.c b/src/select/font_face.c
index cd6556a..ea790eb 100644
--- a/src/select/font_face.c
+++ b/src/select/font_face.c
@@ -21,7 +21,7 @@ static void font_faces_srcs_destroy(css_font_face *font_face)
}
}
- font_face->alloc(srcs, 0, font_face->pw);
+ free(srcs);
font_face->srcs = NULL;
}
@@ -29,38 +29,30 @@ static const css_font_face default_font_face = {
NULL,
NULL,
0,
- { (CSS_FONT_WEIGHT_NORMAL << 2) | CSS_FONT_STYLE_NORMAL },
- NULL,
- NULL
+ { (CSS_FONT_WEIGHT_NORMAL << 2) | CSS_FONT_STYLE_NORMAL }
};
/**
* Create a font-face
*
- * \param alloc Memory (de)allocation function
- * \param pw Pointer to client-specific data
* \param result Pointer to location to receive result
* \return CSS_OK on success,
* CSS_NOMEM on memory exhaustion,
* CSS_BADPARM on bad parameters.
*/
-css_error css__font_face_create(css_allocator_fn alloc, void *pw,
- css_font_face **result)
+css_error css__font_face_create(css_font_face **result)
{
css_font_face *f;
- if (alloc == NULL || result == NULL)
+ if (result == NULL)
return CSS_BADPARM;
- f = alloc(NULL, sizeof(css_font_face), pw);
+ f = malloc(sizeof(css_font_face));
if (f == NULL)
return CSS_NOMEM;
memcpy(f, &default_font_face, sizeof(css_font_face));
- f->alloc = alloc;
- f->pw = pw;
-
*result = f;
return CSS_OK;
@@ -83,7 +75,7 @@ css_error css__font_face_destroy(css_font_face *font_face)
if (font_face->srcs != NULL)
font_faces_srcs_destroy(font_face);
- font_face->alloc(font_face, 0, font_face->pw);
+ free(font_face);
return CSS_OK;
}
diff --git a/src/select/font_face.h b/src/select/font_face.h
index 3572de8..4e6d094 100644
--- a/src/select/font_face.h
+++ b/src/select/font_face.h
@@ -35,13 +35,9 @@ struct css_font_face {
* 1 __wwwwss font-weight | font-style
*/
uint8_t bits[1];
-
- css_allocator_fn alloc;
- void *pw;
};
-css_error css__font_face_create(css_allocator_fn alloc, void *pw,
- css_font_face **result);
+css_error css__font_face_create(css_font_face **result);
css_error css__font_face_destroy(css_font_face *font_face);
css_error css__font_face_set_font_family(css_font_face *font_face,
diff --git a/src/select/hash.c b/src/select/hash.c
index 79c324b..249aeb6 100644
--- a/src/select/hash.c
+++ b/src/select/hash.c
@@ -37,9 +37,6 @@ struct css_selector_hash {
hash_entry universal;
size_t hash_size;
-
- css_allocator_fn alloc;
- void *pw;
};
static hash_entry empty_slot;
@@ -143,48 +140,45 @@ static inline bool _rule_good_for_media(const css_rule *rule, uint64_t media)
/**
* Create a hash
*
- * \param alloc Memory (de)allocation function
- * \param pw Pointer to client-specific private data
* \param hash Pointer to location to receive result
* \return CSS_OK on success, appropriate error otherwise
*/
-css_error css__selector_hash_create(css_allocator_fn alloc, void *pw,
- css_selector_hash **hash)
+css_error css__selector_hash_create(css_selector_hash **hash)
{
css_selector_hash *h;
- if (alloc == NULL || hash == NULL)
+ if (hash == NULL)
return CSS_BADPARM;
- h = alloc(0, sizeof(css_selector_hash), pw);
+ h = malloc(sizeof(css_selector_hash));
if (h == NULL)
return CSS_NOMEM;
/* Element hash */
- h->elements.slots = alloc(0, DEFAULT_SLOTS * sizeof(hash_entry), pw);
+ h->elements.slots = malloc(DEFAULT_SLOTS * sizeof(hash_entry));
if (h->elements.slots == NULL) {
- alloc(h, 0, pw);
+ free(h);
return CSS_NOMEM;
}
memset(h->elements.slots, 0, DEFAULT_SLOTS * sizeof(hash_entry));
h->elements.n_slots = DEFAULT_SLOTS;
/* Class hash */
- h->classes.slots = alloc(0, DEFAULT_SLOTS * sizeof(hash_entry), pw);
+ h->classes.slots = malloc(DEFAULT_SLOTS * sizeof(hash_entry));
if (h->classes.slots == NULL) {
- alloc(h->elements.slots, 0, pw);
- alloc(h, 0, pw);
+ free(h->elements.slots);
+ free(h);
return CSS_NOMEM;
}
memset(h->classes.slots, 0, DEFAULT_SLOTS * sizeof(hash_entry));
h->classes.n_slots = DEFAULT_SLOTS;
/* ID hash */
- h->ids.slots = alloc(0, DEFAULT_SLOTS * sizeof(hash_entry), pw);
+ h->ids.slots = malloc(DEFAULT_SLOTS * sizeof(hash_entry));
if (h->ids.slots == NULL) {
- alloc(h->classes.slots, 0, pw);
- alloc(h->elements.slots, 0, pw);
- alloc(h, 0, pw);
+ free(h->classes.slots);
+ free(h->elements.slots);
+ free(h);
return CSS_NOMEM;
}
memset(h->ids.slots, 0, DEFAULT_SLOTS * sizeof(hash_entry));
@@ -198,9 +192,6 @@ css_error css__selector_hash_create(css_allocator_fn alloc, void *pw,
DEFAULT_SLOTS * sizeof(hash_entry) +
DEFAULT_SLOTS * sizeof(hash_entry);
- h->alloc = alloc;
- h->pw = pw;
-
*hash = h;
return CSS_OK;
@@ -225,39 +216,39 @@ css_error css__selector_hash_destroy(css_selector_hash *hash)
for (d = hash->elements.slots[i].next; d != NULL; d = e) {
e = d->next;
- hash->alloc(d, 0, hash->pw);
+ free(d);
}
}
- hash->alloc(hash->elements.slots, 0, hash->pw);
+ free(hash->elements.slots);
/* Class hash */
for (i = 0; i < hash->classes.n_slots; i++) {
for (d = hash->classes.slots[i].next; d != NULL; d = e) {
e = d->next;
- hash->alloc(d, 0, hash->pw);
+ free(d);
}
}
- hash->alloc(hash->classes.slots, 0, hash->pw);
+ free(hash->classes.slots);
/* ID hash */
for (i = 0; i < hash->ids.n_slots; i++) {
for (d = hash->ids.slots[i].next; d != NULL; d = e) {
e = d->next;
- hash->alloc(d, 0, hash->pw);
+ free(d);
}
}
- hash->alloc(hash->ids.slots, 0, hash->pw);
+ free(hash->ids.slots);
/* Universal chain */
for (d = hash->universal.next; d != NULL; d = e) {
e = d->next;
- hash->alloc(d, 0, hash->pw);
+ free(d);
}
- hash->alloc(hash, 0, hash->pw);
+ free(hash);
return CSS_OK;
}
@@ -837,8 +828,7 @@ css_error _insert_into_chain(css_selector_hash *ctx, hash_entry *head,
} else {
hash_entry *search = head;
hash_entry *prev = NULL;
- hash_entry *entry =
- ctx->alloc(NULL, sizeof(hash_entry), ctx->pw);
+ hash_entry *entry = malloc(sizeof(hash_entry));
if (entry == NULL)
return CSS_NOMEM;
@@ -920,7 +910,7 @@ css_error _remove_from_chain(css_selector_hash *ctx, hash_entry *head,
} else {
prev->next = search->next;
- ctx->alloc(search, 0, ctx->pw);
+ free(search);
ctx->hash_size -= sizeof(hash_entry);
}
diff --git a/src/select/hash.h b/src/select/hash.h
index f572048..71f610f 100644
--- a/src/select/hash.h
+++ b/src/select/hash.h
@@ -10,10 +10,11 @@
#include <libwapcaplet/libwapcaplet.h>
-#include <libcss/bloom.h>
#include <libcss/errors.h>
#include <libcss/functypes.h>
+#include "select/bloom.h"
+
/* Ugh. We need this to avoid circular includes. Happy! */
struct css_selector;
@@ -33,8 +34,7 @@ typedef css_error (*css_selector_hash_iterator)(
const struct css_selector **current,
const struct css_selector ***next);
-css_error css__selector_hash_create(css_allocator_fn alloc, void *pw,
- css_selector_hash **hash);
+css_error css__selector_hash_create(css_selector_hash **hash);
css_error css__selector_hash_destroy(css_selector_hash *hash);
css_error css__selector_hash_insert(css_selector_hash *hash,
diff --git a/src/select/properties/content.c b/src/select/properties/content.c
index 1d033f2..c79dd0d 100644
--- a/src/select/properties/content.c
+++ b/src/select/properties/content.c
@@ -35,16 +35,15 @@ css_error css__cascade_content(uint32_t opv, css_style *style,
lwc_string *he;
css_computed_content_item *temp;
- css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &he);
+ css__stylesheet_string_get(style->sheet,
+ *((css_code_t *) style->bytecode), &he);
- temp = state->computed->alloc(content,
+ temp = realloc(content,
(n_contents + 1) *
- sizeof(css_computed_content_item),
- state->computed->pw);
+ sizeof(css_computed_content_item));
if (temp == NULL) {
if (content != NULL) {
- state->computed->alloc(content,
- 0, state->computed->pw);
+ free(content);
}
return CSS_NOMEM;
}
@@ -127,11 +126,10 @@ css_error css__cascade_content(uint32_t opv, css_style *style,
if (n_contents > 0) {
css_computed_content_item *temp;
- temp = state->computed->alloc(content,
- (n_contents + 1) * sizeof(css_computed_content_item),
- state->computed->pw);
+ temp = realloc(content, (n_contents + 1) *
+ sizeof(css_computed_content_item));
if (temp == NULL) {
- state->computed->alloc(content, 0, state->computed->pw);
+ free(content);
return CSS_NOMEM;
}
@@ -146,11 +144,11 @@ css_error css__cascade_content(uint32_t opv, css_style *style,
error = set_content(state->computed, value, content);
if (error != CSS_OK && content != NULL)
- state->computed->alloc(content, 0, state->computed->pw);
+ free(content);
return error;
} else if (content != NULL) {
- state->computed->alloc(content, 0, state->computed->pw);
+ free(content);
}
return CSS_OK;
@@ -190,7 +188,7 @@ css_error css__set_content_from_hint(const css_hint *hint,
}
if (error != CSS_OK && hint->data.content != NULL)
- style->alloc(hint->data.content, 0, style->pw);
+ free(hint->data.content);
return error;
}
@@ -226,9 +224,8 @@ css_error css__compose_content(const css_computed_style *parent,
i++)
n_items++;
- copy = result->alloc(NULL, (n_items + 1) *
- sizeof(css_computed_content_item),
- result->pw);
+ copy = malloc((n_items + 1) *
+ sizeof(css_computed_content_item));
if (copy == NULL)
return CSS_NOMEM;
@@ -238,7 +235,7 @@ css_error css__compose_content(const css_computed_style *parent,
error = set_content(result, type, copy);
if (error != CSS_OK && copy != NULL)
- result->alloc(copy, 0, result->pw);
+ free(copy);
return error;
}
diff --git a/src/select/properties/counter_increment.c b/src/select/properties/counter_increment.c
index 26419a2..429e558 100644
--- a/src/select/properties/counter_increment.c
+++ b/src/select/properties/counter_increment.c
@@ -37,7 +37,7 @@ css_error css__set_counter_increment_from_hint(const css_hint *hint,
}
if (error != CSS_OK && hint->data.counter != NULL)
- style->alloc(hint->data.counter, 0, style->pw);
+ free(hint->data.counter);
return error;
}
@@ -73,9 +73,8 @@ css_error css__compose_counter_increment(const css_computed_style *parent,
for (i = items; i->name != NULL; i++)
n_items++;
- copy = result->alloc(NULL, (n_items + 1) *
- sizeof(css_computed_counter),
- result->pw);
+ copy = malloc((n_items + 1) *
+ sizeof(css_computed_counter));
if (copy == NULL)
return CSS_NOMEM;
@@ -85,7 +84,7 @@ css_error css__compose_counter_increment(const css_computed_style *parent,
error = set_counter_increment(result, type, copy);
if (error != CSS_OK && copy != NULL)
- result->alloc(copy, 0, result->pw);
+ free(copy);
return error;
}
diff --git a/src/select/properties/counter_reset.c b/src/select/properties/counter_reset.c
index 362c86d..ddf54aa 100644
--- a/src/select/properties/counter_reset.c
+++ b/src/select/properties/counter_reset.c
@@ -37,7 +37,7 @@ css_error css__set_counter_reset_from_hint(const css_hint *hint,
}
if (error != CSS_OK && hint->data.counter != NULL)
- style->alloc(hint->data.counter, 0, style->pw);
+ free(hint->data.counter);
return error;
}
@@ -72,9 +72,8 @@ css_error css__compose_counter_reset(const css_computed_style *parent,
for (i = items; i->name != NULL; i++)
n_items++;
- copy = result->alloc(NULL, (n_items + 1) *
- sizeof(css_computed_counter),
- result->pw);
+ copy = malloc((n_items + 1) *
+ sizeof(css_computed_counter));
if (copy == NULL)
return CSS_NOMEM;
@@ -84,7 +83,7 @@ css_error css__compose_counter_reset(const css_computed_style *parent,
error = set_counter_reset(result, type, copy);
if (error != CSS_OK && copy != NULL)
- result->alloc(copy, 0, result->pw);
+ free(copy);
return error;
}
diff --git a/src/select/properties/cursor.c b/src/select/properties/cursor.c
index d4785b1..a77d21b 100644
--- a/src/select/properties/cursor.c
+++ b/src/select/properties/cursor.c
@@ -28,16 +28,16 @@ css_error css__cascade_cursor(uint32_t opv, css_style *style,
lwc_string *uri;
lwc_string **temp;
- css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &uri);
+ css__stylesheet_string_get(style->sheet,
+ *((css_code_t *) style->bytecode),
+ &uri);
advance_bytecode(style, sizeof(css_code_t));
- temp = state->computed->alloc(uris,
- (n_uris + 1) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(uris,
+ (n_uris + 1) * sizeof(lwc_string *));
if (temp == NULL) {
if (uris != NULL) {
- state->computed->alloc(uris, 0,
- state->computed->pw);
+ free(uris);
}
return CSS_NOMEM;
}
@@ -111,11 +111,10 @@ css_error css__cascade_cursor(uint32_t opv, css_style *style,
if (n_uris > 0) {
lwc_string **temp;
- temp = state->computed->alloc(uris,
- (n_uris + 1) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(uris,
+ (n_uris + 1) * sizeof(lwc_string *));
if (temp == NULL) {
- state->computed->alloc(uris, 0, state->computed->pw);
+ free(uris);
return CSS_NOMEM;
}
@@ -130,12 +129,12 @@ css_error css__cascade_cursor(uint32_t opv, css_style *style,
error = set_cursor(state->computed, value, uris);
if (error != CSS_OK && n_uris > 0)
- state->computed->alloc(uris, 0, state->computed->pw);
+ free(uris);
return error;
} else {
if (n_uris > 0)
- state->computed->alloc(uris, 0, state->computed->pw);
+ free(uris);
}
return CSS_OK;
@@ -155,7 +154,7 @@ css_error css__set_cursor_from_hint(const css_hint *hint,
}
if (error != CSS_OK && hint->data.strings != NULL)
- style->alloc(hint->data.strings, 0, style->pw);
+ free(hint->data.strings);
return error;
}
@@ -190,9 +189,8 @@ css_error css__compose_cursor(const css_computed_style *parent,
for (i = urls; (*i) != NULL; i++)
n_urls++;
- copy = result->alloc(NULL, (n_urls + 1) *
- sizeof(lwc_string *),
- result->pw);
+ copy = malloc((n_urls + 1) *
+ sizeof(lwc_string *));
if (copy == NULL)
return CSS_NOMEM;
@@ -202,7 +200,7 @@ css_error css__compose_cursor(const css_computed_style *parent,
error = set_cursor(result, type, copy);
if (error != CSS_OK && copy != NULL)
- result->alloc(copy, 0, result->pw);
+ free(copy);
return error;
}
diff --git a/src/select/properties/font_family.c b/src/select/properties/font_family.c
index 44860f9..514a43a 100644
--- a/src/select/properties/font_family.c
+++ b/src/select/properties/font_family.c
@@ -63,13 +63,11 @@ css_error css__cascade_font_family(uint32_t opv, css_style *style,
* first generic-family are ignored. */
/** \todo Do this at bytecode generation time? */
if (value == CSS_FONT_FAMILY_INHERIT && font != NULL) {
- temp = state->computed->alloc(fonts,
- (n_fonts + 1) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(fonts,
+ (n_fonts + 1) * sizeof(lwc_string *));
if (temp == NULL) {
if (fonts != NULL) {
- state->computed->alloc(fonts, 0,
- state->computed->pw);
+ free(fonts);
}
return CSS_NOMEM;
}
@@ -90,11 +88,9 @@ css_error css__cascade_font_family(uint32_t opv, css_style *style,
if (n_fonts > 0) {
lwc_string **temp;
- temp = state->computed->alloc(fonts,
- (n_fonts + 1) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(fonts, (n_fonts + 1) * sizeof(lwc_string *));
if (temp == NULL) {
- state->computed->alloc(fonts, 0, state->computed->pw);
+ free(fonts);
return CSS_NOMEM;
}
@@ -126,9 +122,7 @@ css_error css__cascade_font_family(uint32_t opv, css_style *style,
}
if (hint.data.strings != NULL) {
- state->computed->alloc(
- hint.data.strings,
- 0, state->computed->pw);
+ free(hint.data.strings);
}
}
@@ -145,12 +139,12 @@ css_error css__cascade_font_family(uint32_t opv, css_style *style,
error = set_font_family(state->computed, value, fonts);
if (error != CSS_OK && n_fonts > 0)
- state->computed->alloc(fonts, 0, state->computed->pw);
+ free(fonts);
return error;
} else {
if (n_fonts > 0)
- state->computed->alloc(fonts, 0, state->computed->pw);
+ free(fonts);
}
return CSS_OK;
@@ -170,7 +164,7 @@ css_error css__set_font_family_from_hint(const css_hint *hint,
}
if (error != CSS_OK && hint->data.strings != NULL)
- style->alloc(hint->data.strings, 0, style->pw);
+ free(hint->data.strings);
return error;
}
@@ -209,9 +203,7 @@ css_error css__compose_font_family(const css_computed_style *parent,
for (i = names; (*i) != NULL; i++)
n_names++;
- copy = result->alloc(NULL, (n_names + 1) *
- sizeof(lwc_string *),
- result->pw);
+ copy = malloc((n_names + 1) * sizeof(lwc_string *));
if (copy == NULL)
return CSS_NOMEM;
@@ -221,7 +213,7 @@ css_error css__compose_font_family(const css_computed_style *parent,
error = set_font_family(result, type, copy);
if (error != CSS_OK && copy != NULL)
- result->alloc(copy, 0, result->pw);
+ free(copy);
return error;
}
diff --git a/src/select/properties/helpers.c b/src/select/properties/helpers.c
index 28ecdcc..df076db 100644
--- a/src/select/properties/helpers.c
+++ b/src/select/properties/helpers.c
@@ -421,14 +421,12 @@ css_error css__cascade_counter_increment_reset(uint32_t opv, css_style *style,
val = *((css_fixed *) style->bytecode);
advance_bytecode(style, sizeof(css_code_t));
- temp = state->computed->alloc(counters,
+ temp = realloc(counters,
(n_counters + 1) *
- sizeof(css_computed_counter),
- state->computed->pw);
+ sizeof(css_computed_counter));
if (temp == NULL) {
if (counters != NULL) {
- state->computed->alloc(counters,
- 0, state->computed->pw);
+ free(counters);
}
return CSS_NOMEM;
}
@@ -455,11 +453,10 @@ css_error css__cascade_counter_increment_reset(uint32_t opv, css_style *style,
if (n_counters > 0) {
css_computed_counter *temp;
- temp = state->computed->alloc(counters,
- (n_counters + 1) * sizeof(css_computed_counter),
- state->computed->pw);
+ temp = realloc(counters, (n_counters + 1) *
+ sizeof(css_computed_counter));
if (temp == NULL) {
- state->computed->alloc(counters, 0, state->computed->pw);
+ free(counters);
return CSS_NOMEM;
}
@@ -475,11 +472,11 @@ css_error css__cascade_counter_increment_reset(uint32_t opv, css_style *style,
error = fun(state->computed, value, counters);
if (error != CSS_OK && n_counters > 0)
- state->computed->alloc(counters, 0, state->computed->pw);
+ free(counters);
return error;
} else if (n_counters > 0) {
- state->computed->alloc(counters, 0, state->computed->pw);
+ free(counters);
}
return CSS_OK;
diff --git a/src/select/properties/quotes.c b/src/select/properties/quotes.c
index 7671c1d..2dd6af4 100644
--- a/src/select/properties/quotes.c
+++ b/src/select/properties/quotes.c
@@ -30,19 +30,21 @@ css_error css__cascade_quotes(uint32_t opv, css_style *style,
lwc_string *open, *close;
lwc_string **temp;
- css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &open);
+ css__stylesheet_string_get(style->sheet,
+ *((css_code_t *) style->bytecode),
+ &open);
advance_bytecode(style, sizeof(css_code_t));
- css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &close);
+ css__stylesheet_string_get(style->sheet,
+ *((css_code_t *) style->bytecode),
+ &close);
advance_bytecode(style, sizeof(css_code_t));
- temp = state->computed->alloc(quotes,
- (n_quotes + 2) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(quotes,
+ (n_quotes + 2) * sizeof(lwc_string *));
if (temp == NULL) {
if (quotes != NULL) {
- state->computed->alloc(quotes, 0,
- state->computed->pw);
+ free(quotes);
}
return CSS_NOMEM;
}
@@ -61,11 +63,9 @@ css_error css__cascade_quotes(uint32_t opv, css_style *style,
if (n_quotes > 0) {
lwc_string **temp;
- temp = state->computed->alloc(quotes,
- (n_quotes + 1) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(quotes, (n_quotes + 1) * sizeof(lwc_string *));
if (temp == NULL) {
- state->computed->alloc(quotes, 0, state->computed->pw);
+ free(quotes);
return CSS_NOMEM;
}
@@ -80,12 +80,12 @@ css_error css__cascade_quotes(uint32_t opv, css_style *style,
error = set_quotes(state->computed, value, quotes);
if (error != CSS_OK && quotes != NULL)
- state->computed->alloc(quotes, 0, state->computed->pw);
+ free(quotes);
return error;
} else {
if (quotes != NULL)
- state->computed->alloc(quotes, 0, state->computed->pw);
+ free(quotes);
}
return CSS_OK;
@@ -105,7 +105,7 @@ css_error css__set_quotes_from_hint(const css_hint *hint,
}
if (error != CSS_OK && hint->data.strings != NULL)
- style->alloc(hint->data.strings, 0, style->pw);
+ free(hint->data.strings);
return error;
}
@@ -145,9 +145,7 @@ css_error css__compose_quotes(const css_computed_style *parent,
for (i = quotes; (*i) != NULL; i++)
n_quotes++;
- copy = result->alloc(NULL, (n_quotes + 1) *
- sizeof(lwc_string *),
- result->pw);
+ copy = malloc((n_quotes + 1) * sizeof(lwc_string *));
if (copy == NULL)
return CSS_NOMEM;
@@ -157,7 +155,7 @@ css_error css__compose_quotes(const css_computed_style *parent,
error = set_quotes(result, type, copy);
if (error != CSS_OK && copy != NULL)
- result->alloc(copy, 0, result->pw);
+ free(copy);
return error;
}
diff --git a/src/select/properties/voice_family.c b/src/select/properties/voice_family.c
index e61d2c6..5c70d1e 100644
--- a/src/select/properties/voice_family.c
+++ b/src/select/properties/voice_family.c
@@ -31,7 +31,9 @@ css_error css__cascade_voice_family(uint32_t opv, css_style *style,
switch (v) {
case VOICE_FAMILY_STRING:
case VOICE_FAMILY_IDENT_LIST:
- css__stylesheet_string_get(style->sheet, *((css_code_t *) style->bytecode), &voice);
+ css__stylesheet_string_get(style->sheet,
+ *((css_code_t *) style->bytecode),
+ &voice);
advance_bytecode(style, sizeof(css_code_t));
break;
case VOICE_FAMILY_MALE:
@@ -53,13 +55,11 @@ css_error css__cascade_voice_family(uint32_t opv, css_style *style,
* first generic-family are ignored. */
/** \todo Do this at bytecode generation time? */
if (value == 0 && voice != NULL) {
- temp = state->computed->alloc(voices,
- (n_voices + 1) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(voices,
+ (n_voices + 1) * sizeof(lwc_string *));
if (temp == NULL) {
if (voices != NULL) {
- state->computed->alloc(voices, 0,
- state->computed->pw);
+ free(voices);
}
return CSS_NOMEM;
}
@@ -80,11 +80,9 @@ css_error css__cascade_voice_family(uint32_t opv, css_style *style,
if (n_voices > 0) {
lwc_string **temp;
- temp = state->computed->alloc(voices,
- (n_voices + 1) * sizeof(lwc_string *),
- state->computed->pw);
+ temp = realloc(voices, (n_voices + 1) * sizeof(lwc_string *));
if (temp == NULL) {
- state->computed->alloc(voices, 0, state->computed->pw);
+ free(voices);
return CSS_NOMEM;
}
@@ -97,10 +95,10 @@ css_error css__cascade_voice_family(uint32_t opv, css_style *style,
isInherit(opv))) {
/** \todo voice-family */
if (n_voices > 0)
- state->computed->alloc(voices, 0, state->computed->pw);
+ free(voices);
} else {
if (n_voices > 0)
- state->computed->alloc(voices, 0, state->computed->pw);
+ free(voices);
}
return CSS_OK;
diff --git a/src/select/propset.h b/src/select/propset.h
index ddd5642..5af7e8b 100644
--- a/src/select/propset.h
+++ b/src/select/propset.h
@@ -41,8 +41,7 @@ static const css_computed_uncommon default_uncommon = {
#define ENSURE_UNCOMMON do { \
if (style->uncommon == NULL) { \
- style->uncommon = style->alloc(NULL, \
- sizeof(css_computed_uncommon), style->pw); \
+ style->uncommon = malloc(sizeof(css_computed_uncommon));\
if (style->uncommon == NULL) \
return CSS_NOMEM; \
\
@@ -65,8 +64,7 @@ static const css_computed_page default_page = {
#define ENSURE_PAGE do { \
if (style->page == NULL) { \
- style->page = style->alloc(NULL, \
- sizeof(css_computed_page), style->pw); \
+ style->page = malloc(sizeof(css_computed_page)); \
if (style->page == NULL) \
return CSS_NOMEM; \
\
@@ -264,7 +262,7 @@ static inline css_error set_counter_increment(
lwc_string_unref(c->name);
if (oldcounters != counters)
- style->alloc(oldcounters, 0, style->pw);
+ free(oldcounters);
}
return CSS_OK;
@@ -304,7 +302,7 @@ static inline css_error set_counter_reset(
lwc_string_unref(c->name);
if (oldcounters != counters)
- style->alloc(oldcounters, 0, style->pw);
+ free(oldcounters);
}
return CSS_OK;
@@ -344,7 +342,7 @@ static inline css_error set_cursor(
lwc_string_unref(*s);
if (oldurls != urls)
- style->alloc(oldurls, 0, style->pw);
+ free(oldurls);
}
return CSS_OK;
@@ -482,7 +480,7 @@ static inline css_error set_content(
}
if (oldcontent != content)
- style->alloc(oldcontent, 0, style->pw);
+ free(oldcontent);
}
return CSS_OK;
@@ -717,7 +715,7 @@ static inline css_error set_quotes(
lwc_string_unref(*s);
if (oldquotes != quotes)
- style->alloc(oldquotes, 0, style->pw);
+ free(oldquotes);
}
return CSS_OK;
@@ -1641,7 +1639,7 @@ static inline css_error set_font_family(
lwc_string_unref(*s);
if (oldnames != names)
- style->alloc(oldnames, 0, style->pw);
+ free(oldnames);
}
return CSS_OK;
diff --git a/src/select/select.c b/src/select/select.c
index c8567f8..06ed2bf 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -44,8 +44,7 @@ struct css_select_ctx {
css_select_sheet *sheets; /**< Array of sheets */
- css_allocator_fn alloc; /**< Allocation routine */
- void *pw; /**< Client-specific private data */
+ void *pw; /**< Client's private selection context */
/* Useful interned strings */
lwc_string *universal;
@@ -141,7 +140,7 @@ static css_error match_detail(css_select_ctx *ctx, void *node,
bool *match, css_pseudo_element *pseudo_element);
static css_error cascade_style(const css_style *style, css_select_state *state);
-static css_error select_font_faces_from_sheet(css_select_ctx *ctx,
+static css_error select_font_faces_from_sheet(
const css_stylesheet *sheet,
css_origin origin,
css_select_font_faces_state *state);
@@ -151,24 +150,87 @@ static void dump_chain(const css_selector *selector);
#endif
+/* 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;
+ css_error error;
+ unsigned int i;
+
+ if (handler == NULL || libcss_node_data == NULL ||
+ handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) {
+ return CSS_BADPARM;
+ }
+
+ switch (action) {
+ case CSS_NODE_DELETED:
+ free(bloom);
+ break;
+
+ case CSS_NODE_MODIFIED:
+ case CSS_NODE_ANCESTORS_MODIFIED:
+ if (node == NULL) {
+ return CSS_BADPARM;
+ }
+
+ free(bloom);
+
+ /* Don't bother rebuilding bloom here, 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);
+ if (error != CSS_OK) {
+ return error;
+ }
+ 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;
+ }
+ break;
+
+ default:
+ return CSS_BADPARM;
+ }
+
+ return CSS_OK;
+}
+
/**
* Create a selection context
*
- * \param alloc Memory (de)allocation function
- * \param pw Client-specific private data
* \param result Pointer to location to receive created context
* \return CSS_OK on success, appropriate error otherwise.
*/
-css_error css_select_ctx_create(css_allocator_fn alloc, void *pw,
- css_select_ctx **result)
+css_error css_select_ctx_create(css_select_ctx **result)
{
css_select_ctx *c;
css_error error;
- if (alloc == NULL || result == NULL)
+ if (result == NULL)
return CSS_BADPARM;
- c = alloc(NULL, sizeof(css_select_ctx), pw);
+ c = malloc(sizeof(css_select_ctx));
if (c == NULL)
return CSS_NOMEM;
@@ -176,13 +238,10 @@ css_error css_select_ctx_create(css_allocator_fn alloc, void *pw,
error = intern_strings(c);
if (error != CSS_OK) {
- alloc(c, 0, pw);
+ free(c);
return error;
}
- c->alloc = alloc;
- c->pw = pw;
-
*result = c;
return CSS_OK;
@@ -202,9 +261,9 @@ css_error css_select_ctx_destroy(css_select_ctx *ctx)
destroy_strings(ctx);
if (ctx->sheets != NULL)
- ctx->alloc(ctx->sheets, 0, ctx->pw);
+ free(ctx->sheets);
- ctx->alloc(ctx, 0, ctx->pw);
+ free(ctx);
return CSS_OK;
}
@@ -257,9 +316,8 @@ css_error css_select_ctx_insert_sheet(css_select_ctx *ctx,
if (index > ctx->n_sheets)
return CSS_INVALID;
- temp = ctx->alloc(ctx->sheets,
- (ctx->n_sheets + 1) * sizeof(css_select_sheet),
- ctx->pw);
+ temp = realloc(ctx->sheets,
+ (ctx->n_sheets + 1) * sizeof(css_select_sheet));
if (temp == NULL)
return CSS_NOMEM;
@@ -373,7 +431,6 @@ css_error css_select_ctx_get_sheet(css_select_ctx *ctx, uint32_t index,
* update the fully computed style for a node when layout changes.
*/
css_error css_select_style(css_select_ctx *ctx, void *node,
- const css_bloom bloom[CSS_BLOOM_SIZE],
uint64_t media, const css_stylesheet *inline_style,
css_select_handler *handler, void *pw,
css_select_results **result)
@@ -382,10 +439,11 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
css_error error;
css_select_state state;
void *parent = NULL;
+ css_bloom *bloom = NULL;
+ css_bloom *parent_bloom = NULL;
if (ctx == NULL || node == NULL || result == NULL || handler == NULL ||
- handler->handler_version !=
- CSS_SELECT_HANDLER_VERSION_1)
+ handler->handler_version != CSS_SELECT_HANDLER_VERSION_1)
return CSS_BADPARM;
/* Set up the selection state */
@@ -396,31 +454,68 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
state.pw = pw;
state.next_reject = state.reject_cache +
(N_ELEMENTS(state.reject_cache) - 1);
- state.bloom = bloom;
/* Allocate the result set */
- state.results = ctx->alloc(NULL, sizeof(css_select_results), ctx->pw);
+ state.results = malloc(sizeof(css_select_results));
if (state.results == NULL)
return CSS_NOMEM;
- state.results->alloc = ctx->alloc;
- state.results->pw = ctx->pw;
-
for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++)
state.results->styles[i] = NULL;
/* Base element style is guaranteed to exist */
- error = css_computed_style_create(ctx->alloc, ctx->pw,
+ error = css_computed_style_create(
&state.results->styles[CSS_PSEUDO_ELEMENT_NONE]);
if (error != CSS_OK) {
- ctx->alloc(state.results, 0, ctx->pw);
+ free(state.results);
return error;
}
+ /* Create the node's bloom */
+ bloom = calloc(sizeof(css_bloom), CSS_BLOOM_SIZE);
+ if (bloom == NULL) {
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+
error = handler->parent_node(pw, node, &parent);
if (error != CSS_OK)
goto cleanup;
+ /* Get parent node's bloom filter */
+ if (parent != NULL) {
+ /* Get parent bloom filter */
+ error = handler->get_libcss_node_data(pw, parent,
+ (void **) &state.bloom);
+ if (error != CSS_OK)
+ goto cleanup;
+ /* TODO:
+ * If state.bloom == NULL, build and set parent bloom.
+ */
+ }
+
+ if (state.bloom == NULL) {
+ /* Need to create parent bloom */
+ parent_bloom = malloc(sizeof(css_bloom) * CSS_BLOOM_SIZE);
+ if (parent_bloom == NULL) {
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+ if (parent != NULL) {
+ /* Have to make up fully saturated bloom filter */
+ for (i = 0; i < CSS_BLOOM_SIZE; i++) {
+ parent_bloom[i] = ~0;
+ }
+ } else {
+ /* Empty bloom filter */
+ for (i = 0; i < CSS_BLOOM_SIZE; i++) {
+ parent_bloom[i] = 0;
+ }
+ }
+
+ state.bloom = parent_bloom;
+ }
+
/* Get node's name */
error = handler->node_name(pw, node, &state.element);
if (error != CSS_OK)
@@ -432,10 +527,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
goto cleanup;
/* Get node's classes, if any */
- /** \todo Do we really want to force the client to allocate a new array
- * every time we call this? It seems hugely inefficient, given they can
- * cache the data. */
- error = handler->node_classes(pw, node,
+ error = handler->node_classes(pw, node,
&state.classes, &state.n_classes);
if (error != CSS_OK)
goto cleanup;
@@ -550,6 +642,57 @@ css_error css_select_style(css_select_ctx *ctx, void *node,
goto cleanup;
}
+ /* Add node name to bloom */
+ if (state.element.name->insensitive == NULL) {
+ if (lwc__intern_caseless_string(
+ state.element.name) != lwc_error_ok) {
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+ }
+ css_bloom_add_hash(bloom, lwc_string_hash_value(
+ state.element.name->insensitive));
+
+ /* Add id name to bloom */
+ if (state.id != NULL) {
+ if (state.id->insensitive == NULL) {
+ if (lwc__intern_caseless_string(state.id) !=
+ lwc_error_ok) {
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+ }
+ css_bloom_add_hash(bloom, lwc_string_hash_value(
+ state.id->insensitive));
+ }
+
+ /* Add class names to bloom */
+ if (state.classes != NULL) {
+ lwc_string *s;
+ for (i = 0; i < state.n_classes; i++) {
+ s = state.classes[i];
+ if (s->insensitive == NULL) {
+ if (lwc__intern_caseless_string(s) !=
+ lwc_error_ok) {
+ error = CSS_NOMEM;
+ goto cleanup;
+ }
+ }
+ css_bloom_add_hash(bloom, lwc_string_hash_value(
+ s->insensitive));
+ }
+ }
+
+ /* Merge parent bloom into node bloom */
+ css_bloom_merge(state.bloom, bloom);
+
+ /* Set node bloom filter */
+ error = handler->set_libcss_node_data(pw, node, bloom);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ bloom = NULL;
+
*result = state.results;
error = CSS_OK;
@@ -561,11 +704,17 @@ cleanup:
css_select_results_destroy(state.results);
}
+ if (parent_bloom != NULL) {
+ free(parent_bloom);
+ }
+
+ if (bloom != NULL) {
+ free(bloom);
+ }
+
if (state.classes != NULL) {
for (i = 0; i < state.n_classes; i++)
lwc_string_unref(state.classes[i]);
-
- ctx->alloc(state.classes, 0, ctx->pw);
}
if (state.id != NULL)
@@ -596,7 +745,7 @@ css_error css_select_results_destroy(css_select_results *results)
css_computed_style_destroy(results->styles[i]);
}
- results->alloc(results, 0, results->pw);
+ free(results);
return CSS_OK;
}
@@ -634,7 +783,7 @@ css_error css_select_font_faces(css_select_ctx *ctx,
if ((s.media & media) != 0 &&
s.sheet->disabled == false) {
- error = select_font_faces_from_sheet(ctx, s.sheet,
+ error = select_font_faces_from_sheet(s.sheet,
s.origin, &state);
if (error != CSS_OK)
goto cleanup;
@@ -651,22 +800,16 @@ css_error css_select_font_faces(css_select_ctx *ctx,
* the font faces in priority order. */
css_select_font_faces_results *results;
- results = ctx->alloc(NULL,
- sizeof(css_select_font_faces_results),
- ctx->pw);
+ results = malloc(sizeof(css_select_font_faces_results));
if (results == NULL) {
error = CSS_NOMEM;
goto cleanup;
}
- results->alloc = ctx->alloc;
- results->pw = ctx->pw;
-
- results->font_faces = ctx->alloc(NULL,
- n_font_faces * sizeof(css_font_face *),
- ctx->pw);
+ results->font_faces = malloc(
+ n_font_faces * sizeof(css_font_face *));
if (results->font_faces == NULL) {
- ctx->alloc(results, 0, ctx->pw);
+ free(results);
error = CSS_NOMEM;
goto cleanup;
}
@@ -705,13 +848,13 @@ css_error css_select_font_faces(css_select_ctx *ctx,
cleanup:
if (state.ua_font_faces.count != 0)
- ctx->alloc(state.ua_font_faces.font_faces, 0, ctx->pw);
+ free(state.ua_font_faces.font_faces);
if (state.user_font_faces.count != 0)
- ctx->alloc(state.user_font_faces.font_faces, 0, ctx->pw);
+ free(state.user_font_faces.font_faces);
if (state.author_font_faces.count != 0)
- ctx->alloc(state.author_font_faces.font_faces, 0, ctx->pw);
+ free(state.author_font_faces.font_faces);
return error;
}
@@ -731,10 +874,10 @@ css_error css_select_font_faces_results_destroy(
if (results->font_faces != NULL) {
/* Don't destroy the individual css_font_faces, they're owned
by their respective sheets */
- results->alloc(results->font_faces, 0, results->pw);
+ free(results->font_faces);
}
- results->alloc(results, 0, results->pw);
+ free(results);
return CSS_OK;
}
@@ -1136,7 +1279,7 @@ static inline bool _rule_applies_to_media(const css_rule *rule, uint64_t media)
return applies;
}
-static css_error _select_font_face_from_rule(css_select_ctx *ctx,
+static css_error _select_font_face_from_rule(
const css_rule_font_face *rule, css_origin origin,
css_select_font_faces_state *state)
{
@@ -1168,8 +1311,7 @@ static css_error _select_font_face_from_rule(css_select_ctx *ctx,
index = faces->count++;
new_size = faces->count * sizeof(css_font_face *);
- new_faces = ctx->alloc(faces->font_faces,
- new_size, ctx->pw);
+ new_faces = realloc(faces->font_faces, new_size);
if (new_faces == NULL) {
faces->count = 0;
return CSS_NOMEM;
@@ -1183,7 +1325,7 @@ static css_error _select_font_face_from_rule(css_select_ctx *ctx,
return CSS_OK;
}
-static css_error select_font_faces_from_sheet(css_select_ctx *ctx,
+static css_error select_font_faces_from_sheet(
const css_stylesheet *sheet,
css_origin origin,
css_select_font_faces_state *state)
@@ -1223,7 +1365,6 @@ static css_error select_font_faces_from_sheet(css_select_ctx *ctx,
css_error error;
error = _select_font_face_from_rule(
- ctx,
(const css_rule_font_face *) rule,
origin,
state);
@@ -1367,9 +1508,7 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
if (state->classes != NULL && n_classes > 0) {
/* Find hash chains for node classes */
- class_selectors = ctx->alloc(NULL,
- n_classes * sizeof(css_selector **),
- ctx->pw);
+ class_selectors = malloc(n_classes * sizeof(css_selector **));
if (class_selectors == NULL) {
error = CSS_NOMEM;
goto cleanup;
@@ -1455,7 +1594,7 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
error = CSS_OK;
cleanup:
if (class_selectors != NULL)
- ctx->alloc(class_selectors, 0, ctx->pw);
+ free(class_selectors);
return error;
}
@@ -1571,7 +1710,7 @@ css_error match_selector_chain(css_select_ctx *ctx,
/* Ensure that the appropriate computed style exists */
if (state->results->styles[pseudo] == NULL) {
- error = css_computed_style_create(ctx->alloc, ctx->pw,
+ error = css_computed_style_create(
&state->results->styles[pseudo]);
if (error != CSS_OK)
return error;
diff --git a/src/select/select.h b/src/select/select.h
index 43c29d2..fad86ac 100644
--- a/src/select/select.h
+++ b/src/select/select.h
@@ -69,8 +69,8 @@ static inline void advance_bytecode(css_style *style, uint32_t n_bytes)
style->bytecode = style->bytecode + (n_bytes / sizeof(css_code_t));
}
-bool css__outranks_existing(uint16_t op, bool important, css_select_state *state,
- bool inherit);
+bool css__outranks_existing(uint16_t op, bool important,
+ css_select_state *state, bool inherit);
#endif