summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Staudinger <robsta@gnome.org>2009-08-07 13:16:51 +0200
committerRobert Staudinger <robsta@gnome.org>2009-08-07 13:16:51 +0200
commit03780dee6396a96fc3489f433838da998c89c4fe (patch)
tree4d04835f24b8bdfd9b9913ae9b7e36931e8093c8
parent6cdc8e793ddda1fcc629954497c7cb8957e8d9c8 (diff)
[stylesheet] Implement ccss_stylesheet_unload() to unload css parts.
Every selector now stores a descriptor of the CSS file or buffer it originates from. For unloading a file or buffer the internal stylesheet representation is iterated and all selectors and blocks with matching descriptors are destroyed. This also requires an update to ccss_node_get_style(), the descriptor for the inline style is passed to the callback, which the consumer must store in order to unload the inline style later on. The above change in turn obsoletes ccss_stylesheet_invalidate_node() since all unloading now uses a consistent API. Also fix a related memory leak, selectors and -groups would be left over when destroying a stylesheet.
-rw-r--r--ccss-doc/ccss-sections.txt3
-rw-r--r--ccss-doc/tmpl/ccss-unused.sgml8
-rw-r--r--ccss-doc/tmpl/node.sgml1
-rw-r--r--ccss-doc/tmpl/stylesheet.sgml26
-rw-r--r--ccss/ccss-block-priv.h4
-rw-r--r--ccss/ccss-block.c18
-rw-r--r--ccss/ccss-grammar-parse.c77
-rw-r--r--ccss/ccss-grammar-priv.h3
-rw-r--r--ccss/ccss-grammar.c29
-rw-r--r--ccss/ccss-node-priv.h3
-rw-r--r--ccss/ccss-node.c9
-rw-r--r--ccss/ccss-node.h6
-rw-r--r--ccss/ccss-selector-group.c80
-rw-r--r--ccss/ccss-selector-group.h4
-rw-r--r--ccss/ccss-selector.c89
-rw-r--r--ccss/ccss-selector.h32
-rw-r--r--ccss/ccss-stylesheet-priv.h2
-rw-r--r--ccss/ccss-stylesheet.c136
-rw-r--r--ccss/ccss-stylesheet.h17
-rw-r--r--ccss/ccss.sym3
-rw-r--r--configure.in4
-rw-r--r--examples/Makefile.am3
-rw-r--r--examples/example-10.c60
-rw-r--r--examples/example-2.c3
24 files changed, 500 insertions, 120 deletions
diff --git a/ccss-doc/ccss-sections.txt b/ccss-doc/ccss-sections.txt
index 2ed1f1f..c3c0a05 100644
--- a/ccss-doc/ccss-sections.txt
+++ b/ccss-doc/ccss-sections.txt
@@ -70,7 +70,8 @@ ccss_stylesheet_reference
ccss_stylesheet_get_reference_count
+ccss_stylesheet_add_from_buffer
ccss_stylesheet_add_from_file
ccss_stylesheet_foreach
-ccss_stylesheet_invalidate_node
ccss_stylesheet_query_type
ccss_stylesheet_query
+ccss_stylesheet_unload
ccss_stylesheet_dump
diff --git a/ccss-doc/tmpl/ccss-unused.sgml b/ccss-doc/tmpl/ccss-unused.sgml
index 34891ab..a93cf66 100644
--- a/ccss-doc/tmpl/ccss-unused.sgml
+++ b/ccss-doc/tmpl/ccss-unused.sgml
@@ -332,2 +332,10 @@ ccss_selector_group_t
+<!-- ##### FUNCTION ccss_stylesheet_invalidate_node ##### -->
+<para>
+
+</para>
+
+@self:
+@instance:
+
<!-- ##### FUNCTION ccss_stylesheet_iter_init ##### -->
diff --git a/ccss-doc/tmpl/node.sgml b/ccss-doc/tmpl/node.sgml
index 75fb027..8111d22 100644
--- a/ccss-doc/tmpl/node.sgml
+++ b/ccss-doc/tmpl/node.sgml
@@ -258,2 +258,3 @@ ccss_node_t
@self:
+@descriptor:
@Returns:
diff --git a/ccss-doc/tmpl/stylesheet.sgml b/ccss-doc/tmpl/stylesheet.sgml
index e1bb61f..ad21618 100644
--- a/ccss-doc/tmpl/stylesheet.sgml
+++ b/ccss-doc/tmpl/stylesheet.sgml
@@ -70,3 +70,3 @@ ccss_stylesheet_t
-<!-- ##### FUNCTION ccss_stylesheet_add_from_file ##### -->
+<!-- ##### FUNCTION ccss_stylesheet_add_from_buffer ##### -->
<para>
@@ -76,3 +76,4 @@ ccss_stylesheet_t
@self:
-@css_file:
+@buffer:
+@size:
@precedence:
@@ -82,3 +83,3 @@ ccss_stylesheet_t
-<!-- ##### FUNCTION ccss_stylesheet_foreach ##### -->
+<!-- ##### FUNCTION ccss_stylesheet_add_from_file ##### -->
<para>
@@ -88,7 +89,9 @@ ccss_stylesheet_t
@self:
-@func:
+@css_file:
+@precedence:
@user_data:
+@Returns:
-<!-- ##### FUNCTION ccss_stylesheet_invalidate_node ##### -->
+<!-- ##### FUNCTION ccss_stylesheet_foreach ##### -->
<para>
@@ -98,3 +101,4 @@ ccss_stylesheet_t
@self:
-@instance:
+@func:
+@user_data:
@@ -121,2 +125,12 @@ ccss_stylesheet_t
+<!-- ##### FUNCTION ccss_stylesheet_unload ##### -->
+<para>
+
+</para>
+
+@self:
+@descriptor:
+@Returns:
+
+
<!-- ##### FUNCTION ccss_stylesheet_dump ##### -->
diff --git a/ccss/ccss-block-priv.h b/ccss/ccss-block-priv.h
index db87467..a389b04 100644
--- a/ccss/ccss-block-priv.h
+++ b/ccss/ccss-block-priv.h
@@ -37,3 +37,4 @@ struct ccss_block_ {
/*< private >*/
- GHashTable *properties;
+ unsigned int reference_count;
+ GHashTable *properties;
};
@@ -42,2 +43,3 @@ ccss_block_t * ccss_block_create (void);
void ccss_block_destroy (ccss_block_t *self);
+ccss_block_t * ccss_block_reference (ccss_block_t *self);
diff --git a/ccss/ccss-block.c b/ccss/ccss-block.c
index 5347892..2be2244 100644
--- a/ccss/ccss-block.c
+++ b/ccss/ccss-block.c
@@ -31,2 +31,3 @@ ccss_block_create (void)
self = g_new0 (ccss_block_t, 1);
+ self->reference_count = 1;
self->properties = g_hash_table_new_full ((GHashFunc) g_direct_hash,
@@ -44,6 +45,19 @@ ccss_block_destroy (ccss_block_t *self)
- g_hash_table_destroy (self->properties), self->properties = NULL;
- g_free (self);
+ self->reference_count--;
+
+ if (self->reference_count == 0) {
+ g_hash_table_destroy (self->properties), self->properties = NULL;
+ g_free (self);
+ }
}
+ccss_block_t *
+ccss_block_reference (ccss_block_t *self)
+{
+ g_return_val_if_fail (self, NULL);
+
+ self->reference_count++;
+
+ return self;
+}
diff --git a/ccss/ccss-grammar-parse.c b/ccss/ccss-grammar-parse.c
index 937d5c1..6c44e7d 100644
--- a/ccss/ccss-grammar-parse.c
+++ b/ccss/ccss-grammar-parse.c
@@ -40,2 +40,3 @@ typedef struct {
ccss_stylesheet_precedence_t precedence;
+ unsigned int stylesheet_descriptor;
void *user_data;
@@ -96,2 +97,3 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
bool is_important)
@@ -113,3 +115,6 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel,
name = cr_string_peek_raw_str (cr_add_sel->content.class_name);
- selector = ccss_class_selector_create (name, precedence, importance);
+ selector = ccss_class_selector_create (name,
+ precedence,
+ stylesheet_descriptor,
+ importance);
break;
@@ -117,3 +122,6 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel,
name = cr_string_peek_raw_str (cr_add_sel->content.pseudo->name);
- selector = ccss_pseudo_class_selector_create (name, precedence, importance);
+ selector = ccss_pseudo_class_selector_create (name,
+ precedence,
+ stylesheet_descriptor,
+ importance);
break;
@@ -121,3 +129,6 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel,
name = cr_string_peek_raw_str (cr_add_sel->content.id_name);
- selector = ccss_id_selector_create (name, precedence, importance);
+ selector = ccss_id_selector_create (name,
+ precedence,
+ stylesheet_descriptor,
+ importance);
break;
@@ -127,3 +138,8 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel,
match = map_attribute_selector_match (cr_add_sel->content.attr_sel->match_way);
- selector = ccss_attribute_selector_create (name, value, match, precedence, importance);
+ selector = ccss_attribute_selector_create (name,
+ value,
+ match,
+ precedence,
+ stylesheet_descriptor,
+ importance);
break;
@@ -137,3 +153,6 @@ walk_additional_selector (CRAdditionalSel *cr_add_sel,
ccss_selector_t *refinement;
- refinement = walk_additional_selector (cr_add_sel->next, precedence, is_important);
+ refinement = walk_additional_selector (cr_add_sel->next,
+ precedence,
+ stylesheet_descriptor,
+ is_important);
ccss_selector_refine (selector, refinement);
@@ -147,2 +166,3 @@ walk_simple_selector_r (CRSimpleSel *cr_simple_sel,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
bool is_important)
@@ -157,5 +177,10 @@ walk_simple_selector_r (CRSimpleSel *cr_simple_sel,
if (UNIVERSAL_SELECTOR & cr_simple_sel->type_mask) {
- selector = ccss_universal_selector_create (precedence, importance);
+ selector = ccss_universal_selector_create (precedence,
+ stylesheet_descriptor,
+ importance);
} else if (TYPE_SELECTOR & cr_simple_sel->type_mask) {
- selector = ccss_type_selector_create (cr_string_peek_raw_str (cr_simple_sel->name), precedence, importance);
+ selector = ccss_type_selector_create (cr_string_peek_raw_str (cr_simple_sel->name),
+ precedence,
+ stylesheet_descriptor,
+ importance);
} else {
@@ -171,3 +196,6 @@ walk_simple_selector_r (CRSimpleSel *cr_simple_sel,
ccss_selector_t *refinement;
- refinement = walk_additional_selector (cr_simple_sel->add_sel, precedence, is_important);
+ refinement = walk_additional_selector (cr_simple_sel->add_sel,
+ precedence,
+ stylesheet_descriptor,
+ is_important);
ccss_selector_refine (selector, refinement);
@@ -177,3 +205,6 @@ walk_simple_selector_r (CRSimpleSel *cr_simple_sel,
ccss_selector_t *descendant;
- descendant = walk_simple_selector_r (cr_simple_sel->next, precedence, is_important);
+ descendant = walk_simple_selector_r (cr_simple_sel->next,
+ precedence,
+ stylesheet_descriptor,
+ is_important);
if (COMB_WS == cr_simple_sel->next->combinator) {
@@ -197,2 +228,3 @@ walk_selector (CRSelector *cr_sel,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
bool is_important,
@@ -211,3 +243,5 @@ walk_selector (CRSelector *cr_sel,
selector = ccss_instance_selector_create (instance_info->instance,
- precedence, importance);
+ precedence,
+ stylesheet_descriptor,
+ importance);
ccss_selector_set_block (selector, block);
@@ -221,3 +255,6 @@ walk_selector (CRSelector *cr_sel,
do {
- selector = walk_simple_selector_r (iter->simple_sel, precedence, is_important);
+ selector = walk_simple_selector_r (iter->simple_sel,
+ precedence,
+ stylesheet_descriptor,
+ is_important);
if (selector) {
@@ -356,5 +393,5 @@ end_selector_cb (CRDocHandler *handler,
if (info->block) {
- walk_selector (cr_sel, info->block, info->groups,
- info->precedence, false,
- info->instance);
+ walk_selector (cr_sel, info->block, info->groups,
+ info->precedence, info->stylesheet_descriptor,
+ false, info->instance);
info->block = NULL;
@@ -365,5 +402,5 @@ end_selector_cb (CRDocHandler *handler,
if (info->important_block) {
- walk_selector (cr_sel, info->important_block, info->groups,
- info->precedence, true,
- info->instance);
+ walk_selector (cr_sel, info->important_block, info->groups,
+ info->precedence, info->stylesheet_descriptor,
+ true, info->instance);
info->important_block = NULL;
@@ -376,2 +413,3 @@ ccss_grammar_parse_file (ccss_grammar_t const *self,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
void *user_data,
@@ -393,2 +431,3 @@ ccss_grammar_parse_file (ccss_grammar_t const *self,
info.precedence = precedence;
+ info.stylesheet_descriptor = stylesheet_descriptor;
info.user_data = user_data;
@@ -426,2 +465,3 @@ ccss_grammar_parse_buffer (ccss_grammar_t const *self,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
void *user_data,
@@ -444,2 +484,3 @@ ccss_grammar_parse_buffer (ccss_grammar_t const *self,
info.precedence = precedence;
+ info.stylesheet_descriptor = stylesheet_descriptor;
info.user_data = user_data;
@@ -471,2 +512,3 @@ ccss_grammar_parse_inline (ccss_grammar_t const *self,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
ptrdiff_t instance,
@@ -496,2 +538,3 @@ ccss_grammar_parse_inline (ccss_grammar_t const *self,
info.precedence = precedence;
+ info.stylesheet_descriptor = stylesheet_descriptor;
info.blocks = blocks;
diff --git a/ccss/ccss-grammar-priv.h b/ccss/ccss-grammar-priv.h
index c67e059..05ef177 100644
--- a/ccss/ccss-grammar-priv.h
+++ b/ccss/ccss-grammar-priv.h
@@ -52,2 +52,3 @@ ccss_grammar_parse_file (ccss_grammar_t const *self,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
void *user_data,
@@ -61,2 +62,3 @@ ccss_grammar_parse_buffer (ccss_grammar_t const *self,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
void *user_data,
@@ -69,2 +71,3 @@ ccss_grammar_parse_inline (ccss_grammar_t const *self,
ccss_stylesheet_precedence_t precedence,
+ unsigned int stylesheet_descriptor,
ptrdiff_t instance,
diff --git a/ccss/ccss-grammar.c b/ccss/ccss-grammar.c
index 1ffde28..4a319c4 100644
--- a/ccss/ccss-grammar.c
+++ b/ccss/ccss-grammar.c
@@ -268,8 +268,15 @@ ccss_grammar_create_stylesheet_from_buffer (ccss_grammar_t *self,
+ g_return_val_if_fail (self, NULL);
+ g_return_val_if_fail (buffer, NULL);
+ g_return_val_if_fail (size, NULL);
+
stylesheet = ccss_stylesheet_create ();
stylesheet->grammar = ccss_grammar_reference (self);
+ stylesheet->current_descriptor++;
- ret = ccss_grammar_parse_buffer (self, buffer, size,
- CCSS_STYLESHEET_AUTHOR, user_data,
- stylesheet->groups, stylesheet->blocks);
+ ret = ccss_grammar_parse_buffer (self, buffer, size,
+ CCSS_STYLESHEET_AUTHOR,
+ stylesheet->current_descriptor,
+ user_data,
+ stylesheet->groups, stylesheet->blocks);
@@ -278,2 +285,4 @@ ccss_grammar_create_stylesheet_from_buffer (ccss_grammar_t *self,
return stylesheet;
+ } else {
+ /* TODO clean up using stylesheet->current_descriptor */
}
@@ -301,8 +310,14 @@ ccss_grammar_create_stylesheet_from_file (ccss_grammar_t *self,
+ g_return_val_if_fail (self, NULL);
+ g_return_val_if_fail (css_file, NULL);
+
stylesheet = ccss_stylesheet_create ();
stylesheet->grammar = ccss_grammar_reference (self);
+ stylesheet->current_descriptor++;
- ret = ccss_grammar_parse_file (self, css_file, CCSS_STYLESHEET_AUTHOR,
- user_data, stylesheet->groups,
- stylesheet->blocks);
+ ret = ccss_grammar_parse_file (self, css_file,
+ CCSS_STYLESHEET_AUTHOR,
+ stylesheet->current_descriptor,
+ user_data,
+ stylesheet->groups, stylesheet->blocks);
@@ -311,2 +326,4 @@ ccss_grammar_create_stylesheet_from_file (ccss_grammar_t *self,
return stylesheet;
+ } else {
+ /* TODO clean up using stylesheet->current_descriptor */
}
diff --git a/ccss/ccss-node-priv.h b/ccss/ccss-node-priv.h
index 73e1e92..791fb88 100644
--- a/ccss/ccss-node-priv.h
+++ b/ccss/ccss-node-priv.h
@@ -61,3 +61,4 @@ ccss_node_get_attribute (ccss_node_t const *self,
char const *
-ccss_node_get_style (ccss_node_t *self);
+ccss_node_get_style (ccss_node_t *self,
+ unsigned int descriptor);
diff --git a/ccss/ccss-node.c b/ccss/ccss-node.c
index 39d7a1d..306b2a5 100644
--- a/ccss/ccss-node.c
+++ b/ccss/ccss-node.c
@@ -83,3 +83,4 @@ get_attribute (ccss_node_t const *self,
static char const *
-get_style (ccss_node_t const *self)
+get_style (ccss_node_t const *self,
+ unsigned int descriptor)
{
@@ -277,3 +278,4 @@ ccss_node_get_attribute (ccss_node_t const *self,
char const *
-ccss_node_get_style (ccss_node_t *self)
+ccss_node_get_style (ccss_node_t *self,
+ unsigned int descriptor)
{
@@ -284,3 +286,4 @@ ccss_node_get_style (ccss_node_t *self)
if (NULL == self->inline_style)
- self->inline_style = self->node_class->get_style (self);
+ self->inline_style = self->node_class->get_style (self,
+ descriptor);
diff --git a/ccss/ccss-node.h b/ccss/ccss-node.h
index c534c2a..409d273 100644
--- a/ccss/ccss-node.h
+++ b/ccss/ccss-node.h
@@ -136,2 +136,3 @@ typedef char * (*ccss_node_get_attribute_f) (ccss_node_t const *self,
* @self: a #ccss_node_t.
+ * @descriptor: handle to unload this style from the stylesheet later on.
*
@@ -139,5 +140,8 @@ typedef char * (*ccss_node_get_attribute_f) (ccss_node_t const *self,
*
+ * See: ccss_stylesheet_unload().
+ *
* Returns: the node's CSS properties or %NULL.
**/
-typedef const char * (*ccss_node_get_style_f) (ccss_node_t const *self);
+typedef const char * (*ccss_node_get_style_f) (ccss_node_t const *self,
+ unsigned int descriptor);
diff --git a/ccss/ccss-selector-group.c b/ccss/ccss-selector-group.c
index b09cb91..ecdc391 100644
--- a/ccss/ccss-selector-group.c
+++ b/ccss/ccss-selector-group.c
@@ -100,2 +100,82 @@ ccss_selector_group_destroy (ccss_selector_group_t *self)
+typedef struct {
+ unsigned int descriptor;
+ GSList *empty_sets;
+ bool ret;
+} traverse_unload_info_t;
+
+static bool
+traverse_unload (size_t specificity,
+ ccss_selector_set_t *set,
+ traverse_unload_info_t *info)
+{
+ ccss_selector_t *selector;
+ GSList *iter;
+
+ g_assert (info);
+
+ iter = set->selectors;
+ while (iter) {
+ selector = (ccss_selector_t *) iter->data;
+ if (ccss_selector_get_descriptor (selector) == info->descriptor) {
+ ccss_selector_destroy (selector);
+ if (iter == set->selectors) {
+ /* Removing the last element? */
+ iter = g_slist_delete_link (iter, iter);
+ if (NULL == iter) {
+ /* Yes, remember to remove the node. */
+ info->empty_sets = g_slist_prepend (info->empty_sets,
+ GSIZE_TO_POINTER (specificity));
+ set->selectors = NULL;
+ } else {
+ /* No, but new head. */
+ set->selectors = iter;
+ }
+ } else {
+ iter = g_slist_delete_link (iter, iter);
+ }
+ info->ret = true;
+ } else {
+ iter = iter->next;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * ccss_selector_group_unload:
+ * @self: a #ccss_selector_group_t.
+ * @descriptor descriptor of a part that was loaded.
+ *
+ * Unload a CSS file, buffer or inline style that was loaded into the selector group.
+ *
+ * Returns: %TRUE if anything had been unloaded.
+ */
+bool
+ccss_selector_group_unload (ccss_selector_group_t *self,
+ unsigned int descriptor)
+{
+ GSList *iter;
+ traverse_unload_info_t info;
+
+ g_return_val_if_fail (self, false);
+ g_return_val_if_fail (descriptor, false);
+
+ info.descriptor = descriptor;
+ info.empty_sets = NULL;
+ info.ret = false;
+
+ g_tree_foreach (self->sets, (GTraverseFunc) traverse_unload, &info);
+
+ /* Prune empty sets. */
+ iter = info.empty_sets;
+ while (iter) {
+ g_tree_remove (self->sets, iter->data);
+ iter = g_slist_delete_link (iter, iter);
+ }
+
+ return info.ret;
+}
+
/*
diff --git a/ccss/ccss-selector-group.h b/ccss/ccss-selector-group.h
index def0f72..c2c5e77 100644
--- a/ccss/ccss-selector-group.h
+++ b/ccss/ccss-selector-group.h
@@ -42,2 +42,6 @@ ccss_selector_group_destroy (ccss_selector_group_t *self);
bool
+ccss_selector_group_unload (ccss_selector_group_t *self,
+ unsigned int descriptor);
+
+bool
ccss_selector_group_apply_type (ccss_selector_group_t const *self,
diff --git a/ccss/ccss-selector.c b/ccss/ccss-selector.c
index 829c944..17ab68e 100644
--- a/ccss/ccss-selector.c
+++ b/ccss/ccss-selector.c
@@ -55,2 +55,3 @@ struct ccss_selector_ {
ccss_selector_modality_t modality;
+ unsigned int stylesheet_descriptor;
unsigned int importance : 2;
@@ -65,3 +66,3 @@ struct ccss_selector_ {
struct ccss_selector_ *antecessor;
- ccss_block_t const *block;
+ ccss_block_t *block;
};
@@ -75,2 +76,3 @@ selector_sync (ccss_selector_t const *self,
to->modality = self->modality;
+ to->stylesheet_descriptor = self->stylesheet_descriptor;
to->importance = self->importance;
@@ -85,3 +87,3 @@ selector_sync (ccss_selector_t const *self,
to->antecessor = NULL;
- to->block = self->block;
+ to->block = ccss_block_reference (self->block);
}
@@ -94,4 +96,5 @@ typedef ccss_selector_t ccss_universal_selector_t;
ccss_selector_t *
-ccss_universal_selector_create (unsigned int precedence,
- ccss_selector_importance_t importance)
+ccss_universal_selector_create (unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance)
{
@@ -101,2 +104,3 @@ ccss_universal_selector_create (unsigned int precedence,
self->modality = CCSS_SELECTOR_MODALITY_UNIVERSAL;
+ self->stylesheet_descriptor = stylesheet_descriptor;
self->importance = importance;
@@ -143,4 +147,5 @@ ccss_selector_t *
ccss_type_selector_create (char const *type_name,
- unsigned int precedence,
- ccss_selector_importance_t importance)
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance)
{
@@ -152,2 +157,3 @@ ccss_type_selector_create (char const *type_name,
self->parent.modality = CCSS_SELECTOR_MODALITY_TYPE;
+ self->parent.stylesheet_descriptor = stylesheet_descriptor;
self->parent.importance = importance;
@@ -194,5 +200,6 @@ ccss_selector_t *
ccss_base_type_selector_create (char const *type_name,
- unsigned int precedence,
- ccss_selector_importance_t importance,
- unsigned int specificity_e)
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance,
+ unsigned int specificity_e)
{
@@ -200,6 +207,8 @@ ccss_base_type_selector_create (char const *type_name,
- self = ccss_type_selector_create (type_name, precedence, importance);
+ self = ccss_type_selector_create (type_name,
+ precedence,
+ stylesheet_descriptor,
+ importance);
self->modality = CCSS_SELECTOR_MODALITY_BASE_TYPE;
- self->importance = importance;
- self->precedence = precedence;
+
self->a = 0;
@@ -223,4 +232,5 @@ ccss_selector_t *
ccss_class_selector_create (char const *class_name,
- unsigned int precedence,
- ccss_selector_importance_t importance)
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance)
{
@@ -232,2 +242,3 @@ ccss_class_selector_create (char const *class_name,
self->parent.modality = CCSS_SELECTOR_MODALITY_CLASS;
+ self->parent.stylesheet_descriptor = stylesheet_descriptor;
self->parent.importance = importance;
@@ -278,4 +289,5 @@ ccss_selector_t *
ccss_id_selector_create (char const *id,
- unsigned int precedence,
- ccss_selector_importance_t importance)
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance)
{
@@ -287,2 +299,3 @@ ccss_id_selector_create (char const *id,
self->parent.modality = CCSS_SELECTOR_MODALITY_ID;
+ self->parent.stylesheet_descriptor = stylesheet_descriptor;
self->parent.importance = importance;
@@ -334,7 +347,8 @@ typedef struct {
ccss_selector_t *
-ccss_attribute_selector_create (char const *name,
- char const *value,
- ccss_attribute_selector_match_t match,
- unsigned int precedence,
- ccss_selector_importance_t importance)
+ccss_attribute_selector_create (char const *name,
+ char const *value,
+ ccss_attribute_selector_match_t match,
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance)
{
@@ -346,2 +360,3 @@ ccss_attribute_selector_create (char const *name,
self->parent.modality = CCSS_SELECTOR_MODALITY_ATTRIBUTE;
+ self->parent.stylesheet_descriptor = stylesheet_descriptor;
self->parent.importance = importance;
@@ -406,4 +421,5 @@ ccss_selector_t *
ccss_pseudo_class_selector_create (char const *pseudo_class,
- unsigned int precedence,
- ccss_selector_importance_t importance)
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance)
{
@@ -415,2 +431,3 @@ ccss_pseudo_class_selector_create (char const *pseudo_class,
self->parent.modality = CCSS_SELECTOR_MODALITY_PSEUDO_CLASS;
+ self->parent.stylesheet_descriptor = stylesheet_descriptor;
self->parent.importance = importance;
@@ -461,4 +478,5 @@ ccss_selector_t *
ccss_instance_selector_create (ptrdiff_t instance,
- unsigned int precedence,
- ccss_selector_importance_t importance)
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance)
{
@@ -470,2 +488,3 @@ ccss_instance_selector_create (ptrdiff_t instance,
self->parent.modality = CCSS_SELECTOR_MODALITY_INSTANCE;
+ self->parent.stylesheet_descriptor = stylesheet_descriptor;
self->parent.importance = importance;
@@ -614,2 +633,7 @@ ccss_selector_destroy (ccss_selector_t *self)
+ /* Only the innermost type selector references the block. */
+ if (self->block) {
+ ccss_block_destroy (self->block);
+ }
+
switch (self->modality) {
@@ -780,8 +804,8 @@ ccss_selector_get_block (ccss_selector_t const *self)
void
-ccss_selector_set_block (ccss_selector_t *self,
- ccss_block_t const *block)
+ccss_selector_set_block (ccss_selector_t *self,
+ ccss_block_t *block)
{
- g_assert (self);
+ g_assert (self && self->block == NULL);
- self->block = block;
+ self->block = ccss_block_reference (block);
}
@@ -835,2 +859,8 @@ ccss_selector_get_key (ccss_selector_t const *self)
+unsigned int
+ccss_selector_get_descriptor (ccss_selector_t const *self)
+{
+ return self->stylesheet_descriptor;
+}
+
uint32_t
@@ -1127,2 +1157,3 @@ ccss_selector_dump (ccss_selector_t const *self)
g_string_append (selector, " /* ");
+ g_string_append_printf (selector, "'%d' ", self->stylesheet_descriptor);
ccss_selector_serialize_specificity (self, selector);
diff --git a/ccss/ccss-selector.h b/ccss/ccss-selector.h
index 3338e6d..d1420ff 100644
--- a/ccss/ccss-selector.h
+++ b/ccss/ccss-selector.h
@@ -55,2 +55,3 @@ ccss_selector_t *
ccss_universal_selector_create (unsigned int precedence,
+ unsigned int stylesheet_descriptor,
ccss_selector_importance_t importance);
@@ -59,2 +60,3 @@ ccss_type_selector_create (char const *type_name,
unsigned int precedence,
+ unsigned int stylesheet_descriptor,
ccss_selector_importance_t importance);
@@ -63,2 +65,3 @@ ccss_base_type_selector_create (char const *type_name,
unsigned int precedence,
+ unsigned int stylesheet_descriptor,
ccss_selector_importance_t importance,
@@ -68,2 +71,3 @@ ccss_class_selector_create (char const *class_name,
unsigned int precedence,
+ unsigned int stylesheet_descriptor,
ccss_selector_importance_t importance);
@@ -72,2 +76,3 @@ ccss_id_selector_create (char const *id,
unsigned int precedence,
+ unsigned int stylesheet_descriptor,
ccss_selector_importance_t importance);
@@ -78,2 +83,3 @@ ccss_attribute_selector_create (char const *name,
unsigned int precedence,
+ unsigned int stylesheet_descriptor,
ccss_selector_importance_t importance);
@@ -81,4 +87,5 @@ ccss_selector_t *
ccss_pseudo_class_selector_create (char const *pseudo_class,
- unsigned int precedence,
- ccss_selector_importance_t importance);
+ unsigned int precedence,
+ unsigned int stylesheet_descriptor,
+ ccss_selector_importance_t importance);
ccss_selector_t *
@@ -86,13 +93,14 @@ ccss_instance_selector_create (ptrdiff_t instance,
unsigned int precedence,
+ unsigned int stylesheet_descriptor,
ccss_selector_importance_t importance);
+void ccss_selector_destroy (ccss_selector_t *self);
+
ccss_selector_t * ccss_selector_copy (ccss_selector_t const *original);
ccss_selector_t * ccss_selector_copy_as_base (ccss_selector_t const *original,
- int specificity_e);
-
-void ccss_selector_destroy (ccss_selector_t *self);
+ int specificity_e);
-void ccss_selector_refine (ccss_selector_t *self, ccss_selector_t *selector);
-ccss_selector_t * ccss_selector_append_child (ccss_selector_t *self, ccss_selector_t *selector);
-ccss_selector_t * ccss_selector_append_descendant (ccss_selector_t *self, ccss_selector_t *selector);
+void ccss_selector_refine (ccss_selector_t *self, ccss_selector_t *selector);
+ccss_selector_t * ccss_selector_append_child (ccss_selector_t *self, ccss_selector_t *selector);
+ccss_selector_t * ccss_selector_append_descendant (ccss_selector_t *self, ccss_selector_t *selector);
@@ -100,6 +108,7 @@ bool ccss_selector_is_type (ccss_selector_t const *self);
bool ccss_selector_is_class (ccss_selector_t const *self);
-bool ccss_selector_is_id (ccss_selector_t const *self);
+bool ccss_selector_is_id (ccss_selector_t const *self);
-ccss_block_t const * ccss_selector_get_block (ccss_selector_t const *self);
-void ccss_selector_set_block (ccss_selector_t *self, ccss_block_t const *block);
+ccss_block_t const * ccss_selector_get_block (ccss_selector_t const *self);
+void ccss_selector_set_block (ccss_selector_t *self,
+ ccss_block_t *block);
@@ -108,2 +117,3 @@ ccss_selector_importance_t ccss_selector_get_importance (ccss_selector_t const *
/*ccss_stylesheet_precedence_t ccss_selector_get_precedence (ccss_selector_t const *self);*/
+unsigned int ccss_selector_get_descriptor (ccss_selector_t const *self);
uint32_t ccss_selector_get_specificity (ccss_selector_t const *self);
diff --git a/ccss/ccss-stylesheet-priv.h b/ccss/ccss-stylesheet-priv.h
index 4cc6c1e..8efab44 100644
--- a/ccss/ccss-stylesheet-priv.h
+++ b/ccss/ccss-stylesheet-priv.h
@@ -36,2 +36,3 @@ CCSS_BEGIN_DECLS
* @groups: Associates type names with all applying selectors.
+ * @current_descriptor: descriptor of the recently loaded CSS file or buffer.
*
@@ -45,2 +46,3 @@ struct ccss_stylesheet_ {
GHashTable *groups;
+ unsigned int current_descriptor;
};
diff --git a/ccss/ccss-stylesheet.c b/ccss/ccss-stylesheet.c
index 3253e01..c22e2b9 100644
--- a/ccss/ccss-stylesheet.c
+++ b/ccss/ccss-stylesheet.c
@@ -39,5 +39,10 @@ ccss_stylesheet_create (void)
self->reference_count = 1;
- self->blocks = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) ccss_block_destroy);
- self->groups = g_hash_table_new (g_str_hash, g_str_equal);
+ self->blocks = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ (GDestroyNotify) ccss_block_destroy);
+ self->groups = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ NULL,
+ (GDestroyNotify) ccss_selector_group_destroy);
@@ -92,3 +97,3 @@ ccss_stylesheet_fix_dangling_selectors (ccss_stylesheet_t *self)
* ccss_stylesheet_add_from_file:
- * @self: #ccss_stylesheet_t instance or %NULL.
+ * @self: a #ccss_stylesheet_t.
* @css_file: file to parse.
@@ -99,5 +104,6 @@ ccss_stylesheet_fix_dangling_selectors (ccss_stylesheet_t *self)
*
- * Returns: a #ccss_stylesheet_t representation of the CSS file.
+ * Returns: a stylesheet descriptor that can be used to unload the CSS file
+ * contents from the stylesheet instance.
**/
-ccss_stylesheet_t *
+unsigned int
ccss_stylesheet_add_from_file (ccss_stylesheet_t *self,
@@ -109,5 +115,8 @@ ccss_stylesheet_add_from_file (ccss_stylesheet_t *self,
- g_return_val_if_fail (self && css_file, NULL);
+ g_return_val_if_fail (self, 0);
+ g_return_val_if_fail (css_file, 0);
+ self->current_descriptor++;
ret = ccss_grammar_parse_file (self->grammar, css_file, precedence,
+ self->current_descriptor,
user_data, self->groups, self->blocks);
@@ -115,6 +124,75 @@ ccss_stylesheet_add_from_file (ccss_stylesheet_t *self,
ccss_stylesheet_fix_dangling_selectors (self);
- return self;
+ return self->current_descriptor;
+ } else {
+ /* TODO clean up using self->current_descriptor */
+ return 0;
}
+}
- return NULL;
+/**
+ * ccss_stylesheet_add_from_buffer:
+ * @self: a #ccss_stylesheet_t.
+ * @buffer: buffer to parse.
+ * @size: size of the buffer.
+ * @precedence: see #ccss_stylesheet_precedence_t.
+ * @user_data: user-data passed to property- and function-handlers.
+ *
+ * Load a CSS file with a given precedence.
+ *
+ * Returns: a stylesheet descriptor that can be used to unload the CSS file
+ * contents from the stylesheet instance.
+ **/
+unsigned int
+ccss_stylesheet_add_from_buffer (ccss_stylesheet_t *self,
+ char const *buffer,
+ size_t size,
+ ccss_stylesheet_precedence_t precedence,
+ void *user_data)
+{
+ enum CRStatus ret;
+
+ g_return_val_if_fail (self, 0);
+ g_return_val_if_fail (buffer, 0);
+ g_return_val_if_fail (size, 0);
+
+ self->current_descriptor++;
+ ret = ccss_grammar_parse_buffer (self->grammar, buffer, size, precedence,
+ self->current_descriptor,
+ user_data,
+ self->groups, self->blocks);
+ if (CR_OK == ret) {
+ ccss_stylesheet_fix_dangling_selectors (self);
+ return self->current_descriptor;
+ } else {
+ /* TODO clean up using self->current_descriptor */
+ return 0;
+ }
+}
+
+/**
+ * ccss_stylesheet_unload:
+ * @self: a #ccss_stylesheet_t.
+ * @descriptor descriptor of a part that was loaded.
+ *
+ * Unload a CSS file, buffer or inline style that was loaded into the stylesheet.
+ *
+ * Returns: %TRUE if anything had been unloaded.
+ */
+bool
+ccss_stylesheet_unload (ccss_stylesheet_t *self,
+ unsigned int descriptor)
+{
+ ccss_selector_group_t *group;
+ GHashTableIter iter;
+ bool ret;
+
+ g_return_val_if_fail (self, false);
+
+ ret = false;
+ g_hash_table_iter_init (&iter, self->groups);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &group)) {
+ ret |= ccss_selector_group_unload (group, descriptor);
+ }
+
+ return ret;
}
@@ -280,5 +358,5 @@ query_type_r (ccss_stylesheet_t const *self,
static bool
-query_node (ccss_stylesheet_t const *self,
- ccss_node_t *node,
- ccss_style_t *style)
+query_node (ccss_stylesheet_t *self,
+ ccss_node_t *node,
+ ccss_style_t *style)
{
@@ -287,2 +365,3 @@ query_node (ccss_stylesheet_t const *self,
char const *inline_css;
+ unsigned int prospective_descriptor;
enum CRStatus status;
@@ -306,3 +385,4 @@ query_node (ccss_stylesheet_t const *self,
/* Handle inline styling. */
- inline_css = ccss_node_get_style (node);
+ prospective_descriptor = self->current_descriptor + 1;
+ inline_css = ccss_node_get_style (node, prospective_descriptor);
if (inline_css) {
@@ -318,2 +398,3 @@ query_node (ccss_stylesheet_t const *self,
CCSS_STYLESHEET_AUTHOR,
+ prospective_descriptor,
instance, NULL,
@@ -322,2 +403,7 @@ query_node (ccss_stylesheet_t const *self,
ret |= (status == CR_OK);
+ if (CR_OK == ret) {
+ self->current_descriptor = prospective_descriptor;
+ } else {
+ /* TODO clean up using prospective_descriptor. */
+ }
}
@@ -417,6 +503,6 @@ inherit_container_style (ccss_style_t const *container_style,
static bool
-query_container_r (ccss_stylesheet_t const *self,
- ccss_node_t *node,
- GHashTable *inherit,
- ccss_style_t *style)
+query_container_r (ccss_stylesheet_t *self,
+ ccss_node_t *node,
+ GHashTable *inherit,
+ ccss_style_t *style)
{
@@ -526,18 +612,2 @@ ccss_stylesheet_query (ccss_stylesheet_t *self,
/**
- * ccss_stylesheet_invalidate_node:
- * @self: a #ccss_stylesheet_t.
- * @instance: an instance identifyer, as returned by #ccss_node_get_instance_f.
- *
- * Frees parsed inline CSS asocciated to a document node.
- **/
-void
-ccss_stylesheet_invalidate_node (ccss_stylesheet_t const *self,
- ptrdiff_t instance)
-{
- g_assert (self && self->blocks);
-
- g_hash_table_remove (self->blocks, (gconstpointer) instance);
-}
-
-/**
* ccss_stylesheet_foreach:
diff --git a/ccss/ccss-stylesheet.h b/ccss/ccss-stylesheet.h
index 8a6ccde..3f81893 100644
--- a/ccss/ccss-stylesheet.h
+++ b/ccss/ccss-stylesheet.h
@@ -60,3 +60,3 @@ ccss_stylesheet_get_grammar (ccss_stylesheet_t const *self);
-ccss_stylesheet_t *
+unsigned int
ccss_stylesheet_add_from_file (ccss_stylesheet_t *self,
@@ -66,2 +66,13 @@ ccss_stylesheet_add_from_file (ccss_stylesheet_t *self,
+unsigned int
+ccss_stylesheet_add_from_buffer (ccss_stylesheet_t *self,
+ char const *buffer,
+ size_t size,
+ ccss_stylesheet_precedence_t precedence,
+ void *user_data);
+
+bool
+ccss_stylesheet_unload (ccss_stylesheet_t *self,
+ unsigned int descriptor);
+
ccss_style_t *
@@ -74,6 +85,2 @@ ccss_stylesheet_query (ccss_stylesheet_t *self,
-void
-ccss_stylesheet_invalidate_node (ccss_stylesheet_t const *self,
- ptrdiff_t instance);
-
/**
diff --git a/ccss/ccss.sym b/ccss/ccss.sym
index 511f6b8..6f031db 100644
--- a/ccss/ccss.sym
+++ b/ccss/ccss.sym
@@ -33,2 +33,3 @@ ccss_style_hash
ccss_style_interpret_property
+ccss_stylesheet_add_from_buffer
ccss_stylesheet_add_from_file
@@ -38,3 +39,2 @@ ccss_stylesheet_foreach
ccss_stylesheet_get_reference_count
-ccss_stylesheet_invalidate_node
ccss_stylesheet_query
@@ -42 +42,2 @@ ccss_stylesheet_query_type
ccss_stylesheet_reference
+ccss_stylesheet_unload
diff --git a/configure.in b/configure.in
index e32ba86..15fe81f 100644
--- a/configure.in
+++ b/configure.in
@@ -9,4 +9,4 @@ AC_PREREQ(2.54)
m4_define([ccss_version_major], [0])
-m4_define([ccss_version_minor], [4])
-m4_define([ccss_version_micro], [1])
+m4_define([ccss_version_minor], [5])
+m4_define([ccss_version_micro], [0])
m4_define([ccss_version_extra], [])
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 30f4029..d351e09 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -27,2 +27,3 @@ noinst_PROGRAMS = \
example-9 \
+ example-10 \
$(NULL)
@@ -67,2 +68,4 @@ example_9_SOURCES = example-9.c
+example_10_SOURCES = example-10.c
+
EXTRA_DIST = \
diff --git a/examples/example-10.c b/examples/example-10.c
new file mode 100644
index 0000000..b0c249e
--- /dev/null
+++ b/examples/example-10.c
@@ -0,0 +1,60 @@
+/* vim: set ts=8 sw=8 noexpandtab: */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ccss/ccss.h>
+#include "config.h"
+
+static char const _css_1[] = " \
+ a { \
+ bar: 1; \
+ } \
+";
+
+static char const _css_2[] = " \
+ a { \
+ baz: 2; \
+ } \
+ b { \
+ frob: 3; \
+ } \
+";
+
+int
+main (int argc,
+ char **argv)
+{
+ ccss_grammar_t *grammar;
+ ccss_stylesheet_t *stylesheet;
+ unsigned int descriptor;
+
+ grammar = ccss_grammar_create_css ();
+ stylesheet = ccss_grammar_create_stylesheet (grammar);
+ ccss_grammar_destroy (grammar);
+
+ g_debug ("Empty stylesheet");
+ ccss_stylesheet_dump (stylesheet);
+
+ descriptor = ccss_stylesheet_add_from_buffer (stylesheet,
+ _css_1, sizeof (_css_1),
+ CCSS_STYLESHEET_AUTHOR,
+ NULL);
+ g_debug ("With buffer 1 ('%d')", descriptor);
+ ccss_stylesheet_dump (stylesheet);
+
+ descriptor = ccss_stylesheet_add_from_buffer (stylesheet,
+ _css_2, sizeof (_css_2),
+ CCSS_STYLESHEET_AUTHOR,
+ NULL);
+ g_debug ("With buffer 2 ('%d')", descriptor);
+ ccss_stylesheet_dump (stylesheet);
+
+ ccss_stylesheet_unload (stylesheet, descriptor);
+ g_debug ("Back to just buffer 1");
+ ccss_stylesheet_dump (stylesheet);
+
+ ccss_stylesheet_destroy (stylesheet);
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/examples/example-2.c b/examples/example-2.c
index 716ce60..088a1cc 100644
--- a/examples/example-2.c
+++ b/examples/example-2.c
@@ -28,3 +28,4 @@ get_instance (node_t const *self)
static char const *
-get_style (node_t const *self)
+get_style (node_t const *self,
+ unsigned int descriptor)
{