From: Michael Orlitzky Date: Sat, 14 Oct 2023 15:39:20 +0000 (-0400) Subject: src/svgtiny_css.c: implement node_is_empty() select handler X-Git-Url: http://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=092d632d8f8e3a05e51ed536d01f8598d847ac00;p=libsvgtiny.git src/svgtiny_css.c: implement node_is_empty() select handler --- diff --git a/src/svgtiny_css.c b/src/svgtiny_css.c index ffc9c3e..ebf432d 100644 --- a/src/svgtiny_css.c +++ b/src/svgtiny_css.c @@ -45,6 +45,7 @@ static css_error node_has_attribute_substring(void *pw, void *node, static css_error node_is_root(void *pw, void *node, bool *match); static css_error node_count_siblings(void *pw, void *node, bool same_name, bool after, int32_t *count); +static css_error node_is_empty(void *pw, void *node, bool *is_empty); /** @@ -1363,3 +1364,65 @@ css_error node_count_siblings(void *pw, void *node, return CSS_OK; } + + +/** + * Determine whether or not the given element is empty + * + * An element is "nonempty" if it has a child that is either an + * element node or a text node. + * + * \param pw Pointer to the current SVG parser state + * \param node Libdom SVG node to check for emptiness + * \param is_empty Pointer to the return value + * + * \return CSS_OK on success, or CSS_NOMEM if anything goes wrong + */ +css_error node_is_empty(void *pw, void *node, bool *is_empty) +{ + UNUSED(pw); + dom_node *child; /* current child node pointer */ + dom_node *next; /* next child node pointer */ + dom_node_type type; /* what type of node is "child" */ + dom_exception err; + + /* Assume that it's empty by default */ + *is_empty = true; + + /* Get the given node's first child. Implementation detail: + * this increments the reference counter on the child node. */ + err = dom_node_get_first_child((dom_node *)node, &child); + if (err != DOM_NO_ERR) { + return CSS_NOMEM; + } + + /* And now loop through all children looking for a + * text/element node. If we find one, the original + * node is "nonempty" */ + while (child != NULL) { + err = dom_node_get_node_type(child, &type); + if (err != DOM_NO_ERR) { + dom_node_unref(child); + return CSS_NOMEM; + } + + if (type == DOM_ELEMENT_NODE || type == DOM_TEXT_NODE) { + *is_empty = false; + dom_node_unref(child); + return CSS_OK; + } + + err = dom_node_get_next_sibling(child, &next); + if (err != DOM_NO_ERR) { + dom_node_unref(child); + return CSS_NOMEM; + } + + /* If we're moving to the next node, we can release + * the reference to the current one */ + dom_node_unref(child); + child = next; + } + + return CSS_OK; +}