/** * Callback to count a node's siblings. * * \param pw HTML document * \param n DOM node * \param same_name Only count siblings with the same name, or all * \param after Count anteceding instead of preceding siblings * \param count Pointer to location to receive result * \return CSS_OK. * * \post \a count will contain the number of siblings */ css_error node_count_siblings(void *pw, void *n, bool same_name, bool after, int32_t *count) { int32_t cnt = 0; dom_exception exc; dom_string *node_name = NULL; if (same_name) { dom_node *node = n; exc = dom_node_get_node_name(node, &node_name); if ((exc != DOM_NO_ERR) || (node_name == NULL)) { return CSS_NOMEM; } } if (after) { dom_node *node = dom_node_ref(n); dom_node *next; do { exc = dom_node_get_next_sibling(node, &next); if ((exc != DOM_NO_ERR)) break; dom_node_unref(node); node = next; cnt += node_count_siblings_check(node, same_name, node_name); } while (node != NULL); } else { dom_node *node = dom_node_ref(n); dom_node *next; do { exc = dom_node_get_previous_sibling(node, &next); if ((exc != DOM_NO_ERR)) break; dom_node_unref(node); node = next; cnt += node_count_siblings_check(node, same_name, node_name); } while (node != NULL); } if (node_name != NULL) { dom_string_unref(node_name); } *count = cnt; return CSS_OK; }
/** * Get the node in the collection according name * * \param col The collection * \param name The name of target node * \param node The returned node object * \return DOM_NO_ERR on success. */ dom_exception dom_html_collection_named_item(dom_html_collection *col, dom_string *name, struct dom_node **node) { struct dom_node_internal *n = col->root; dom_exception err; while (n != NULL) { if (n->type == DOM_ELEMENT_NODE && col->ic(n, col->ctx) == true) { dom_string *id = NULL; err = _dom_element_get_id((struct dom_element *) n, &id); if (err != DOM_NO_ERR) { return err; } if (id != NULL && dom_string_isequal(name, id)) { *node = (struct dom_node *) n; dom_node_ref(n); dom_string_unref(id); return DOM_NO_ERR; } if (id != NULL) dom_string_unref(id); } /* Depth first iterating */ if (n->first_child != NULL) { n = n->first_child; } else if (n->next != NULL) { n = n->next; } else { /* No children and siblings */ struct dom_node_internal *parent = n->parent; while (parent != col->root && n == parent->last_child) { n = parent; parent = parent->parent; } if (parent == col->root) n = NULL; else n = n->next; } } /* Not found the target node */ *node = NULL; return DOM_NO_ERR; }
static hubbub_error ref_node(void *parser, void *node) { struct dom_node *dnode = (struct dom_node *) node; UNUSED(parser); dom_node_ref(dnode); return HUBBUB_OK; }
/** * Intialiase a dom_html_collection * * \param doc The document * \param col The collection object to be initialised * \param root The root element of the collection * \param ic The callback function used to determin whether certain node * beint32_ts to the collection * \return DOM_NO_ERR on success. */ dom_exception _dom_html_collection_initialise(struct dom_html_document *doc, struct dom_html_collection *col, struct dom_node_internal *root, dom_callback_is_in_collection ic, void *ctx) { assert(doc != NULL); assert(ic != NULL); assert(root != NULL); col->doc = doc; dom_node_ref(doc); col->root = root; dom_node_ref(root); col->ic = ic; col->ctx = ctx; col->refcnt = 1; return DOM_NO_ERR; }
static struct html_stylesheet * html_create_style_element(html_content *c, dom_node *style) { dom_string *val; dom_exception exc; struct html_stylesheet *stylesheets; /* type='text/css', or not present (invalid but common) */ exc = dom_element_get_attribute(style, corestring_dom_type, &val); if (exc == DOM_NO_ERR && val != NULL) { if (!dom_string_caseless_lwc_isequal(val, corestring_lwc_text_css)) { dom_string_unref(val); return NULL; } dom_string_unref(val); } /* media contains 'screen' or 'all' or not present */ exc = dom_element_get_attribute(style, corestring_dom_media, &val); if (exc == DOM_NO_ERR && val != NULL) { if (strcasestr(dom_string_data(val), "screen") == NULL && strcasestr(dom_string_data(val), "all") == NULL) { dom_string_unref(val); return NULL; } dom_string_unref(val); } /* Extend array */ stylesheets = realloc(c->stylesheets, sizeof(struct html_stylesheet) * (c->stylesheet_count + 1)); if (stylesheets == NULL) { content_broadcast_errorcode(&c->base, NSERROR_NOMEM); return false; } c->stylesheets = stylesheets; c->stylesheets[c->stylesheet_count].node = dom_node_ref(style); c->stylesheets[c->stylesheet_count].sheet = NULL; c->stylesheets[c->stylesheet_count].modified = false; c->stylesheet_count++; return c->stylesheets + (c->stylesheet_count - 1); }
/** * Retrieve the doctype of a document * * \param doc The document to retrieve the doctype from * \param result Pointer to location to receive result * \return DOM_NO_ERR. * * The returned node will have its reference count increased. It is * the responsibility of the caller to unref the node once it has * finished with it. */ dom_exception _dom_document_get_doctype(dom_document *doc, dom_document_type **result) { dom_node_internal *c; for (c = doc->base.first_child; c != NULL; c = c->next) { if (c->type == DOM_DOCUMENT_TYPE_NODE) break; } if (c != NULL) dom_node_ref(c); *result = (dom_document_type *) c; return DOM_NO_ERR; }
/** * Retrieve the document element of a document * * \param doc The document to retrieve the document element from * \param result Pointer to location to receive result * \return DOM_NO_ERR. * * The returned node will have its reference count increased. It is * the responsibility of the caller to unref the node once it has * finished with it. */ dom_exception _dom_document_get_document_element(dom_document *doc, dom_element **result) { dom_node_internal *root; /* Find the first element node in child list */ for (root = doc->base.first_child; root != NULL; root = root->next) { if (root->type == DOM_ELEMENT_NODE) break; } if (root != NULL) dom_node_ref(root); *result = (dom_element *) root; return DOM_NO_ERR; }
/** * Get the node with certain index * * \param col The dom_html_collection object * \param index The index number based on zero * \param node The returned node object * \return DOM_NO_ERR on success. */ dom_exception dom_html_collection_item(dom_html_collection *col, uint32_t index, struct dom_node **node) { struct dom_node_internal *n = col->root; uint32_t len = 0; while (n != NULL) { if (n->type == DOM_ELEMENT_NODE && col->ic(n, col->ctx) == true) len++; if (len == index + 1) { dom_node_ref(n); *node = (struct dom_node *) n; return DOM_NO_ERR; } /* Depth first iterating */ if (n->first_child != NULL) { n = n->first_child; } else if (n->next != NULL) { n = n->next; } else { /* No children and siblings */ struct dom_node_internal *parent = n->parent; while (parent != col->root && n == parent->last_child) { n = parent; parent = parent->parent; } if (n == col->root) n = NULL; else n = n->next; } } /* Not find the node */ *node = NULL; return DOM_NO_ERR; }
void list_add(struct list* list, void* data) { struct list_elt* elt = list_new_elt(data); struct list_elt* tail = list->tail; /* if tail was set, make its 'next' ptr point to elt */ if (tail != NULL) { tail->next = elt; } /* make elt the new tail */ list->tail = elt; if (list->head == NULL) { list->head = elt; } /* inc the size of the list */ list->size++; if (list->type == DOM_STRING) dom_string_ref((dom_string *) data); if (list->type == NODE) dom_node_ref(data); }
/** * Create a Hubbub parser instance * * \param params The binding creation parameters * \param parser Pointer to location to recive instance. * \param document Pointer to location to receive document. * \return Error code */ dom_hubbub_error dom_hubbub_parser_create(dom_hubbub_parser_params *params, dom_hubbub_parser **parser, dom_document **document) { dom_hubbub_parser *binding; hubbub_parser_optparams optparams; hubbub_error error; dom_exception err; dom_string *idname = NULL; /* check result parameters */ if (document == NULL) { return DOM_HUBBUB_BADPARM; } if (parser == NULL) { return DOM_HUBBUB_BADPARM; } /* setup binding parser context */ binding = malloc(sizeof(dom_hubbub_parser)); if (binding == NULL) { return DOM_HUBBUB_NOMEM; } binding->parser = NULL; binding->doc = NULL; binding->encoding = params->enc; if (params->enc != NULL) { binding->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_HEADER; } else { binding->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_DETECTED; } binding->complete = false; if (params->msg == NULL) { binding->msg = dom_hubbub_parser_default_msg; } else { binding->msg = params->msg; } binding->mctx = params->ctx; /* ensure script function is valid or use the default */ if (params->script == NULL) { binding->script = dom_hubbub_parser_default_script; } else { binding->script = params->script; } /* create hubbub parser */ error = hubbub_parser_create(binding->encoding, params->fix_enc, dom_hubbub_alloc, NULL, &binding->parser); if (error != HUBBUB_OK) { free(binding); return (DOM_HUBBUB_HUBBUB_ERR | error); } /* create DOM document */ err = dom_implementation_create_document(DOM_IMPLEMENTATION_HTML, NULL, NULL, NULL, params->daf, params->ctx, &binding->doc); if (err != DOM_NO_ERR) { hubbub_parser_destroy(binding->parser); free(binding); return DOM_HUBBUB_DOM; } binding->tree_handler = tree_handler; binding->tree_handler.ctx = (void *)binding; /* set tree handler on parser */ optparams.tree_handler = &binding->tree_handler; hubbub_parser_setopt(binding->parser, HUBBUB_PARSER_TREE_HANDLER, &optparams); /* set document node*/ optparams.document_node = dom_node_ref((struct dom_node *)binding->doc); hubbub_parser_setopt(binding->parser, HUBBUB_PARSER_DOCUMENT_NODE, &optparams); /* set scripting state */ optparams.enable_scripting = params->enable_script; hubbub_parser_setopt(binding->parser, HUBBUB_PARSER_ENABLE_SCRIPTING, &optparams); /* set the document id parameter before the parse so searches * based on id succeed. */ err = dom_string_create_interned((const uint8_t *) "id", SLEN("id"), &idname); if (err != DOM_NO_ERR) { binding->msg(DOM_MSG_ERROR, binding->mctx, "Can't set DOM document id name"); hubbub_parser_destroy(binding->parser); free(binding); return DOM_HUBBUB_DOM; } _dom_document_set_id_name(binding->doc, idname); dom_string_unref(idname); /* set return parameters */ *document = (dom_document *)dom_node_ref(binding->doc); *parser = binding; return DOM_HUBBUB_OK; }
static bool save_complete_libdom_treewalk(dom_node *root, bool (*callback)(dom_node *node, save_complete_event_type event_type, void *ctx), void *ctx) { dom_node *node; node = dom_node_ref(root); /* tree root */ while (node != NULL) { dom_node *next = NULL; dom_exception exc; exc = dom_node_get_first_child(node, &next); if (exc != DOM_NO_ERR) { dom_node_unref(node); break; } if (next != NULL) { /* 1. children */ dom_node_unref(node); node = next; } else { exc = dom_node_get_next_sibling(node, &next); if (exc != DOM_NO_ERR) { dom_node_unref(node); break; } if (next != NULL) { /* 2. siblings */ if (callback(node, EVENT_LEAVE, ctx) == false) { return false; } dom_node_unref(node); node = next; } else { /* 3. ancestor siblings */ while (node != NULL) { exc = dom_node_get_next_sibling(node, &next); if (exc != DOM_NO_ERR) { dom_node_unref(node); node = NULL; break; } if (next != NULL) { dom_node_unref(next); break; } exc = dom_node_get_parent_node(node, &next); if (exc != DOM_NO_ERR) { dom_node_unref(node); node = NULL; break; } if (callback(node, EVENT_LEAVE, ctx) == false) { return false; } dom_node_unref(node); node = next; } if (node == NULL) break; exc = dom_node_get_next_sibling(node, &next); if (exc != DOM_NO_ERR) { dom_node_unref(node); break; } if (callback(node, EVENT_LEAVE, ctx) == false) { return false; } dom_node_unref(node); node = next; } } assert(node != NULL); if (callback(node, EVENT_ENTER, ctx) == false) { return false; /* callback caused early termination */ } } return true; }