From bcb95bf5fa2c5cfd2e7c80f211f7fd6db6ce2f9a Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sat, 12 Mar 2011 17:16:31 +0000 Subject: CSS3 Namespaces svn path=/trunk/libcss/; revision=11972 --- include/libcss/select.h | 28 ++-- include/libcss/types.h | 21 +++ src/parse/language.c | 334 +++++++++++++++++++++++++++++++++++++++++++----- src/parse/language.h | 17 ++- src/parse/propstrings.c | 1 + src/parse/propstrings.h | 2 +- src/select/hash.c | 31 ++--- src/select/hash.h | 2 +- src/select/select.c | 104 +++++++-------- src/stylesheet.c | 41 ++++-- src/stylesheet.h | 6 +- test/dump.h | 32 ++--- test/parse-auto.c | 32 ++--- test/select-auto.c | 80 ++++++------ 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 - #include #include #include @@ -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 #include +#include + #include /** @@ -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 @@ -18,6 +18,14 @@ #include "parse/parse.h" #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 */ @@ -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; -- cgit v1.2.3