summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-07-27 19:38:34 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-07-27 19:38:34 +0000
commitfc6b96707730c54fb7ac4040680d79864169b5e0 (patch)
treeb26b5cc05c4ce87564b679628db3f044972eda3c /src
parent854eda8b63cc260524a5ec3e3681308b382c7060 (diff)
downloadlibcss-fc6b96707730c54fb7ac4040680d79864169b5e0.tar.gz
libcss-fc6b96707730c54fb7ac4040680d79864169b5e0.tar.bz2
Calculate the in-memory size of stylesheets and provide some API to access this.
svn path=/trunk/libcss/; revision=8830
Diffstat (limited to 'src')
-rw-r--r--src/select/hash.c29
-rw-r--r--src/select/hash.h2
-rw-r--r--src/stylesheet.c137
-rw-r--r--src/stylesheet.h2
4 files changed, 170 insertions, 0 deletions
diff --git a/src/select/hash.c b/src/select/hash.c
index 9bcfb15..df6ce4e 100644
--- a/src/select/hash.c
+++ b/src/select/hash.c
@@ -25,6 +25,8 @@ struct css_selector_hash {
lwc_context *ctx;
+ size_t hash_size;
+
css_allocator_fn alloc;
void *pw;
};
@@ -65,6 +67,9 @@ css_error css_selector_hash_create(lwc_context *dict,
memset(h->slots, 0, DEFAULT_SLOTS * sizeof(hash_entry));
h->n_slots = DEFAULT_SLOTS;
+ h->hash_size = sizeof(css_selector_hash) +
+ DEFAULT_SLOTS * sizeof(hash_entry);
+
h->ctx = lwc_context_ref(dict);
h->alloc = alloc;
h->pw = pw;
@@ -163,6 +168,8 @@ css_error css_selector_hash_insert(css_selector_hash *hash,
entry->next = prev->next;
prev->next = entry;
}
+
+ hash->hash_size += sizeof(hash_entry);
}
return CSS_OK;
@@ -216,6 +223,8 @@ css_error css_selector_hash_remove(css_selector_hash *hash,
prev->next = head->next;
hash->alloc(head, 0, hash->pw);
+
+ hash->hash_size -= sizeof(hash_entry);
}
return CSS_OK;
@@ -317,6 +326,26 @@ css_error css_selector_hash_iterate(css_selector_hash *hash,
return CSS_OK;
}
+/**
+ * Determine the memory-resident size of a hash
+ *
+ * \param hash Hash to consider
+ * \param size Pointer to location to receive byte count
+ * \return CSS_OK on success.
+ *
+ * \note The returned size will represent the size of the hash datastructures,
+ * and will not include the size of the data stored in the hash.
+ */
+css_error css_selector_hash_size(css_selector_hash *hash, size_t *size)
+{
+ if (hash == NULL || size == NULL)
+ return CSS_BADPARM;
+
+ *size = hash->hash_size;
+
+ return CSS_OK;
+}
+
/******************************************************************************
* Private functions *
******************************************************************************/
diff --git a/src/select/hash.h b/src/select/hash.h
index 59c8b76..9beaa6b 100644
--- a/src/select/hash.h
+++ b/src/select/hash.h
@@ -35,5 +35,7 @@ css_error css_selector_hash_iterate(css_selector_hash *hash,
const struct css_selector **current,
const struct css_selector ***next);
+css_error css_selector_hash_size(css_selector_hash *hash, size_t *size);
+
#endif
diff --git a/src/stylesheet.c b/src/stylesheet.c
index 7ec55b2..9afd5cc 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -16,6 +16,7 @@
static css_error _add_selectors(css_stylesheet *sheet, css_rule *rule);
static css_error _remove_selectors(css_stylesheet *sheet, css_rule *rule);
+static size_t _rule_size(const css_rule *rule);
/**
* Create a stylesheet
@@ -144,6 +145,10 @@ css_error css_stylesheet_create(css_language_level level,
sheet->alloc = alloc;
sheet->pw = alloc_pw;
+ sheet->size = sizeof(css_stylesheet) + strlen(sheet->url);
+ if (sheet->title != NULL)
+ sheet->size += strlen(sheet->title);
+
*stylesheet = sheet;
return CSS_OK;
@@ -506,6 +511,42 @@ css_error css_stylesheet_set_disabled(css_stylesheet *sheet, bool disabled)
return CSS_OK;
}
+/**
+ * Determine the memory-resident size of a stylesheet
+ *
+ * \param sheet Sheet to consider
+ * \param size Pointer to location to receive byte count
+ * \return CSS_OK on success.
+ *
+ * \note The returned size will not include the size of interned strings
+ * or imported stylesheets.
+ */
+css_error css_stylesheet_size(css_stylesheet *sheet, size_t *size)
+{
+ size_t bytes = 0;
+ css_error error;
+
+ if (sheet == NULL || size == NULL)
+ return CSS_BADPARM;
+
+ bytes = sheet->size;
+
+ /* Selector hash */
+ if (sheet->selectors != NULL) {
+ size_t hash_size;
+
+ error = css_selector_hash_size(sheet->selectors, &hash_size);
+ if (error != CSS_OK)
+ return error;
+
+ bytes += hash_size;
+ }
+
+ *size = bytes;
+
+ return CSS_OK;
+}
+
/******************************************************************************
* Library-private API below here *
******************************************************************************/
@@ -1042,11 +1083,17 @@ css_error css_stylesheet_rule_append_style(css_stylesheet *sheet,
cur = temp;
cur->length += style->length;
+ /* Add this to the sheet's size */
+ sheet->size += style->length;
+
/* Done with style */
css_stylesheet_style_destroy(sheet, style);
} else {
/* No current style, so use this one */
cur = style;
+
+ /* Add to the sheet's size */
+ sheet->size += style->length;
}
if (rule->type == CSS_RULE_SELECTOR)
@@ -1192,6 +1239,9 @@ css_error css_stylesheet_add_rule(css_stylesheet *sheet, css_rule *rule,
if (error != CSS_OK)
return error;
+ /* Add to the sheet's size */
+ sheet->size += _rule_size(rule);
+
if (parent != NULL) {
css_rule_media *media = (css_rule_media *) parent;
@@ -1252,6 +1302,9 @@ css_error css_stylesheet_remove_rule(css_stylesheet *sheet, css_rule *rule)
if (error != CSS_OK)
return error;
+ /* Reduce sheet's size */
+ sheet->size -= _rule_size(rule);
+
if (rule->next == NULL)
sheet->last_rule = rule->prev;
else
@@ -1392,3 +1445,87 @@ css_error _remove_selectors(css_stylesheet *sheet, css_rule *rule)
return CSS_OK;
}
+/**
+ * Calculate the size of a rule
+ *
+ * \param r Rule to consider
+ * \return Size in bytes
+ *
+ * \note The returned size does not include interned strings.
+ */
+size_t _rule_size(const css_rule *r)
+{
+ size_t bytes = 0;
+
+ if (r->type == CSS_RULE_SELECTOR) {
+ const css_rule_selector *rs = (const css_rule_selector *) r;
+ uint32_t i;
+
+ bytes += sizeof(css_rule_selector);
+
+ /* Process selector chains */
+ bytes += r->items * sizeof(css_selector *);
+ for (i = 0; i < r->items; i++) {
+ const css_selector *s = rs->selectors[i];
+
+ do {
+ const css_selector_detail *d = &s->data;
+
+ bytes += sizeof(css_selector);
+
+ while (d->next) {
+ bytes += sizeof(css_selector_detail);
+ d++;
+ }
+
+ s = s->combinator;
+ } while (s != NULL);
+ }
+
+ if (rs->style != NULL)
+ bytes += rs->style->length;
+ } else if (r->type == CSS_RULE_CHARSET) {
+ bytes += sizeof(css_rule_charset);
+ } else if (r->type == CSS_RULE_IMPORT) {
+ bytes += sizeof(css_rule_import);
+ } else if (r->type == CSS_RULE_MEDIA) {
+ const css_rule_media *rm = (const css_rule_media *) r;
+ const css_rule *c;
+
+ bytes += sizeof(css_rule_media);
+
+ /* Process children */
+ for (c = rm->first_child; c != NULL; c = c->next)
+ bytes += _rule_size(c);
+ } else if (r->type == CSS_RULE_FONT_FACE) {
+ const css_rule_font_face *rf = (const css_rule_font_face *) r;
+
+ bytes += sizeof(css_rule_font_face);
+
+ if (rf->style != NULL)
+ bytes += rf->style->length;
+ } else if (r->type == CSS_RULE_PAGE) {
+ const css_rule_page *rp = (const css_rule_page *) r;
+ const css_selector *s = rp->selector;
+
+ /* Process selector chain */
+ while (s != NULL) {
+ const css_selector_detail *d = &s->data;
+
+ bytes += sizeof(css_selector);
+
+ while (d->next) {
+ bytes += sizeof(css_selector_detail);
+ d++;
+ }
+
+ s = s->combinator;
+ }
+
+ if (rp->style != NULL)
+ bytes += rp->style->length;
+ }
+
+ return bytes;
+}
+
diff --git a/src/stylesheet.h b/src/stylesheet.h
index 4ac560c..80b58b0 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -175,6 +175,8 @@ struct css_stylesheet {
bool inline_style; /**< Is an inline style */
+ size_t size; /**< Size, in bytes */
+
css_url_resolution_fn resolve; /**< URL resolution function */
void *resolve_pw; /**< Private word */