summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/stylesheet.c79
-rw-r--r--src/stylesheet.h3
-rw-r--r--src/utils/utils.h4
3 files changed, 72 insertions, 14 deletions
diff --git a/src/stylesheet.c b/src/stylesheet.c
index 9afd5cc..e6d8ea7 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -162,6 +162,7 @@ css_error css_stylesheet_create(css_language_level level,
*/
css_error css_stylesheet_destroy(css_stylesheet *sheet)
{
+ uint32_t bucket;
css_rule *r, *s;
if (sheet == NULL)
@@ -185,6 +186,17 @@ css_error css_stylesheet_destroy(css_stylesheet *sheet)
css_selector_hash_destroy(sheet->selectors);
+ /* Release cached free styles */
+ for (bucket = 0; bucket != N_ELEMENTS(sheet->free_styles); bucket++) {
+ while (sheet->free_styles[bucket] != NULL) {
+ css_style *s = sheet->free_styles[bucket];
+
+ sheet->free_styles[bucket] = s->bytecode;
+
+ sheet->alloc(s, 0, sheet->pw);
+ }
+ }
+
/* These two may have been destroyed when parsing completed */
if (sheet->parser_frontend != NULL)
css_language_destroy(sheet->parser_frontend);
@@ -228,6 +240,7 @@ css_error css_stylesheet_append_data(css_stylesheet *sheet,
css_error css_stylesheet_data_done(css_stylesheet *sheet)
{
const css_rule *r;
+ uint32_t bucket;
css_error error;
if (sheet == NULL)
@@ -247,6 +260,17 @@ css_error css_stylesheet_data_done(css_stylesheet *sheet)
sheet->parser_frontend = NULL;
sheet->parser = NULL;
+ /* Release cached free styles */
+ for (bucket = 0; bucket != N_ELEMENTS(sheet->free_styles); bucket++) {
+ while (sheet->free_styles[bucket] != NULL) {
+ css_style *s = sheet->free_styles[bucket];
+
+ sheet->free_styles[bucket] = s->bytecode;
+
+ sheet->alloc(s, 0, sheet->pw);
+ }
+ }
+
/* Determine if there are any pending imports */
for (r = sheet->rule_list; r != NULL; r = r->next) {
const css_rule_import *i = (const css_rule_import *) r;
@@ -565,13 +589,21 @@ css_error css_stylesheet_style_create(css_stylesheet *sheet, uint32_t len,
css_style **style)
{
css_style *s;
+ const uint32_t alloclen = ((len + 15) & ~15);
+ const uint32_t bucket = (alloclen / N_ELEMENTS(sheet->free_styles)) - 1;
if (sheet == NULL || len == 0 || style == NULL)
return CSS_BADPARM;
- s = sheet->alloc(NULL, sizeof(css_style) + len, sheet->pw);
- if (s == NULL)
- return CSS_NOMEM;
+ if (bucket < N_ELEMENTS(sheet->free_styles) &&
+ sheet->free_styles[bucket] != NULL) {
+ s = sheet->free_styles[bucket];
+ sheet->free_styles[bucket] = s->bytecode;
+ } else {
+ s = sheet->alloc(NULL, sizeof(css_style) + alloclen, sheet->pw);
+ if (s == NULL)
+ return CSS_NOMEM;
+ }
/* DIY variable-sized data member */
s->bytecode = ((uint8_t *) s + sizeof(css_style));
@@ -593,10 +625,20 @@ css_error css_stylesheet_style_create(css_stylesheet *sheet, uint32_t len,
*/
css_error css_stylesheet_style_destroy(css_stylesheet *sheet, css_style *style)
{
+ uint32_t alloclen, bucket;
+
if (sheet == NULL || style == NULL)
return CSS_BADPARM;
- sheet->alloc(style, 0, sheet->pw);
+ alloclen = ((style->length + 15) & ~15);
+ bucket = (alloclen / N_ELEMENTS(sheet->free_styles)) - 1;
+
+ if (bucket < N_ELEMENTS(sheet->free_styles)) {
+ style->bytecode = sheet->free_styles[bucket];
+ sheet->free_styles[bucket] = style;
+ } else {
+ sheet->alloc(style, 0, sheet->pw);
+ }
return CSS_OK;
}
@@ -1067,20 +1109,31 @@ css_error css_stylesheet_rule_append_style(css_stylesheet *sheet,
if (cur != NULL) {
/* Already have a style, so append to the end of the bytecode */
- css_style *temp = sheet->alloc(cur,
- sizeof(css_style) + cur->length + style->length,
- sheet->pw);
- if (temp == NULL)
- return CSS_NOMEM;
+ const uint32_t reqlen = cur->length + style->length;
+ const uint32_t curlen = ((cur->length + 15) & ~15);
+
+ if (curlen < reqlen) {
+ css_style *temp;
+ css_error error;
- /* Ensure bytecode pointer is correct */
- temp->bytecode = ((uint8_t *) temp + sizeof(css_style));
+ error = css_stylesheet_style_create(sheet,
+ reqlen, &temp);
+ if (error != CSS_OK)
+ return error;
+
+ memcpy((uint8_t *) temp->bytecode, cur->bytecode,
+ cur->length);
+ temp->length = cur->length;
+
+ css_stylesheet_style_destroy(sheet, cur);
+
+ cur = temp;
+ }
/** \todo Can we optimise the bytecode here? */
- memcpy((uint8_t *) temp->bytecode + temp->length,
+ memcpy((uint8_t *) cur->bytecode + cur->length,
style->bytecode, style->length);
- cur = temp;
cur->length += style->length;
/* Add this to the sheet's size */
diff --git a/src/stylesheet.h b/src/stylesheet.h
index 1769bff..df095d9 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -24,7 +24,6 @@
typedef struct css_rule css_rule;
typedef struct css_selector css_selector;
-/** \todo would a parserutils_buffer be better here? */
typedef struct css_style {
uint32_t length; /**< Length, in bytes, of bytecode */
void *bytecode; /**< Pointer to bytecode */
@@ -177,6 +176,8 @@ struct css_stylesheet {
size_t size; /**< Size, in bytes */
+ css_style *free_styles[4]; /**< Free styles: 16B buckets */
+
css_url_resolution_fn resolve; /**< URL resolution function */
void *resolve_pw; /**< Private word */
diff --git a/src/utils/utils.h b/src/utils/utils.h
index 1c380f8..26c9a08 100644
--- a/src/utils/utils.h
+++ b/src/utils/utils.h
@@ -30,6 +30,10 @@
#define UNUSED(x) ((x)=(x))
#endif
+#ifndef N_ELEMENTS
+#define N_ELEMENTS(x) (sizeof((x)) / sizeof((x)[0]))
+#endif
+
css_fixed number_from_lwc_string(lwc_string *string, bool int_only,
size_t *consumed);