From 4fccdf18f3956eaab6481597e38efd1939f16f81 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Fri, 12 Oct 2012 16:21:29 +0100 Subject: Move dom walker to utils/libdom.{c|h}. Add a few HTML elements to core strings. --- utils/libdom.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 utils/libdom.c (limited to 'utils/libdom.c') diff --git a/utils/libdom.c b/utils/libdom.c new file mode 100644 index 000000000..7caadc3d5 --- /dev/null +++ b/utils/libdom.c @@ -0,0 +1,164 @@ +/* + * Copyright 2012 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * libdom utilities (implementation). + */ + +#include + +#include "utils/libdom.h" + + +/* exported interface documented in libdom.h */ +bool libdom_treewalk(dom_node *root, + bool (*callback)(dom_node *node, dom_string *name, void *ctx), + void *ctx) +{ + dom_node *node; + bool result = true;; + + node = dom_node_ref(root); /* tree root */ + + while (node != NULL) { + dom_node *next = NULL; + dom_node_type type; + dom_string *name; + 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 */ + 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; + } + + 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; + } + + dom_node_unref(node); + node = next; + } + } + + assert(node != NULL); + + exc = dom_node_get_node_type(node, &type); + if ((exc != DOM_NO_ERR) || (type != DOM_ELEMENT_NODE)) + continue; + + exc = dom_node_get_node_name(node, &name); + if (exc != DOM_NO_ERR) + continue; + + result = callback(node, name, ctx); + + dom_string_unref(name); + + if (result == false) { + break; /* callback caused early termination */ + } + + } + return result; +} + + +/* libdom_treewalk context for libdom_find_element */ +struct find_element_ctx { + lwc_string *search; + dom_node *found; +}; +/* libdom_treewalk callback for libdom_find_element */ +static bool libdom_find_element_callback(dom_node *node, dom_string *name, + void *ctx) +{ + struct find_element_ctx *data = ctx; + + if (dom_string_caseless_lwc_isequal(name, data->search)) { + /* Found element */ + data->found = node; + return false; /* Discontinue search */ + } + + return true; /* Continue search */ +} + + +/* exported interface documented in libdom.h */ +dom_node *libdom_find_element(dom_node *node, lwc_string *element_name) +{ + struct find_element_ctx data; + + assert(element_name != NULL); + + if (node == NULL) + return NULL; + + data.search = element_name; + data.found = NULL; + + libdom_treewalk(node, libdom_find_element_callback, &data); + + return data.found; +} \ No newline at end of file -- cgit v1.2.3