summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcss/select.h28
-rw-r--r--include/libcss/types.h21
-rw-r--r--src/parse/language.c334
-rw-r--r--src/parse/language.h17
-rw-r--r--src/parse/propstrings.c1
-rw-r--r--src/parse/propstrings.h2
-rw-r--r--src/select/hash.c31
-rw-r--r--src/select/hash.h2
-rw-r--r--src/select/select.c104
-rw-r--r--src/stylesheet.c41
-rw-r--r--src/stylesheet.h6
-rw-r--r--test/dump.h32
-rw-r--r--test/parse-auto.c32
-rw-r--r--test/select-auto.c80
14 files changed, 524 insertions, 207 deletions
diff --git a/include/libcss/select.h b/include/libcss/select.h
index b912fa3..bdc16ac 100644
--- a/include/libcss/select.h
+++ b/include/libcss/select.h
@@ -13,8 +13,6 @@ extern "C"
{
#endif
-#include <libwapcaplet/libwapcaplet.h>
-
#include <libcss/errors.h>
#include <libcss/functypes.h>
#include <libcss/hint.h>
@@ -50,7 +48,7 @@ typedef struct css_select_results {
typedef struct css_select_handler {
css_error (*node_name)(void *pw, void *node,
- lwc_string **name);
+ css_qname *qname);
css_error (*node_classes)(void *pw, void *node,
lwc_string ***classes,
uint32_t *n_classes);
@@ -58,42 +56,42 @@ typedef struct css_select_handler {
lwc_string **id);
css_error (*named_ancestor_node)(void *pw, void *node,
- lwc_string *name, void **ancestor);
+ const css_qname *qname, void **ancestor);
css_error (*named_parent_node)(void *pw, void *node,
- lwc_string *name, void **parent);
+ const css_qname *qname, void **parent);
css_error (*named_sibling_node)(void *pw, void *node,
- lwc_string *name, void **sibling);
+ const css_qname *qname, void **sibling);
css_error (*named_generic_sibling_node)(void *pw, void *node,
- lwc_string *name, void **sibling);
+ const css_qname *qname, void **sibling);
css_error (*parent_node)(void *pw, void *node, void **parent);
css_error (*sibling_node)(void *pw, void *node, void **sibling);
css_error (*node_has_name)(void *pw, void *node,
- lwc_string *name, bool *match);
+ const css_qname *qname, bool *match);
css_error (*node_has_class)(void *pw, void *node,
lwc_string *name, bool *match);
css_error (*node_has_id)(void *pw, void *node,
lwc_string *name, bool *match);
css_error (*node_has_attribute)(void *pw, void *node,
- lwc_string *name, bool *match);
+ const css_qname *qname, bool *match);
css_error (*node_has_attribute_equal)(void *pw, void *node,
- lwc_string *name, lwc_string *value,
+ const css_qname *qname, lwc_string *value,
bool *match);
css_error (*node_has_attribute_dashmatch)(void *pw, void *node,
- lwc_string *name, lwc_string *value,
+ const css_qname *qname, lwc_string *value,
bool *match);
css_error (*node_has_attribute_includes)(void *pw, void *node,
- lwc_string *name, lwc_string *value,
+ const css_qname *qname, lwc_string *value,
bool *match);
css_error (*node_has_attribute_prefix)(void *pw, void *node,
- lwc_string *name, lwc_string *value,
+ const css_qname *qname, lwc_string *value,
bool *match);
css_error (*node_has_attribute_suffix)(void *pw, void *node,
- lwc_string *name, lwc_string *value,
+ const css_qname *qname, lwc_string *value,
bool *match);
css_error (*node_has_attribute_substring)(void *pw, void *node,
- lwc_string *name, lwc_string *value,
+ const css_qname *qname, lwc_string *value,
bool *match);
css_error (*node_is_root)(void *pw, void *node, bool *match);
diff --git a/include/libcss/types.h b/include/libcss/types.h
index 8bc65a9..c8b9cf9 100644
--- a/include/libcss/types.h
+++ b/include/libcss/types.h
@@ -17,6 +17,8 @@ extern "C"
#include <stdint.h>
#include <stdlib.h>
+#include <libwapcaplet/libwapcaplet.h>
+
#include <libcss/fpmath.h>
/**
@@ -100,6 +102,25 @@ typedef enum css_unit {
CSS_UNIT_KHZ = 0xf
} css_unit;
+/**
+ * Type of a qualified name
+ */
+typedef struct css_qname {
+ /**
+ * Namespace URI:
+ *
+ * NULL for no namespace
+ * '*' for any namespace (including none)
+ * URI for a specific namespace
+ */
+ lwc_string *ns;
+
+ /**
+ * Local part of qualified name
+ */
+ lwc_string *name;
+} css_qname;
+
typedef struct css_stylesheet css_stylesheet;
typedef struct css_select_ctx css_select_ctx;
diff --git a/src/parse/language.c b/src/parse/language.c
index ab363bd..5e550b1 100644
--- a/src/parse/language.c
+++ b/src/parse/language.c
@@ -55,6 +55,10 @@ static css_error handleDeclaration(css_language *c,
static css_error parseMediaList(css_language *c,
const parserutils_vector *vector, int *ctx,
uint64_t *media);
+static css_error addNamespace(css_language *c,
+ lwc_string *prefix, lwc_string *uri);
+static css_error lookupNamespace(css_language *c,
+ lwc_string *prefix, lwc_string **uri);
/* Selector list parsing */
static css_error parseClass(css_language *c,
@@ -78,6 +82,9 @@ static css_error parseAppendSpecific(css_language *c,
static css_error parseSelectorSpecifics(css_language *c,
const parserutils_vector *vector, int *ctx,
css_selector **parent);
+static css_error parseTypeSelector(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_qname *qname);
static css_error parseSimpleSelector(css_language *c,
const parserutils_vector *vector, int *ctx,
css_selector **result);
@@ -155,7 +162,10 @@ css_error css__language_create(css_stylesheet *sheet, css_parser *parser,
}
c->sheet = sheet;
- c->state = BEFORE_CHARSET;
+ c->state = CHARSET_PERMITTED;
+ c->default_namespace = NULL;
+ c->namespaces = NULL;
+ c->num_namespaces = 0;
c->alloc = alloc;
c->pw = pw;
@@ -172,11 +182,23 @@ css_error css__language_create(css_stylesheet *sheet, css_parser *parser,
*/
css_error css__language_destroy(css_language *language)
{
- int i;
+ uint32_t i;
if (language == NULL)
return CSS_BADPARM;
+ if (language->default_namespace != NULL)
+ lwc_string_unref(language->default_namespace);
+
+ if (language->namespaces != NULL) {
+ for (i = 0; i < language->num_namespaces; i++) {
+ lwc_string_unref(language->namespaces[i].prefix);
+ lwc_string_unref(language->namespaces[i].uri);
+ }
+
+ language->alloc(language->namespaces, 0, language->pw);
+ }
+
parserutils_stack_destroy(language->context);
for (i = 0; i < LAST_KNOWN; ++i) {
@@ -315,8 +337,8 @@ css_error handleStartRuleset(css_language *c, const parserutils_vector *vector)
return error;
}
- /* Flag that we've had a valid rule, so @import/@charset have
- * no effect. */
+ /* Flag that we've had a valid rule, so @import/@namespace/@charset
+ * have no effect. */
c->state = HAD_RULE;
/* Rule is now owned by the sheet, so no need to destroy it */
@@ -370,7 +392,7 @@ css_error handleStartAtRule(css_language *c, const parserutils_vector *vector)
if (lwc_string_caseless_isequal(atkeyword->idata, c->strings[CHARSET],
&match) == lwc_error_ok && match) {
- if (c->state == BEFORE_CHARSET) {
+ if (c->state == CHARSET_PERMITTED) {
const css_token *charset;
/* any0 = STRING */
@@ -407,14 +429,14 @@ css_error handleStartAtRule(css_language *c, const parserutils_vector *vector)
/* Rule is now owned by the sheet,
* so no need to destroy it */
- c->state = BEFORE_RULES;
+ c->state = IMPORT_PERMITTED;
} else {
return CSS_INVALID;
}
} else if (lwc_string_caseless_isequal(atkeyword->idata,
c->strings[LIBCSS_IMPORT], &match) == lwc_error_ok &&
match) {
- if (c->state != HAD_RULE) {
+ if (c->state <= IMPORT_PERMITTED) {
lwc_string *url;
uint64_t media = 0;
@@ -482,7 +504,43 @@ css_error handleStartAtRule(css_language *c, const parserutils_vector *vector)
/* Rule is now owned by the sheet,
* so no need to destroy it */
- c->state = BEFORE_RULES;
+ c->state = IMPORT_PERMITTED;
+ } else {
+ return CSS_INVALID;
+ }
+ } else if (lwc_string_caseless_isequal(atkeyword->idata,
+ c->strings[NAMESPACE], &match) == lwc_error_ok &&
+ match) {
+ if (c->state <= NAMESPACE_PERMITTED) {
+ lwc_string *prefix = NULL;
+
+ /* any0 = (IDENT ws)? (STRING | URI) ws */
+
+ token = parserutils_vector_iterate(vector, &ctx);
+ if (token == NULL)
+ return CSS_INVALID;
+
+ if (token->type == CSS_TOKEN_IDENT) {
+ prefix = token->idata;
+
+ consumeWhitespace(vector, &ctx);
+
+ token = parserutils_vector_iterate(vector,
+ &ctx);
+ }
+
+ if (token == NULL || (token->type != CSS_TOKEN_STRING &&
+ token->type != CSS_TOKEN_URI)) {
+ return CSS_INVALID;
+ }
+
+ consumeWhitespace(vector, &ctx);
+
+ error = addNamespace(c, prefix, token->idata);
+ if (error != CSS_OK)
+ return error;
+
+ c->state = NAMESPACE_PERMITTED;
} else {
return CSS_INVALID;
}
@@ -728,6 +786,7 @@ css_error handleDeclaration(css_language *c, const parserutils_vector *vector)
/******************************************************************************
* At-rule parsing functions *
******************************************************************************/
+
css_error parseMediaList(css_language *c,
const parserutils_vector *vector, int *ctx,
uint64_t *media)
@@ -807,6 +866,101 @@ css_error parseMediaList(css_language *c,
return CSS_OK;
}
+/**
+ * Add a namespace mapping
+ *
+ * \param c Parsing context to add to
+ * \param prefix Namespace prefix, or NULL for default namespace
+ * \param uri Namespace URI
+ * \return CSS_OK on success, CSS_NOMEM on memory exhaustion.
+ */
+css_error addNamespace(css_language *c, lwc_string *prefix, lwc_string *uri)
+{
+ if (prefix == NULL) {
+ /* Replace default namespace */
+ if (c->default_namespace != NULL)
+ lwc_string_unref(c->default_namespace);
+
+ /* Special case: if new namespace uri is "", use NULL */
+ if (lwc_string_length(uri) == 0)
+ c->default_namespace = NULL;
+ else
+ c->default_namespace = lwc_string_ref(uri);
+ } else {
+ /* Replace, or add mapping */
+ bool match;
+ uint32_t idx;
+
+ for (idx = 0; idx < c->num_namespaces; idx++) {
+ if (lwc_string_isequal(c->namespaces[idx].prefix,
+ prefix, &match) == lwc_error_ok &&
+ match)
+ break;
+ }
+
+ if (idx == c->num_namespaces) {
+ /* Not found, create a new mapping */
+ css_namespace *ns = c->alloc(c->namespaces,
+ sizeof(css_namespace) *
+ (c->num_namespaces + 1),
+ c->pw);
+
+ if (ns == NULL)
+ return CSS_NOMEM;
+
+ ns[idx].prefix = lwc_string_ref(prefix);
+ ns[idx].uri = NULL;
+
+ c->namespaces = ns;
+ c->num_namespaces++;
+ }
+
+ /* Replace namespace URI */
+ if (c->namespaces[idx].uri != NULL)
+ lwc_string_unref(c->namespaces[idx].uri);
+
+ /* Special case: if new namespace uri is "", use NULL */
+ if (lwc_string_length(uri) == 0)
+ c->namespaces[idx].uri = NULL;
+ else
+ c->namespaces[idx].uri = lwc_string_ref(uri);
+ }
+
+ return CSS_OK;
+}
+
+/**
+ * Look up a namespace prefix
+ *
+ * \param c Language parser context
+ * \param prefix Namespace prefix to find, or NULL for none
+ * \param uri Pointer to location to receive namespace URI
+ * \return CSS_OK on success, CSS_INVALID if prefix is not found
+ */
+css_error lookupNamespace(css_language *c, lwc_string *prefix, lwc_string **uri)
+{
+ uint32_t idx;
+ bool match;
+
+ if (prefix == NULL) {
+ *uri = NULL;
+ } else {
+ for (idx = 0; idx < c->num_namespaces; idx++) {
+ if (lwc_string_isequal(c->namespaces[idx].prefix,
+ prefix, &match) == lwc_error_ok &&
+ match)
+ break;
+ }
+
+ if (idx == c->num_namespaces)
+ return CSS_INVALID;
+
+ *uri = c->namespaces[idx].uri;
+ }
+
+ return CSS_OK;
+}
+
/******************************************************************************
* Selector list parsing functions *
******************************************************************************/
@@ -814,6 +968,7 @@ css_error parseMediaList(css_language *c,
css_error parseClass(css_language *c, const parserutils_vector *vector,
int *ctx, css_selector_detail *specific)
{
+ css_qname qname;
css_selector_detail_value detail_value;
const css_token *token;
@@ -828,19 +983,25 @@ css_error parseClass(css_language *c, const parserutils_vector *vector,
detail_value.string = NULL;
+ qname.ns = NULL;
+ qname.name = token->idata;
+
return css__stylesheet_selector_detail_init(c->sheet,
- CSS_SELECTOR_CLASS, token->idata, detail_value,
+ CSS_SELECTOR_CLASS, &qname, detail_value,
CSS_SELECTOR_DETAIL_VALUE_STRING, false, specific);
}
css_error parseAttrib(css_language *c, const parserutils_vector *vector,
int *ctx, css_selector_detail *specific)
{
+ css_qname qname;
css_selector_detail_value detail_value;
- const css_token *token, *name, *value = NULL;
+ const css_token *token, *value = NULL;
css_selector_type type = CSS_SELECTOR_ATTRIBUTE;
+ css_error error;
+ lwc_string *prefix = NULL;
- /* attrib -> '[' ws IDENT ws [
+ /* attrib -> '[' ws namespace_prefix? IDENT ws [
* [ '=' |
* INCLUDES |
* DASHMATCH |
@@ -849,6 +1010,7 @@ css_error parseAttrib(css_language *c, const parserutils_vector *vector,
* SUBSTRINGMATCH
* ] ws
* [ IDENT | STRING ] ws ]? ']'
+ * namespace_prefix -> [ IDENT | '*' ]? '|'
*/
token = parserutils_vector_iterate(vector, ctx);
if (token == NULL || tokenIsChar(token, '[') == false)
@@ -857,10 +1019,34 @@ css_error parseAttrib(css_language *c, const parserutils_vector *vector,
consumeWhitespace(vector, ctx);
token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || (token->type != CSS_TOKEN_IDENT &&
+ tokenIsChar(token, '*') == false &&
+ tokenIsChar(token, '|') == false))
+ return CSS_INVALID;
+
+ if (tokenIsChar(token, '|')) {
+ token = parserutils_vector_iterate(vector, ctx);
+ } else {
+ const css_token *temp;
+
+ temp = parserutils_vector_peek(vector, *ctx);
+ if (temp != NULL && tokenIsChar(temp, '|')) {
+ prefix = token->idata;
+
+ parserutils_vector_iterate(vector, ctx);
+
+ token = parserutils_vector_iterate(vector, ctx);
+ }
+ }
+
if (token == NULL || token->type != CSS_TOKEN_IDENT)
return CSS_INVALID;
- name = token;
+ error = lookupNamespace(c, prefix, &qname.ns);
+ if (error != CSS_OK)
+ return error;
+
+ qname.name = token->idata;
consumeWhitespace(vector, ctx);
@@ -903,7 +1089,7 @@ css_error parseAttrib(css_language *c, const parserutils_vector *vector,
detail_value.string = value != NULL ? value->idata : NULL;
return css__stylesheet_selector_detail_init(c->sheet, type,
- name->idata, detail_value,
+ &qname, detail_value,
CSS_SELECTOR_DETAIL_VALUE_STRING, false, specific);
}
@@ -1151,7 +1337,7 @@ css_error parsePseudo(css_language *c, const parserutils_vector *vector,
css_selector_detail_value detail_value;
css_selector_detail_value_type value_type =
CSS_SELECTOR_DETAIL_VALUE_STRING;
- lwc_string *name;
+ css_qname qname;
const css_token *token;
bool match = false, require_element = false, negate = false;
uint32_t lut_idx;
@@ -1181,11 +1367,12 @@ css_error parsePseudo(css_language *c, const parserutils_vector *vector,
token->type != CSS_TOKEN_FUNCTION))
return CSS_INVALID;
- name = token->idata;
+ qname.ns = NULL;
+ qname.name = token->idata;
/* Search lut for selector type */
for (lut_idx = 0; lut_idx < N_ELEMENTS(pseudo_lut); lut_idx++) {
- if ((lwc_string_caseless_isequal(name,
+ if ((lwc_string_caseless_isequal(qname.name,
c->strings[pseudo_lut[lut_idx].index],
&match) == lwc_error_ok) && match) {
type = pseudo_lut[lut_idx].type;
@@ -1232,22 +1419,24 @@ css_error parsePseudo(css_language *c, const parserutils_vector *vector,
value_type = CSS_SELECTOR_DETAIL_VALUE_NTH;
} else if (fun_type == NOT) {
- /* element_name | specific */
+ /* type_selector | specific */
token = parserutils_vector_peek(vector, *ctx);
if (token == NULL)
return CSS_INVALID;
if (token->type == CSS_TOKEN_IDENT ||
- tokenIsChar(token, '*')) {
- /* Have element name */
- name = token->idata;
+ tokenIsChar(token, '*') ||
+ tokenIsChar(token, '|')) {
+ /* Have type selector */
+ error = parseTypeSelector(c, vector, ctx,
+ &qname);
+ if (error != CSS_OK)
+ return error;
type = CSS_SELECTOR_ELEMENT;
detail_value.string = NULL;
value_type = CSS_SELECTOR_DETAIL_VALUE_STRING;
-
- parserutils_vector_iterate(vector, ctx);
} else {
/* specific */
css_selector_detail det;
@@ -1257,7 +1446,7 @@ css_error parsePseudo(css_language *c, const parserutils_vector *vector,
if (error != CSS_OK)
return error;
- name = det.name;
+ qname = det.qname;
type = det.type;
detail_value = det.value;
value_type = det.value_type;
@@ -1274,7 +1463,8 @@ css_error parsePseudo(css_language *c, const parserutils_vector *vector,
}
return css__stylesheet_selector_detail_init(c->sheet,
- type, name, detail_value, value_type, negate, specific);
+ type, &qname, detail_value, value_type,
+ negate, specific);
}
css_error parseSpecific(css_language *c,
@@ -1291,12 +1481,16 @@ css_error parseSpecific(css_language *c,
return CSS_INVALID;
if (token->type == CSS_TOKEN_HASH) {
+ css_qname qname;
css_selector_detail_value detail_value;
detail_value.string = NULL;
+ qname.ns = NULL;
+ qname.name = token->idata;
+
error = css__stylesheet_selector_detail_init(c->sheet,
- CSS_SELECTOR_ID, token->idata, detail_value,
+ CSS_SELECTOR_ID, &qname, detail_value,
CSS_SELECTOR_DETAIL_VALUE_STRING, false,
specific);
if (error != CSS_OK)
@@ -1359,35 +1553,105 @@ css_error parseSelectorSpecifics(css_language *c,
return CSS_OK;
}
+css_error parseTypeSelector(css_language *c, const parserutils_vector *vector,
+ int *ctx, css_qname *qname)
+{
+ const css_token *token;
+ css_error error;
+ lwc_string *prefix = NULL;
+
+ /* type_selector -> namespace_prefix? element_name
+ * namespace_prefix -> [ IDENT | '*' ]? '|'
+ * element_name -> IDENT | '*'
+ */
+
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL)
+ return CSS_INVALID;
+
+ if (tokenIsChar(token, '|') == false) {
+ prefix = token->idata;
+
+ parserutils_vector_iterate(vector, ctx);
+
+ token = parserutils_vector_peek(vector, *ctx);
+ }
+
+ if (token != NULL && tokenIsChar(token, '|')) {
+ /* Have namespace prefix */
+ parserutils_vector_iterate(vector, ctx);
+
+ /* Expect element_name */
+ token = parserutils_vector_iterate(vector, ctx);
+
+ if (token == NULL || (token->type != CSS_TOKEN_IDENT &&
+ tokenIsChar(token, '*') == false)) {
+ return CSS_INVALID;
+ }
+
+ error = lookupNamespace(c, prefix, &qname->ns);
+ if (error != CSS_OK)
+ return error;
+
+ qname->name = token->idata;
+ } else {
+ /* No namespace prefix */
+ if (c->default_namespace == NULL) {
+ qname->ns = c->strings[UNIVERSAL];
+ } else {
+ qname->ns = c->default_namespace;
+ }
+
+ qname->name = prefix;
+ }
+
+ return CSS_OK;
+}
+
css_error parseSimpleSelector(css_language *c,
const parserutils_vector *vector, int *ctx,
css_selector **result)
{
+ int orig_ctx = *ctx;
css_error error;
const css_token *token;
css_selector *selector;
+ css_qname qname;
- /* simple_selector -> element_name specifics
- * -> specific specifics
- * element_name -> IDENT | '*'
+ /* simple_selector -> type_selector specifics
+ * -> specific specifics
*/
token = parserutils_vector_peek(vector, *ctx);
if (token == NULL)
return CSS_INVALID;
- if (token->type == CSS_TOKEN_IDENT || tokenIsChar(token, '*')) {
- /* Have element name */
- error = css__stylesheet_selector_create(c->sheet,
- token->idata, &selector);
- if (error != CSS_OK)
+ if (token->type == CSS_TOKEN_IDENT || tokenIsChar(token, '*') ||
+ tokenIsChar(token, '|')) {
+ /* Have type selector */
+ error = parseTypeSelector(c, vector, ctx, &qname);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
return error;
+ }
- parserutils_vector_iterate(vector, ctx);
+ error = css__stylesheet_selector_create(c->sheet,
+ &qname, &selector);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
} else {
/* Universal selector */
+ if (c->default_namespace == NULL)
+ qname.ns = c->strings[UNIVERSAL];
+ else
+ qname.ns = c->default_namespace;
+
+ qname.name = c->strings[UNIVERSAL];
+
error = css__stylesheet_selector_create(c->sheet,
- c->strings[UNIVERSAL], &selector);
+ &qname, &selector);
if (error != CSS_OK)
return error;
diff --git a/src/parse/language.h b/src/parse/language.h
index 39b7222..0f1985c 100644
--- a/src/parse/language.h
+++ b/src/parse/language.h
@@ -19,6 +19,14 @@
#include "parse/propstrings.h"
/**
+ * CSS namespace mapping
+ */
+typedef struct css_namespace {
+ lwc_string *prefix; /**< Namespace prefix */
+ lwc_string *uri; /**< Namespace URI */
+} css_namespace;
+
+/**
* Context for a CSS language parser
*/
typedef struct css_language {
@@ -28,8 +36,9 @@ typedef struct css_language {
parserutils_stack *context; /**< Context stack */
enum {
- BEFORE_CHARSET,
- BEFORE_RULES,
+ CHARSET_PERMITTED,
+ IMPORT_PERMITTED,
+ NAMESPACE_PERMITTED,
HAD_RULE
} state; /**< State flag, for at-rule handling */
@@ -37,6 +46,10 @@ typedef struct css_language {
/** Interned strings */
lwc_string *strings[LAST_KNOWN];
+ lwc_string *default_namespace; /**< Default namespace URI */
+ css_namespace *namespaces; /**< Array of namespace mappings */
+ uint32_t num_namespaces; /**< Number of namespace mappings */
+
css_allocator_fn alloc; /**< Memory (de)allocation function */
void *pw; /**< Client's private data */
} css_language;
diff --git a/src/parse/propstrings.c b/src/parse/propstrings.c
index 37ced63..7e15e31 100644
--- a/src/parse/propstrings.c
+++ b/src/parse/propstrings.c
@@ -14,6 +14,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
{ "charset", SLEN("charset") },
{ "import", SLEN("import") },
{ "media", SLEN("media") },
+ { "namespace", SLEN("namespace") },
{ "page", SLEN("page") },
{ "aural", SLEN("aural") },
diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h
index fc91806..25fe113 100644
--- a/src/parse/propstrings.h
+++ b/src/parse/propstrings.h
@@ -15,7 +15,7 @@ enum {
UNIVERSAL,
/* At-rules */
- CHARSET, LIBCSS_IMPORT, MEDIA, PAGE,
+ CHARSET, LIBCSS_IMPORT, MEDIA, NAMESPACE, PAGE,
/* Media types */
AURAL, BRAILLE, EMBOSSED, HANDHELD, PRINT, PROJECTION,
diff --git a/src/select/hash.c b/src/select/hash.c
index 43a696f..e6c6cf8 100644
--- a/src/select/hash.c
+++ b/src/select/hash.c
@@ -202,11 +202,11 @@ css_error css__selector_hash_insert(css_selector_hash *hash,
return CSS_BADPARM;
/* Work out which hash to insert into */
- if (lwc_string_length(selector->data.name) != 1 ||
- lwc_string_data(selector->data.name)[0] != '*') {
+ if (lwc_string_length(selector->data.qname.name) != 1 ||
+ lwc_string_data(selector->data.qname.name)[0] != '*') {
/* Named element */
mask = hash->elements.n_slots - 1;
- index = _hash_name(selector->data.name) & mask;
+ index = _hash_name(selector->data.qname.name) & mask;
error = _insert_into_chain(hash, &hash->elements.slots[index],
selector);
@@ -250,11 +250,11 @@ css_error css__selector_hash_remove(css_selector_hash *hash,
return CSS_BADPARM;
/* Work out which hash to insert into */
- if (lwc_string_length(selector->data.name) != 1 ||
- lwc_string_data(selector->data.name)[0] != '*') {
+ if (lwc_string_length(selector->data.qname.name) != 1 ||
+ lwc_string_data(selector->data.qname.name)[0] != '*') {
/* Named element */
mask = hash->elements.n_slots - 1;
- index = _hash_name(selector->data.name) & mask;
+ index = _hash_name(selector->data.qname.name) & mask;
error = _remove_from_chain(hash, &hash->elements.slots[index],
selector);
@@ -284,7 +284,7 @@ css_error css__selector_hash_remove(css_selector_hash *hash,
* Find the first selector that matches name
*
* \param hash Hash to search
- * \param name Name to match
+ * \param qname Qualified name to match
* \param iterator Pointer to location to receive iterator function
* \param matched Pointer to location to receive selector
* \return CSS_OK on success, appropriate error otherwise
@@ -292,19 +292,19 @@ css_error css__selector_hash_remove(css_selector_hash *hash,
* If nothing matches, CSS_OK will be returned and **matched == NULL
*/
css_error css__selector_hash_find(css_selector_hash *hash,
- lwc_string *name,
+ css_qname *qname,
css_selector_hash_iterator *iterator,
const css_selector ***matched)
{
uint32_t index, mask;
hash_entry *head;
- if (hash == NULL || name == NULL || iterator == NULL || matched == NULL)
+ if (hash == NULL || qname == NULL || iterator == NULL || matched == NULL)
return CSS_BADPARM;
/* Find index */
mask = hash->elements.n_slots - 1;
- index = _hash_name(name) & mask;
+ index = _hash_name(qname->name) & mask;
head = &hash->elements.slots[index];
@@ -315,7 +315,8 @@ css_error css__selector_hash_find(css_selector_hash *hash,
bool match = false;
lerror = lwc_string_caseless_isequal(
- name, head->sel->data.name, &match);
+ qname->name, head->sel->data.qname.name,
+ &match);
if (lerror != lwc_error_ok)
return css_error_from_lwc_error(lerror);
@@ -538,7 +539,7 @@ lwc_string *_class_name(const css_selector *selector)
do {
/* Ignore :not(.class) */
if (detail->type == CSS_SELECTOR_CLASS && detail->negate == 0) {
- name = detail->name;
+ name = detail->qname.name;
break;
}
@@ -565,7 +566,7 @@ lwc_string *_id_name(const css_selector *selector)
do {
/* Ignore :not(#id) */
if (detail->type == CSS_SELECTOR_ID && detail->negate == 0) {
- name = detail->name;
+ name = detail->qname.name;
break;
}
@@ -701,7 +702,7 @@ css_error _iterate_elements(css_selector_hash *hash,
if (hash == NULL || current == NULL || next == NULL)
return CSS_BADPARM;
- name = head->sel->data.name;
+ name = head->sel->data.qname.name;
/* Look for the next selector that matches the key */
for (head = head->next; head != NULL; head = head->next) {
@@ -709,7 +710,7 @@ css_error _iterate_elements(css_selector_hash *hash,
bool match = false;
lerror = lwc_string_caseless_isequal(
- name, head->sel->data.name, &match);
+ name, head->sel->data.qname.name, &match);
if (lerror != lwc_error_ok)
return css_error_from_lwc_error(lerror);
diff --git a/src/select/hash.h b/src/select/hash.h
index c8a3d36..6b55950 100644
--- a/src/select/hash.h
+++ b/src/select/hash.h
@@ -32,7 +32,7 @@ css_error css__selector_hash_remove(css_selector_hash *hash,
const struct css_selector *selector);
css_error css__selector_hash_find(css_selector_hash *hash,
- lwc_string *name,
+ css_qname *qname,
css_selector_hash_iterator *iterator,
const struct css_selector ***matched);
css_error css__selector_hash_find_by_class(css_selector_hash *hash,
diff --git a/src/select/select.c b/src/select/select.c
index ee1ad47..e2b55ee 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -929,7 +929,7 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
const css_stylesheet *sheet, css_select_state *state)
{
static const css_selector *empty_selector = NULL;
- lwc_string *element = NULL;
+ css_qname element = { NULL, NULL };
lwc_string *id = NULL;
lwc_string **classes = NULL;
uint32_t n_classes = 0, i = 0;
@@ -965,7 +965,7 @@ css_error match_selectors_in_sheet(css_select_ctx *ctx,
goto cleanup;
/* Find hash chain that applies to current node */
- error = css__selector_hash_find(sheet->selectors, element,
+ error = css__selector_hash_find(sheet->selectors, &element,
&node_iterator, &node_selectors);
if (error != CSS_OK)
goto cleanup;
@@ -1081,7 +1081,10 @@ cleanup:
if (id != NULL)
lwc_string_unref(id);
- lwc_string_unref(element);
+ if (element.ns != NULL)
+ lwc_string_unref(element.ns);
+ lwc_string_unref(element.name);
+
return error;
}
@@ -1122,7 +1125,8 @@ css_error match_selector_chain(css_select_ctx *ctx,
/* Consider any combinator on this selector */
if (s->data.comb != CSS_COMBINATOR_NONE &&
- s->combinator->data.name != state->universal) {
+ s->combinator->data.qname.name !=
+ state->universal) {
/* Named combinator */
error = match_named_combinator(ctx, s->data.comb,
s->combinator, state, node, &next_node);
@@ -1133,7 +1137,8 @@ css_error match_selector_chain(css_select_ctx *ctx,
if (next_node == NULL)
return CSS_OK;
} else if (s->data.comb != CSS_COMBINATOR_NONE &&
- s->combinator->data.name == state->universal) {
+ s->combinator->data.qname.name ==
+ state->universal) {
/* Universal combinator */
error = match_universal_combinator(ctx, s->data.comb,
s->combinator, state, node, &next_node);
@@ -1187,25 +1192,26 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type,
switch (type) {
case CSS_COMBINATOR_ANCESTOR:
error = state->handler->named_ancestor_node(state->pw,
- n, selector->data.name, &n);
+ n, &selector->data.qname, &n);
if (error != CSS_OK)
return error;
break;
case CSS_COMBINATOR_PARENT:
error = state->handler->named_parent_node(state->pw,
- n, selector->data.name, &n);
+ n, &selector->data.qname, &n);
if (error != CSS_OK)
return error;
break;
case CSS_COMBINATOR_SIBLING:
error = state->handler->named_sibling_node(state->pw,
- n, selector->data.name, &n);
+ n, &selector->data.qname, &n);
if (error != CSS_OK)
return error;
break;
case CSS_COMBINATOR_GENERIC_SIBLING:
error = state->handler->named_generic_sibling_node(
- state->pw, n, selector->data.name, &n);
+ state->pw, n, &selector->data.qname,
+ &n);
if (error != CSS_OK)
return error;
case CSS_COMBINATOR_NONE:
@@ -1358,28 +1364,24 @@ css_error match_detail(css_select_ctx *ctx, void *node,
switch (detail->type) {
case CSS_SELECTOR_ELEMENT:
- if (lwc_string_length(detail->name) == 1 &&
- lwc_string_data(detail->name)[0] == '*') {
- *match = true;
- } else {
- error = state->handler->node_has_name(state->pw, node,
- detail->name, match);
- }
+ error = state->handler->node_has_name(state->pw, node,
+ &detail->qname, match);
break;
case CSS_SELECTOR_CLASS:
error = state->handler->node_has_class(state->pw, node,
- detail->name, match);
+ detail->qname.name, match);
break;
case CSS_SELECTOR_ID:
error = state->handler->node_has_id(state->pw, node,
- detail->name, match);
+ detail->qname.name, match);
break;
case CSS_SELECTOR_PSEUDO_CLASS:
error = state->handler->node_is_root(state->pw, node, &is_root);
if (error != CSS_OK)
return error;
- if (is_root == false && detail->name == state->first_child) {
+ if (is_root == false &&
+ detail->qname.name == state->first_child) {
int32_t num_before = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1387,7 +1389,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
if (error == CSS_OK)
*match = (num_before == 0);
} else if (is_root == false &&
- detail->name == state->nth_child) {
+ detail->qname.name == state->nth_child) {
int32_t num_before = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1399,7 +1401,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
*match = match_nth(a, b, num_before + 1);
}
} else if (is_root == false &&
- detail->name == state->nth_last_child) {
+ detail->qname.name == state->nth_last_child) {
int32_t num_after = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1411,7 +1413,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
*match = match_nth(a, b, num_after + 1);
}
} else if (is_root == false &&
- detail->name == state->nth_of_type) {
+ detail->qname.name == state->nth_of_type) {
int32_t num_before = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1423,7 +1425,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
*match = match_nth(a, b, num_before + 1);
}
} else if (is_root == false &&
- detail->name == state->nth_last_of_type) {
+ detail->qname.name == state->nth_last_of_type) {
int32_t num_after = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1435,7 +1437,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
*match = match_nth(a, b, num_after + 1);
}
} else if (is_root == false &&
- detail->name == state->last_child) {
+ detail->qname.name == state->last_child) {
int32_t num_after = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1443,7 +1445,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
if (error == CSS_OK)
*match = (num_after == 0);
} else if (is_root == false &&
- detail->name == state->first_of_type) {
+ detail->qname.name == state->first_of_type) {
int32_t num_before = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1451,7 +1453,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
if (error == CSS_OK)
*match = (num_before == 0);
} else if (is_root == false &&
- detail->name == state->last_of_type) {
+ detail->qname.name == state->last_of_type) {
int32_t num_after = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1459,7 +1461,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
if (error == CSS_OK)
*match = (num_after == 0);
} else if (is_root == false &&
- detail->name == state->only_child) {
+ detail->qname.name == state->only_child) {
int32_t num_before = 0, num_after = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1473,7 +1475,7 @@ css_error match_detail(css_select_ctx *ctx, void *node,
(num_after == 0);
}
} else if (is_root == false &&
- detail->name == state->only_of_type) {
+ detail->qname.name == state->only_of_type) {
int32_t num_before = 0, num_after = 0;
error = state->handler->node_count_siblings(state->pw,
@@ -1486,39 +1488,39 @@ css_error match_detail(css_select_ctx *ctx, void *node,
*match = (num_before == 0) &&
(num_after == 0);
}
- } else if (detail->name == state->root) {
+ } else if (detail->qname.name == state->root) {
*match = is_root;
- } else if (detail->name == state->empty) {
+ } else if (detail->qname.name == state->empty) {
error = state->handler->node_is_empty(state->pw,
node, match);
- } else if (detail->name == state->link) {
+ } else if (detail->qname.name == state->link) {
error = state->handler->node_is_link(state->pw,
node, match);
- } else if (detail->name == state->visited) {
+ } else if (detail->qname.name == state->visited) {
error = state->handler->node_is_visited(state->pw,
node, match);
- } else if (detail->name == state->hover) {
+ } else if (detail->qname.name == state->hover) {
error = state->handler->node_is_hover(state->pw,
node, match);
- } else if (detail->name == state->active) {
+ } else if (detail->qname.name == state->active) {
error = state->handler->node_is_active(state->pw,
node, match);
- } else if (detail->name == state->focus) {
+ } else if (detail->qname.name == state->focus) {
error = state->handler->node_is_focus(state->pw,
node, match);
- } else if (detail->name == state->target) {
+ } else if (detail->qname.name == state->target) {
error = state->handler->node_is_target(state->pw,
node, match);
- } else if (detail->name == state->lang) {
+ } else if (detail->qname.name == state->lang) {
error = state->handler->node_is_lang(state->pw,
node, detail->value.string, match);
- } else if (detail->name == state->enabled) {
+ } else if (detail->qname.name == state->enabled) {
error = state->handler->node_is_enabled(state->pw,
node, match);
- } else if (detail->name == state->disabled) {
+ } else if (detail->qname.name == state->disabled) {
error = state->handler->node_is_disabled(state->pw,
node, match);
- } else if (detail->name == state->checked) {
+ } else if (detail->qname.name == state->checked) {
error = state->handler->node_is_checked(state->pw,
node, match);
} else
@@ -1527,49 +1529,49 @@ css_error match_detail(css_select_ctx *ctx, void *node,
case CSS_SELECTOR_PSEUDO_ELEMENT:
*match = true;
- if (detail->name == state->first_line) {
+ if (detail->qname.name == state->first_line) {
*pseudo_element = CSS_PSEUDO_ELEMENT_FIRST_LINE;
- } else if (detail->name == state->first_letter) {
+ } else if (detail->qname.name == state->first_letter) {
*pseudo_element = CSS_PSEUDO_ELEMENT_FIRST_LETTER;
- } else if (detail->name == state->before) {
+ } else if (detail->qname.name == state->before) {
*pseudo_element = CSS_PSEUDO_ELEMENT_BEFORE;
- } else if (detail->name == state->after) {
+ } else if (detail->qname.name == state->after) {
*pseudo_element = CSS_PSEUDO_ELEMENT_AFTER;
} else
*match = false;
break;
case CSS_SELECTOR_ATTRIBUTE:
error = state->handler->node_has_attribute(state->pw, node,
- detail->name, match);
+ &detail->qname, match);
break;
case CSS_SELECTOR_ATTRIBUTE_EQUAL:
error = state->handler->node_has_attribute_equal(state->pw,
- node, detail->name, detail->value.string,
+ node, &detail->qname, detail->value.string,
match);
break;
case CSS_SELECTOR_ATTRIBUTE_DASHMATCH:
error = state->handler->node_has_attribute_dashmatch(state->pw,
- node, detail->name, detail->value.string,
+ node, &detail->qname, detail->value.string,
match);
break;
case CSS_SELECTOR_ATTRIBUTE_INCLUDES:
error = state->handler->node_has_attribute_includes(state->pw,
- node, detail->name, detail->value.string,
+ node, &detail->qname, detail->value.string,
match);
break;
case CSS_SELECTOR_ATTRIBUTE_PREFIX:
error = state->handler->node_has_attribute_prefix(state->pw,
- node, detail->name, detail->value.string,
+ node, &detail->qname, detail->value.string,
match);
break;
case CSS_SELECTOR_ATTRIBUTE_SUFFIX:
error = state->handler->node_has_attribute_suffix(state->pw,
- node, detail->name, detail->value.string,
+ node, &detail->qname, detail->value.string,
match);
break;
case CSS_SELECTOR_ATTRIBUTE_SUBSTRING:
error = state->handler->node_has_attribute_substring(state->pw,
- node, detail->name, detail->value.string,
+ node, &detail->qname, detail->value.string,
match);
break;
}
diff --git a/src/stylesheet.c b/src/stylesheet.c
index 382260a..604d824 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -781,18 +781,19 @@ css_error css__stylesheet_style_destroy(css_style *style)
* Create an element selector
*
* \param sheet The stylesheet context
- * \param name Name of selector
+ * \param qname Qualified name of selector
* \param selector Pointer to location to receive selector object
* \return CSS_OK on success,
* CSS_BADPARM on bad parameters,
* CSS_NOMEM on memory exhaustion
*/
css_error css__stylesheet_selector_create(css_stylesheet *sheet,
- lwc_string *name, css_selector **selector)
+ css_qname *qname, css_selector **selector)
{
css_selector *sel;
- if (sheet == NULL || name == NULL || selector == NULL)
+ if (sheet == NULL || qname == NULL || qname->name == NULL ||
+ selector == NULL)
return CSS_BADPARM;
sel = sheet->alloc(NULL, sizeof(css_selector), sheet->pw);
@@ -802,7 +803,11 @@ css_error css__stylesheet_selector_create(css_stylesheet *sheet,
memset(sel, 0, sizeof(css_selector));
sel->data.type = CSS_SELECTOR_ELEMENT;
- sel->data.name = lwc_string_ref(name);
+ if (qname->ns != NULL)
+ sel->data.qname.ns = lwc_string_ref(qname->ns);
+ else
+ sel->data.qname.ns = NULL;
+ sel->data.qname.name = lwc_string_ref(qname->name);
sel->data.value.string = NULL;
sel->data.value_type = CSS_SELECTOR_DETAIL_VALUE_STRING;
@@ -810,8 +815,8 @@ css_error css__stylesheet_selector_create(css_stylesheet *sheet,
sel->specificity = CSS_SPECIFICITY_A;
} else {
/* Initial specificity -- 1 for an element, 0 for universal */
- if (lwc_string_length(name) != 1 ||
- lwc_string_data(name)[0] != '*')
+ if (lwc_string_length(qname->name) != 1 ||
+ lwc_string_data(qname->name)[0] != '*')
sel->specificity = CSS_SPECIFICITY_D;
else
sel->specificity = 0;
@@ -848,7 +853,9 @@ css_error css__stylesheet_selector_destroy(css_stylesheet *sheet,
d = c->combinator;
for (detail = &c->data; detail;) {
- lwc_string_unref(detail->name);
+ if (detail->qname.ns != NULL)
+ lwc_string_unref(detail->qname.ns);
+ lwc_string_unref(detail->qname.name);
if (detail->value_type ==
CSS_SELECTOR_DETAIL_VALUE_STRING &&
@@ -866,7 +873,9 @@ css_error css__stylesheet_selector_destroy(css_stylesheet *sheet,
}
for (detail = &selector->data; detail;) {
- lwc_string_unref(detail->name);
+ if (detail->qname.ns != NULL)
+ lwc_string_unref(detail->qname.ns);
+ lwc_string_unref(detail->qname.name);
if (detail->value_type == CSS_SELECTOR_DETAIL_VALUE_STRING &&
detail->value.string != NULL) {
@@ -891,27 +900,31 @@ css_error css__stylesheet_selector_destroy(css_stylesheet *sheet,
*
* \param sheet The stylesheet context
* \param type The type of selector to create
- * \param name Name of selector
+ * \param qname Qualified name of selector
* \param value Value of selector
* \param value_type Type of \a value
* \param negate Whether the detail match should be negated
* \param detail Pointer to detail object to initialise
* \return CSS_OK on success,
* CSS_BADPARM on bad parameters
+ *
+ * \note No strings are referenced at this point: they will be
+ * referenced when appending the detail to a selector.
*/
css_error css__stylesheet_selector_detail_init(css_stylesheet *sheet,
- css_selector_type type, lwc_string *name,
+ css_selector_type type, css_qname *qname,
css_selector_detail_value value,
css_selector_detail_value_type value_type,
bool negate, css_selector_detail *detail)
{
- if (sheet == NULL || name == NULL || detail == NULL)
+ if (sheet == NULL || qname == NULL || qname->name == NULL ||
+ detail == NULL)
return CSS_BADPARM;
memset(detail, 0, sizeof(css_selector_detail));
detail->type = type;
- detail->name = name;
+ detail->qname = *qname;
detail->value = value;
detail->value_type = value_type;
detail->negate = negate;
@@ -959,7 +972,9 @@ css_error css__stylesheet_selector_append_specific(css_stylesheet *sheet,
(&temp->data)[num_details].next = 1;
/* Ref the strings */
- lwc_string_ref(detail->name);
+ if (detail->qname.ns != NULL)
+ lwc_string_ref(detail->qname.ns);
+ lwc_string_ref(detail->qname.name);
if (detail->value_type == CSS_SELECTOR_DETAIL_VALUE_STRING &&
detail->value.string != NULL)
lwc_string_ref(detail->value.string);
diff --git a/src/stylesheet.h b/src/stylesheet.h
index 9734f02..6333d76 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -69,7 +69,7 @@ typedef union css_selector_detail_value {
} css_selector_detail_value;
typedef struct css_selector_detail {
- lwc_string *name; /**< Interned name */
+ css_qname qname; /**< Interned name */
css_selector_detail_value value; /**< Detail value */
unsigned int type : 4, /**< Type of selector */
@@ -240,12 +240,12 @@ static inline css_error css_stylesheet_style_inherit(css_style *style,
}
css_error css__stylesheet_selector_create(css_stylesheet *sheet,
- lwc_string *name, css_selector **selector);
+ css_qname *qname, css_selector **selector);
css_error css__stylesheet_selector_destroy(css_stylesheet *sheet,
css_selector *selector);
css_error css__stylesheet_selector_detail_init(css_stylesheet *sheet,
- css_selector_type type, lwc_string *name,
+ css_selector_type type, css_qname *qname,
css_selector_detail_value value,
css_selector_detail_value_type value_type,
bool negate, css_selector_detail *detail);
diff --git a/test/dump.h b/test/dump.h
index 85f65b8..e54f3a6 100644
--- a/test/dump.h
+++ b/test/dump.h
@@ -209,30 +209,30 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
switch (detail->type) {
case CSS_SELECTOR_ELEMENT:
- if (lwc_string_length(detail->name) == 1 &&
- lwc_string_data(detail->name)[0] == '*' &&
+ if (lwc_string_length(detail->qname.name) == 1 &&
+ lwc_string_data(detail->qname.name)[0] == '*' &&
detail->next == 0) {
- dump_string(detail->name, ptr);
- } else if (lwc_string_length(detail->name) != 1 ||
- lwc_string_data(detail->name)[0] != '*') {
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
+ } else if (lwc_string_length(detail->qname.name) != 1 ||
+ lwc_string_data(detail->qname.name)[0] != '*') {
+ dump_string(detail->qname.name, ptr);
}
break;
case CSS_SELECTOR_CLASS:
**ptr = '.';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
break;
case CSS_SELECTOR_ID:
**ptr = '#';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
break;
case CSS_SELECTOR_PSEUDO_CLASS:
case CSS_SELECTOR_PSEUDO_ELEMENT:
**ptr = ':';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
if (detail->value_type == CSS_SELECTOR_DETAIL_VALUE_STRING) {
if (detail->value.string != NULL) {
**ptr = '(';
@@ -250,14 +250,14 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
**ptr = ']';
*ptr += 1;
break;
case CSS_SELECTOR_ATTRIBUTE_EQUAL:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '=';
(*ptr)[1] = '"';
*ptr += 2;
@@ -269,7 +269,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_DASHMATCH:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '|';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -282,7 +282,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_INCLUDES:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '~';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -295,7 +295,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_PREFIX:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '^';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -308,7 +308,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_SUFFIX:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '$';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -321,7 +321,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_SUBSTRING:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '*';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
diff --git a/test/parse-auto.c b/test/parse-auto.c
index e050b22..e9fd2e3 100644
--- a/test/parse-auto.c
+++ b/test/parse-auto.c
@@ -651,30 +651,30 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
switch (detail->type) {
case CSS_SELECTOR_ELEMENT:
- if (lwc_string_length(detail->name) == 1 &&
- lwc_string_data(detail->name)[0] == '*' &&
+ if (lwc_string_length(detail->qname.name) == 1 &&
+ lwc_string_data(detail->qname.name)[0] == '*' &&
detail->next == 0) {
- dump_string(detail->name, ptr);
- } else if (lwc_string_length(detail->name) != 1 ||
- lwc_string_data(detail->name)[0] != '*') {
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
+ } else if (lwc_string_length(detail->qname.name) != 1 ||
+ lwc_string_data(detail->qname.name)[0] != '*') {
+ dump_string(detail->qname.name, ptr);
}
break;
case CSS_SELECTOR_CLASS:
**ptr = '.';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
break;
case CSS_SELECTOR_ID:
**ptr = '#';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
break;
case CSS_SELECTOR_PSEUDO_CLASS:
case CSS_SELECTOR_PSEUDO_ELEMENT:
**ptr = ':';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
if (detail->value_type == CSS_SELECTOR_DETAIL_VALUE_STRING) {
if (detail->value.string != NULL) {
**ptr = '(';
@@ -692,14 +692,14 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
**ptr = ']';
*ptr += 1;
break;
case CSS_SELECTOR_ATTRIBUTE_EQUAL:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '=';
(*ptr)[1] = '"';
*ptr += 2;
@@ -711,7 +711,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_DASHMATCH:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '|';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -724,7 +724,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_INCLUDES:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '~';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -737,7 +737,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_PREFIX:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '^';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -750,7 +750,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_SUFFIX:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '$';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
@@ -763,7 +763,7 @@ void dump_selector_detail(css_selector_detail *detail, char **ptr)
case CSS_SELECTOR_ATTRIBUTE_SUBSTRING:
**ptr = '[';
*ptr += 1;
- dump_string(detail->name, ptr);
+ dump_string(detail->qname.name, ptr);
(*ptr)[0] = '*';
(*ptr)[1] = '=';
(*ptr)[2] = '"';
diff --git a/test/select-auto.c b/test/select-auto.c
index 6184a6c..554cc3e 100644
--- a/test/select-auto.c
+++ b/test/select-auto.c
@@ -76,27 +76,27 @@ static void run_test(line_ctx *ctx, const char *exp, size_t explen);
static void destroy_tree(node *root);
static css_error node_name(void *pw, void *node,
- lwc_string **name);
+ css_qname *qname);
static css_error node_classes(void *pw, void *node,
lwc_string ***classes, uint32_t *n_classes);
static css_error node_id(void *pw, void *node,
lwc_string **id);
static css_error named_ancestor_node(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
void **ancestor);
static css_error named_parent_node(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
void **parent);
static css_error named_sibling_node(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
void **sibling);
static css_error named_generic_sibling_node(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
void **sibling);
static css_error parent_node(void *pw, void *node, void **parent);
static css_error sibling_node(void *pw, void *node, void **sibling);
static css_error node_has_name(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
bool *match);
static css_error node_has_class(void *pw, void *node,
lwc_string *name,
@@ -105,30 +105,30 @@ static css_error node_has_id(void *pw, void *node,
lwc_string *name,
bool *match);
static css_error node_has_attribute(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
bool *match);
static css_error node_has_attribute_equal(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match);
static css_error node_has_attribute_dashmatch(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match);
static css_error node_has_attribute_includes(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match);
static css_error node_has_attribute_prefix(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match);
static css_error node_has_attribute_suffix(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match);
static css_error node_has_attribute_substring(void *pw, void *node,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match);
static css_error node_is_root(void *pw, void *node, bool *match);
@@ -785,13 +785,13 @@ void destroy_tree(node *root)
}
-css_error node_name(void *pw, void *n, lwc_string **name)
+css_error node_name(void *pw, void *n, css_qname *qname)
{
node *node = n;
UNUSED(pw);
- *name = lwc_string_ref(node->name);
+ qname->name = lwc_string_ref(node->name);
return CSS_OK;
}
@@ -854,7 +854,7 @@ css_error node_id(void *pw, void *n,
}
css_error named_ancestor_node(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
void **ancestor)
{
node *node = n;
@@ -863,7 +863,8 @@ css_error named_ancestor_node(void *pw, void *n,
for (node = node->parent; node != NULL; node = node->parent) {
bool match;
assert(lwc_string_caseless_isequal(
- name, node->name, &match) == lwc_error_ok);
+ qname->name, node->name,
+ &match) == lwc_error_ok);
if (match == true)
break;
}
@@ -874,7 +875,7 @@ css_error named_ancestor_node(void *pw, void *n,
}
css_error named_parent_node(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
void **parent)
{
node *node = n;
@@ -884,7 +885,7 @@ css_error named_parent_node(void *pw, void *n,
if (node->parent != NULL) {
bool match;
assert(lwc_string_caseless_isequal(
- name, node->parent->name, &match) ==
+ qname->name, node->parent->name, &match) ==
lwc_error_ok);
if (match == true)
*parent = (void *) node->parent;
@@ -894,7 +895,7 @@ css_error named_parent_node(void *pw, void *n,
}
css_error named_sibling_node(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
void **sibling)
{
node *node = n;
@@ -904,7 +905,7 @@ css_error named_sibling_node(void *pw, void *n,
if (node->prev != NULL) {
bool match;
assert(lwc_string_caseless_isequal(
- name, node->prev->name, &match) ==
+ qname->name, node->prev->name, &match) ==
lwc_error_ok);
if (match == true)
*sibling = (void *) node->prev;
@@ -914,7 +915,7 @@ css_error named_sibling_node(void *pw, void *n,
}
css_error named_generic_sibling_node(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
void **sibling)
{
node *node = n;
@@ -923,7 +924,8 @@ css_error named_generic_sibling_node(void *pw, void *n,
for (node = node->prev; node != NULL; node = node->prev) {
bool match;
assert(lwc_string_caseless_isequal(
- name, node->name, &match) == lwc_error_ok);
+ qname->name, node->name,
+ &match) == lwc_error_ok);
if (match == true)
break;
}
@@ -956,14 +958,14 @@ css_error sibling_node(void *pw, void *n, void **sibling)
}
css_error node_has_name(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
bool *match)
{
node *node = n;
UNUSED(pw);
assert(lwc_string_caseless_isequal(node->name,
- name, match) == lwc_error_ok);
+ qname->name, match) == lwc_error_ok);
return CSS_OK;
}
@@ -1021,7 +1023,7 @@ css_error node_has_id(void *pw, void *n,
}
css_error node_has_attribute(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
bool *match)
{
node *node = n;
@@ -1031,7 +1033,7 @@ css_error node_has_attribute(void *pw, void *n,
*match = false;
for (i = 0; i < node->n_attrs; i++) {
assert(lwc_string_caseless_isequal(
- node->attrs[i].name, name, match) ==
+ node->attrs[i].name, qname->name, match) ==
lwc_error_ok);
if (*match == true)
break;
@@ -1041,7 +1043,7 @@ css_error node_has_attribute(void *pw, void *n,
}
css_error node_has_attribute_equal(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match)
{
@@ -1053,7 +1055,7 @@ css_error node_has_attribute_equal(void *pw, void *n,
for (i = 0; i < node->n_attrs; i++) {
assert(lwc_string_caseless_isequal(
- node->attrs[i].name, name, match) ==
+ node->attrs[i].name, qname->name, match) ==
lwc_error_ok);
if (*match == true)
break;
@@ -1069,7 +1071,7 @@ css_error node_has_attribute_equal(void *pw, void *n,
}
css_error node_has_attribute_includes(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match)
{
@@ -1082,7 +1084,7 @@ css_error node_has_attribute_includes(void *pw, void *n,
for (i = 0; i < node->n_attrs; i++) {
assert(lwc_string_caseless_isequal(
- node->attrs[i].name, name, match) ==
+ node->attrs[i].name, qname->name, match) ==
lwc_error_ok);
if (*match == true)
break;
@@ -1115,7 +1117,7 @@ css_error node_has_attribute_includes(void *pw, void *n,
}
css_error node_has_attribute_dashmatch(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match)
{
@@ -1128,7 +1130,7 @@ css_error node_has_attribute_dashmatch(void *pw, void *n,
for (i = 0; i < node->n_attrs; i++) {
assert(lwc_string_caseless_isequal(
- node->attrs[i].name, name, match) ==
+ node->attrs[i].name, qname->name, match) ==
lwc_error_ok);
if (*match == true)
break;
@@ -1161,7 +1163,7 @@ css_error node_has_attribute_dashmatch(void *pw, void *n,
}
css_error node_has_attribute_prefix(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match)
{
@@ -1173,7 +1175,7 @@ css_error node_has_attribute_prefix(void *pw, void *n,
for (i = 0; i < node->n_attrs; i++) {
assert(lwc_string_caseless_isequal(
- node->attrs[i].name, name, match) ==
+ node->attrs[i].name, qname->name, match) ==
lwc_error_ok);
if (*match == true)
break;
@@ -1196,7 +1198,7 @@ css_error node_has_attribute_prefix(void *pw, void *n,
}
css_error node_has_attribute_suffix(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match)
{
@@ -1208,7 +1210,7 @@ css_error node_has_attribute_suffix(void *pw, void *n,
for (i = 0; i < node->n_attrs; i++) {
assert(lwc_string_caseless_isequal(
- node->attrs[i].name, name, match) ==
+ node->attrs[i].name, qname->name, match) ==
lwc_error_ok);
if (*match == true)
break;
@@ -1235,7 +1237,7 @@ css_error node_has_attribute_suffix(void *pw, void *n,
}
css_error node_has_attribute_substring(void *pw, void *n,
- lwc_string *name,
+ const css_qname *qname,
lwc_string *value,
bool *match)
{
@@ -1247,7 +1249,7 @@ css_error node_has_attribute_substring(void *pw, void *n,
for (i = 0; i < node->n_attrs; i++) {
assert(lwc_string_caseless_isequal(
- node->attrs[i].name, name, match) ==
+ node->attrs[i].name, qname->name, match) ==
lwc_error_ok);
if (*match == true)
break;