r3420 bursa - /trunk/netsurf/image/svg.c
by netsurf@semichrome.net
Author: bursa
Date: Mon Jul 16 00:22:54 2007
New Revision: 3420
URL: http://source.netsurf-browser.org?rev=3420&view=rev
Log:
Add SVG support for a few basic shapes.
Modified:
trunk/netsurf/image/svg.c
Modified: trunk/netsurf/image/svg.c
URL: http://source.netsurf-browser.org/trunk/netsurf/image/svg.c?rev=3420&r1=3...
==============================================================================
--- trunk/netsurf/image/svg.c (original)
+++ trunk/netsurf/image/svg.c Mon Jul 16 00:22:54 2007
@@ -18,16 +18,52 @@
#include <libxml/debugXML.h>
#include "utils/config.h"
#include "content/content.h"
+#include "css/css.h"
#include "desktop/plotters.h"
+#include "desktop/options.h"
#include "image/svg.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utils.h"
-static bool svg_redraw_svg(xmlNode *svg, int x, int y);
-static bool svg_redraw_rect(xmlNode *rect, int x, int y);
-static bool svg_redraw_text(xmlNode *text, int x, int y);
+struct svg_redraw_state {
+ /* screen origin */
+ int origin_x;
+ int origin_y;
+
+ float viewport_width;
+ float viewport_height;
+
+ /* current transformation matrix */
+ struct {
+ float a, b, c, d, e, f;
+ } ctm;
+
+ struct css_style style;
+
+ /* paint attributes */
+ colour fill;
+ colour stroke;
+ int stroke_width;
+};
+
+
+static bool svg_redraw_svg(xmlNode *svg, struct svg_redraw_state state);
+static bool svg_redraw_rect(xmlNode *rect, struct svg_redraw_state state);
+static bool svg_redraw_circle(xmlNode *circle, struct svg_redraw_state state);
+static bool svg_redraw_line(xmlNode *line, struct svg_redraw_state state);
+static bool svg_redraw_text(xmlNode *text, struct svg_redraw_state state);
+static void svg_parse_position_attributes(const xmlNode *node,
+ const struct svg_redraw_state state,
+ float *x, float *y, float *width, float *height);
+static float svg_parse_length(const xmlChar *s, int viewport_size,
+ const struct svg_redraw_state state);
+static void svg_parse_paint_attributes(const xmlNode *node,
+ struct svg_redraw_state *state);
+static void svg_parse_color(const char *s, colour *c);
+static void svg_parse_font_attributes(const xmlNode *node,
+ struct svg_redraw_state *state);
/**
@@ -86,21 +122,13 @@
c->data.svg.svg = svg;
/* get graphic dimensions */
- xmlChar *width = xmlGetProp(svg, "width");
- if (width) {
- c->width = atoi(width);
- xmlFree(width);
- } else {
- c->width = 100;
- }
-
- xmlChar *height = xmlGetProp(svg, "height");
- if (height) {
- c->height = atoi(height);
- xmlFree(height);
- } else {
- c->height = 100;
- }
+ struct svg_redraw_state state;
+ state.viewport_width = w;
+ state.viewport_height = h;
+ float x, y, width, height;
+ svg_parse_position_attributes(svg, state, &x, &y, &width, &height);
+ c->width = width;
+ c->height = height;
/*c->title = malloc(100);
if (c->title)
@@ -123,28 +151,74 @@
{
assert(c->data.svg.svg);
- return svg_redraw_svg(c->data.svg.svg, x, y);
-}
-
-
-/**
- * Redraw a <svg> element node.
- */
-
-bool svg_redraw_svg(xmlNode *svg, int x, int y)
-{
+ struct svg_redraw_state state;
+
+ state.origin_x = x;
+ state.origin_y = y;
+ state.viewport_width = width;
+ state.viewport_height = height;
+ state.ctm.a = 1;
+ state.ctm.b = 0;
+ state.ctm.c = 0;
+ state.ctm.d = 1;
+ state.ctm.e = 0;
+ state.ctm.f = 0;
+ state.style = css_base_style;
+ state.style.font_size.value.length.value = option_font_size * 0.1;
+ state.fill = 0x000000;
+ state.stroke = TRANSPARENT;
+ state.stroke_width = 1;
+
+ return svg_redraw_svg(c->data.svg.svg, state);
+}
+
+
+/**
+ * Redraw a <svg> or <g> element node.
+ */
+
+bool svg_redraw_svg(xmlNode *svg, struct svg_redraw_state state)
+{
+ float x, y;
+
+ svg_parse_position_attributes(svg, state,
+ &x, &y,
+ &state.viewport_width, &state.viewport_height);
+ svg_parse_paint_attributes(svg, &state);
+ svg_parse_font_attributes(svg, &state);
+
+ /* parse viewBox */
+ xmlAttr *view_box = xmlHasProp(svg, (const xmlChar *) "viewBox");
+ if (view_box) {
+ const char *s = (const char *) view_box->children->content;
+ float min_x, min_y, width, height;
+ if (sscanf(s, "%f,%f,%f,%f",
+ &min_x, &min_y, &width, &height) == 4 ||
+ sscanf(s, "%f %f %f %f",
+ &min_x, &min_y, &width, &height) == 4) {
+ state.ctm.a = state.viewport_width / width;
+ state.ctm.d = state.viewport_height / height;
+ state.ctm.e = -min_x;
+ state.ctm.f = -min_y;
+ }
+ }
+
for (xmlNode *child = svg->children; child; child = child->next) {
bool ok = true;
if (child->type == XML_ELEMENT_NODE) {
if (strcmp(child->name, "svg") == 0)
- ok = svg_redraw_svg(child, x, y);
+ ok = svg_redraw_svg(child, state);
else if (strcmp(child->name, "g") == 0)
- ok = svg_redraw_svg(child, x, y);
+ ok = svg_redraw_svg(child, state);
else if (strcmp(child->name, "rect") == 0)
- ok = svg_redraw_rect(child, x, y);
+ ok = svg_redraw_rect(child, state);
+ else if (strcmp(child->name, "circle") == 0)
+ ok = svg_redraw_circle(child, state);
+ else if (strcmp(child->name, "line") == 0)
+ ok = svg_redraw_line(child, state);
else if (strcmp(child->name, "text") == 0)
- ok = svg_redraw_text(child, x, y);
+ ok = svg_redraw_text(child, state);
}
if (!ok)
@@ -159,22 +233,116 @@
* Redraw a <rect> element node.
*/
-bool svg_redraw_rect(xmlNode *rect, int x, int y)
-{
- int width = 0, height = 0;
-
- for (xmlAttr *attr = rect->properties; attr; attr = attr->next) {
- if (strcmp(attr->name, "x") == 0)
- x += atoi(attr->children->content);
- else if (strcmp(attr->name, "y") == 0)
- y += atoi(attr->children->content);
- else if (strcmp(attr->name, "width") == 0)
- width = atoi(attr->children->content);
- else if (strcmp(attr->name, "height") == 0)
- height = atoi(attr->children->content);
- }
-
- return plot.rectangle(x, y, width, height, 5, 0x000000, false, false);
+bool svg_redraw_rect(xmlNode *rect, struct svg_redraw_state state)
+{
+ float x, y, width, height;
+
+ svg_parse_position_attributes(rect, state,
+ &x, &y, &width, &height);
+ svg_parse_paint_attributes(rect, &state);
+
+ int p[8] = { x, y,
+ x + width, y,
+ x + width, y + height,
+ x, y + height };
+ for (unsigned int i = 0; i != 8; i += 2) {
+ p[i] = state.origin_x + state.ctm.a * p[i] +
+ state.ctm.c * p[i+1] + state.ctm.e;
+ p[i+1] = state.origin_y + state.ctm.b * p[i] +
+ state.ctm.d * p[i+1] + state.ctm.f;
+ }
+
+ if (state.fill != TRANSPARENT)
+ if (!plot.polygon(p, 4, state.fill))
+ return false;
+
+ if (state.stroke != TRANSPARENT) {
+ for (unsigned int i = 0; i != 8; i += 2) {
+ if (!plot.line(p[i], p[i+1], p[(i+2)%8], p[(i+3)%8],
+ state.stroke_width, state.stroke,
+ false, false))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Redraw a <circle> element node.
+ */
+
+bool svg_redraw_circle(xmlNode *circle, struct svg_redraw_state state)
+{
+ float x = 0, y = 0, r = 0;
+
+ for (xmlAttr *attr = circle->properties; attr; attr = attr->next) {
+ if (strcmp(attr->name, "cx") == 0)
+ x = svg_parse_length(attr->children->content,
+ state.viewport_width, state);
+ else if (strcmp(attr->name, "cy") == 0)
+ y = svg_parse_length(attr->children->content,
+ state.viewport_height, state);
+ else if (strcmp(attr->name, "r") == 0)
+ r = svg_parse_length(attr->children->content,
+ state.viewport_width, state);
+ }
+ svg_parse_paint_attributes(circle, &state);
+
+ int px = state.origin_x + state.ctm.a * x +
+ state.ctm.c * y + state.ctm.e;
+ int py = state.origin_y + state.ctm.b * x +
+ state.ctm.d * y + state.ctm.f;
+ int pr = r * state.ctm.a;
+
+ if (state.fill != TRANSPARENT)
+ if (!plot.disc(px, py, pr, state.fill, true))
+ return false;
+
+ if (state.stroke != TRANSPARENT)
+ if (!plot.disc(px, py, pr, state.stroke, false))
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Redraw a <line> element node.
+ */
+
+bool svg_redraw_line(xmlNode *line, struct svg_redraw_state state)
+{
+ float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+
+ for (xmlAttr *attr = line->properties; attr; attr = attr->next) {
+ if (strcmp(attr->name, "x1") == 0)
+ x1 = svg_parse_length(attr->children->content,
+ state.viewport_width, state);
+ else if (strcmp(attr->name, "y1") == 0)
+ y1 = svg_parse_length(attr->children->content,
+ state.viewport_height, state);
+ else if (strcmp(attr->name, "x2") == 0)
+ x2 = svg_parse_length(attr->children->content,
+ state.viewport_width, state);
+ else if (strcmp(attr->name, "y2") == 0)
+ y2 = svg_parse_length(attr->children->content,
+ state.viewport_height, state);
+ }
+ svg_parse_paint_attributes(line, &state);
+
+ int px1 = state.origin_x + state.ctm.a * x1 +
+ state.ctm.c * y1 + state.ctm.e;
+ int py1 = state.origin_y + state.ctm.b * x1 +
+ state.ctm.d * y1 + state.ctm.f;
+ int px2 = state.origin_x + state.ctm.a * x2 +
+ state.ctm.c * y2 + state.ctm.e;
+ int py2 = state.origin_y + state.ctm.b * x2 +
+ state.ctm.d * y2 + state.ctm.f;
+
+ return plot.line(px1, py1, px2, py2, state.stroke_width, state.stroke,
+ false, false);
}
@@ -182,25 +350,34 @@
* Redraw a <text> or <tspan> element node.
*/
-bool svg_redraw_text(xmlNode *text, int x, int y)
-{
- for (xmlAttr *attr = text->properties; attr; attr = attr->next) {
- if (strcmp(attr->name, "x") == 0)
- x += atoi(attr->children->content);
- else if (strcmp(attr->name, "y") == 0)
- y += atoi(attr->children->content);
- }
+bool svg_redraw_text(xmlNode *text, struct svg_redraw_state state)
+{
+ float x, y, width, height;
+
+ svg_parse_position_attributes(text, state,
+ &x, &y, &width, &height);
+ svg_parse_font_attributes(text, &state);
+ int px = state.origin_x + state.ctm.a * x +
+ state.ctm.c * y + state.ctm.e;
+ int py = state.origin_y + state.ctm.b * x +
+ state.ctm.d * y + state.ctm.f;
+ state.ctm.e = px - state.origin_x;
+ state.ctm.f = py - state.origin_y;
+
+ struct css_style style = state.style;
+ style.font_size.value.length.value *= state.ctm.a;
for (xmlNode *child = text->children; child; child = child->next) {
bool ok = true;
if (child->type == XML_TEXT_NODE) {
- ok = plot.text(x, y, &css_base_style,
+ ok = plot.text(px, py,
+ &css_base_style,
child->content, strlen(child->content),
0xffffff, 0x000000);
} else if (child->type == XML_ELEMENT_NODE &&
strcmp(child->name, "tspan") == 0) {
- ok = svg_redraw_text(child, x, y);
+ ok = svg_redraw_text(child, state);
}
if (!ok)
@@ -212,6 +389,151 @@
/**
+ * Parse x, y, width, and height attributes, if present.
+ */
+
+void svg_parse_position_attributes(const xmlNode *node,
+ const struct svg_redraw_state state,
+ float *x, float *y, float *width, float *height)
+{
+ *x = 0;
+ *y = 0;
+ *width = state.viewport_width;
+ *height = state.viewport_height;
+
+ for (xmlAttr *attr = node->properties; attr; attr = attr->next) {
+ if (strcmp(attr->name, "x") == 0)
+ *x = svg_parse_length(attr->children->content,
+ state.viewport_width, state);
+ else if (strcmp(attr->name, "y") == 0)
+ *y = svg_parse_length(attr->children->content,
+ state.viewport_height, state);
+ else if (strcmp(attr->name, "width") == 0)
+ *width = svg_parse_length(attr->children->content,
+ state.viewport_width, state);
+ else if (strcmp(attr->name, "height") == 0)
+ *height = svg_parse_length(attr->children->content,
+ state.viewport_height, state);
+ }
+}
+
+
+/**
+ * Parse a length as a number of pixels.
+ */
+
+float svg_parse_length(const xmlChar *s, int viewport_size,
+ const struct svg_redraw_state state)
+{
+ int num_length = strspn(s, "0123456789+-.");
+ const xmlChar *unit = s + num_length;
+ float n = atof((const char *) s);
+ float font_size = css_len2px(&state.style.font_size.value.length, 0);
+
+ if (unit[0] == 0) {
+ return n;
+ } else if (unit[0] == '%') {
+ return n / 100.0 * viewport_size;
+ } else if (unit[0] == 'e' && unit[1] == 'm') {
+ return n * font_size;
+ } else if (unit[0] == 'e' && unit[1] == 'x') {
+ return n / 2.0 * font_size;
+ } else if (unit[0] == 'p' && unit[1] == 'x') {
+ return n;
+ } else if (unit[0] == 'p' && unit[1] == 't') {
+ return n * 1.25;
+ } else if (unit[0] == 'p' && unit[1] == 'c') {
+ return n * 15.0;
+ } else if (unit[0] == 'm' && unit[1] == 'm') {
+ return n * 3.543307;
+ } else if (unit[0] == 'c' && unit[1] == 'm') {
+ return n * 35.43307;
+ } else if (unit[0] == 'i' && unit[1] == 'n') {
+ return n * 90;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Parse paint attributes, if present.
+ */
+
+void svg_parse_paint_attributes(const xmlNode *node,
+ struct svg_redraw_state *state)
+{
+ for (const xmlAttr *attr = node->properties; attr; attr = attr->next) {
+ if (strcmp(attr->name, "fill") == 0)
+ svg_parse_color((const char *) attr->children->content,
+ &state->fill);
+ else if (strcmp(attr->name, "stroke") == 0)
+ svg_parse_color((const char *) attr->children->content,
+ &state->stroke);
+ else if (strcmp(attr->name, "stroke-width") == 0)
+ state->stroke_width = svg_parse_length(
+ attr->children->content,
+ state->viewport_width, *state);
+ }
+}
+
+
+/**
+ * Parse a colour.
+ */
+
+void svg_parse_color(const char *s, colour *c)
+{
+ unsigned int r, g, b;
+ float rf, gf, bf;
+ size_t len = strlen(s);
+
+ if (len == 4 && s[0] == '#') {
+ if (sscanf(s + 1, "%1x%1x%1x", &r, &g, &b) == 3)
+ *c = (b << 20) | (b << 16) |
+ (g << 12) | (g << 8) |
+ (r << 4) | r;
+ } else if (len == 7 && s[0] == '#') {
+ if (sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
+ *c = (b << 16) | (g << 8) | r;
+ } else if (10 <= len && s[0] == 'r' && s[1] == 'g' && s[2] == 'b' &&
+ s[3] == '(' && s[len - 1] == ')') {
+ if (sscanf(s + 4, "%i,%i,%i", &r, &g, &b) == 3)
+ *c = (b << 16) | (g << 8) | r;
+ else if (sscanf(s + 4, "%f%%,%f%%,%f%%", &rf, &gf, &bf) == 3) {
+ b = bf * 255 / 100;
+ g = gf * 255 / 100;
+ r = rf * 255 / 100;
+ *c = (b << 16) | (g << 8) | r;
+ }
+ } else {
+ *c = named_colour(s);
+ }
+}
+
+
+/**
+ * Parse font attributes, if present.
+ */
+
+void svg_parse_font_attributes(const xmlNode *node,
+ struct svg_redraw_state *state)
+{
+ for (const xmlAttr *attr = node->properties; attr; attr = attr->next) {
+ if (strcmp(attr->name, "font-size") == 0) {
+ /*if (css_parse_length(
+ (const char *) attr->children->content,
+ &state->style.font_size.value.length,
+ true, true)) {
+ state->style.font_size.size =
+ CSS_FONT_SIZE_LENGTH;
+ }*/
+ }
+ }
+}
+
+
+/**
* Destroy a CONTENT_SVG and free all resources it owns.
*/
16 years, 2 months
r3419 jmb - in /trunk/dom/test: Makefile binding.c data/binding/ data/binding/staff.xml testutils.h
by netsurf@semichrome.net
Author: jmb
Date: Sun Jul 15 23:09:59 2007
New Revision: 3419
URL: http://source.netsurf-browser.org?rev=3419&view=rev
Log:
Implement TestObject class and other test utilities (testutils.h)
Rudimentary test of libxml binding, so I can see what's needed
Added:
trunk/dom/test/binding.c
trunk/dom/test/data/binding/
trunk/dom/test/data/binding/staff.xml
trunk/dom/test/testutils.h
Modified:
trunk/dom/test/Makefile
Modified: trunk/dom/test/Makefile
URL: http://source.netsurf-browser.org/trunk/dom/test/Makefile?rev=3419&r1=341...
==============================================================================
--- trunk/dom/test/Makefile (original)
+++ trunk/dom/test/Makefile Sun Jul 15 23:09:59 2007
@@ -19,7 +19,8 @@
# test Execute any test cases
# Extend toolchain settings
-CFLAGS += -I${TOP}/src/ -I$(CURDIR)
+CFLAGS += -I${TOP}/src/ -I${TOP}/bindings/xml/ -I$(CURDIR)
+LDFLAGS += `pkg-config --libs libxml-2.0`
# Release output
RELEASE =
@@ -28,7 +29,7 @@
DEBUG =
# Objects
-OBJS =
+OBJS = binding
.PHONY: clean debug export release setup test
@@ -56,5 +57,5 @@
%: %.c
@${ECHO} ${ECHOFLAGS} "==> $<"
@${CC} -c -g ${CFLAGS} -o $@.o $<
- @${LD} -g -o $@ $@.o ${LDFLAGS} -ldom-debug
+ @${LD} -g -o $@ $@.o ${LDFLAGS} -ldom-libxml-debug -ldom-debug
@${RM} ${RMFLAGS} $@.o
Added: trunk/dom/test/binding.c
URL: http://source.netsurf-browser.org/trunk/dom/test/binding.c?rev=3419&view=...
==============================================================================
--- trunk/dom/test/binding.c (added)
+++ trunk/dom/test/binding.c Sun Jul 15 23:09:59 2007
@@ -1,0 +1,29 @@
+#include <dom/dom.h>
+#include "testutils.h"
+
+int main(int argc, char **argv)
+{
+ struct dom_document *doc;
+ struct dom_element *element;
+ struct dom_string *elementName;
+ dom_exception err;
+ TestObject *staff;
+
+ staff = test_object_create(argc, argv, "staff", false);
+ assert(staff != NULL);
+
+ doc = test_object_get_doc(staff);
+ assert(doc != NULL);
+
+ err = dom_document_get_element(doc, &element);
+ assert(err == DOM_NO_ERR);
+ assert(element != NULL);
+
+ err = dom_element_get_tag_name(element, &elementName);
+ assert(err == DOM_NO_ERR);
+ assert(elementName != NULL);
+
+ printf("PASS\n");
+
+ return 0;
+}
Added: trunk/dom/test/data/binding/staff.xml
URL: http://source.netsurf-browser.org/trunk/dom/test/data/binding/staff.xml?r...
==============================================================================
--- trunk/dom/test/data/binding/staff.xml (added)
+++ trunk/dom/test/data/binding/staff.xml Sun Jul 15 23:09:59 2007
@@ -1,0 +1,57 @@
+<?xml version="1.0"?><?TEST-STYLE PIDATA?>
+<!DOCTYPE staff SYSTEM "staff.dtd" [
+ <!ENTITY ent1 "es">
+ <!ENTITY ent2 "1900 Dallas Road">
+ <!ENTITY ent3 "Texas">
+ <!ENTITY ent4 "<entElement domestic='Yes'>Element data</entElement><?PItarget PIdata?>">
+ <!ENTITY ent5 PUBLIC "entityURI" "entityFile" NDATA notation1>
+ <!ENTITY ent1 "This entity should be discarded">
+ <!NOTATION notation1 PUBLIC "notation1File">
+ <!NOTATION notation2 SYSTEM "notation2File">
+]>
+<!-- This is comment number 1.-->
+<staff>
+ <employee>
+ <employeeId>EMP0001</employeeId>
+ <name>Margaret Martin</name>
+ <position>Accountant</position>
+ <salary>56,000</salary>
+ <gender>Female</gender>
+ <address domestic="Yes">1230 North Ave. Dallas, Texas 98551</address>
+ </employee>
+ <employee>
+ <employeeId>EMP0002</employeeId>
+ <name>Martha Raynolds<![CDATA[This is a CDATASection with EntityReference number 2 &ent2;]]>
+<![CDATA[This is an adjacent CDATASection with a reference to a tab &tab;]]></name>
+ <position>Secretary</position>
+ <salary>35,000</salary>
+ <gender>Female</gender>
+ <address domestic="Yes" street="Yes">&ent2; Dallas, &ent3;
+ 98554</address>
+ </employee>
+ <employee>
+ <employeeId>EMP0003</employeeId>
+ <name>Roger
+ Jones</name>
+ <position>Department Manager</position>
+ <salary>100,000</salary>
+ <gender>&ent4;</gender>
+ <address domestic="Yes" street="No">PO Box 27 Irving, texas 98553</address>
+ </employee>
+ <employee>
+ <employeeId>EMP0004</employeeId>
+ <name>Jeny Oconnor</name>
+ <position>Personnel Director</position>
+ <salary>95,000</salary>
+ <gender>Female</gender>
+ <address domestic="Yes" street="Y&ent1;">27 South Road. Dallas, Texas 98556</address>
+ </employee>
+ <employee>
+ <employeeId>EMP0005</employeeId>
+ <name>Robert Myers</name>
+ <position>Computer Specialist</position>
+ <salary>90,000</salary>
+ <gender>male</gender>
+ <address street="Yes">1821 Nordic. Road, Irving Texas 98558</address>
+ </employee>
+ </staff>
Added: trunk/dom/test/testutils.h
URL: http://source.netsurf-browser.org/trunk/dom/test/testutils.h?rev=3419&vie...
==============================================================================
--- trunk/dom/test/testutils.h (added)
+++ trunk/dom/test/testutils.h Sun Jul 15 23:09:59 2007
@@ -1,0 +1,145 @@
+#ifndef dom_test_testutils_h_
+#define dom_test_testutils_h_
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "xmlbinding.h"
+#include "xmlparser.h"
+
+#ifndef UNUSED
+#define UNUSED(x) ((x) = (x))
+#endif
+
+/* Redefine assert, so we can simply use the standard assert mechanism
+ * within testcases and exit with the right output for the testrunner
+ * to do the right thing. */
+void __assert2(const char *expr, const char *function,
+ const char *file, int line);
+
+void __assert2(const char *expr, const char *function,
+ const char *file, int line)
+{
+ UNUSED(function);
+ UNUSED(file);
+
+ printf("FAIL - %s at line %d\n", expr, line);
+
+ exit(EXIT_FAILURE);
+}
+
+#define assert(expr) \
+ ((void) ((expr) || (__assert2 (#expr, __func__, __FILE__, __LINE__), 0)))
+
+static void *myrealloc(void *ptr, size_t len, void *pw)
+{
+ UNUSED(pw);
+
+ return realloc(ptr, len);
+}
+
+typedef struct TestObject {
+ xml_parser *parser;
+ struct dom_document *doc;
+} TestObject;
+
+TestObject *test_object_create(int argc, char **argv,
+ const char *uri, bool will_be_modified);
+struct dom_document *test_object_get_doc(TestObject *obj);
+const char *test_object_get_mimetype(TestObject *obj);
+
+TestObject *test_object_create(int argc, char **argv,
+ const char *uri, bool will_be_modified)
+{
+ static bool xml_parser_initialised;
+
+ char fnbuf[1024];
+#define CHUNK_SIZE 4096
+ uint8_t buf[CHUNK_SIZE];
+ FILE *fp;
+ size_t len;
+ TestObject *ret;
+
+ UNUSED(will_be_modified);
+
+ if (argc != 2) {
+ printf("Usage: %s <datapath>\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (xml_parser_initialised == false) {
+ assert(xml_dom_binding_initialise(myrealloc, NULL) == XML_OK);
+
+ xml_parser_initialised = true;
+ }
+
+ snprintf(fnbuf, sizeof fnbuf, "%s/%s.xml", argv[1], uri);
+
+ ret = malloc(sizeof(TestObject));
+ if (ret == NULL)
+ return NULL;
+
+ ret->parser = xml_parser_create(NULL, "UTF-8", myrealloc, NULL);
+ if (ret->parser == NULL) {
+ free(ret);
+ return NULL;
+ }
+
+ fp = fopen(fnbuf, "r");
+ if (fp == NULL) {
+ xml_parser_destroy(ret->parser);
+ free(ret);
+ return NULL;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ len = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ while (len > CHUNK_SIZE) {
+ fread(buf, 1, CHUNK_SIZE, fp);
+
+ assert(xml_parser_parse_chunk(ret->parser, buf,
+ CHUNK_SIZE) == XML_OK);
+
+ len -= CHUNK_SIZE;
+ }
+
+ if (len > 0) {
+ fread(buf, 1, len, fp);
+
+ assert(xml_parser_parse_chunk(ret->parser, buf,
+ len) == XML_OK);
+
+ len = 0;
+
+ assert(xml_parser_completed(ret->parser) == XML_OK);
+ }
+
+ fclose(fp);
+
+ ret->doc = xml_parser_get_document(ret->parser);
+
+ xml_parser_destroy(ret->parser);
+ ret->parser = NULL;
+
+ return ret;
+
+#undef CHUNK_SIZE
+}
+
+struct dom_document *test_object_get_doc(TestObject *obj)
+{
+ return obj->doc;
+}
+
+const char *test_object_get_mimetype(TestObject *obj)
+{
+ UNUSED(obj);
+
+ return "text/xml";
+}
+
+#endif
16 years, 2 months
r3418 jmb - in /trunk/dom/bindings: Makefile xml/xmlparser.c
by netsurf@semichrome.net
Author: jmb
Date: Sun Jul 15 23:09:07 2007
New Revision: 3418
URL: http://source.netsurf-browser.org?rev=3418&view=rev
Log:
Fix libxml binding buildsystem target filename (previously overwrote core library)
Wrap all libxml SAX callbacks -- if we register our own SAX handler, our own userdata is used, which (obviously) breaks the internal handlers.
Make xml_parser_add_node print the node type being added to the console (this is temporary, while I work out what's needed here).
Modified:
trunk/dom/bindings/Makefile
trunk/dom/bindings/xml/xmlparser.c
Modified: trunk/dom/bindings/Makefile
URL: http://source.netsurf-browser.org/trunk/dom/bindings/Makefile?rev=3418&r1...
==============================================================================
--- trunk/dom/bindings/Makefile (original)
+++ trunk/dom/bindings/Makefile Sun Jul 15 23:09:07 2007
@@ -22,10 +22,10 @@
CFLAGS += -I$(CURDIR)
# Release output
-RELEASE = ${TOP}/${COMPONENT}.a
+RELEASE = ${TOP}/${COMPONENT}-libxml.a
# Debug output
-DEBUG = ${TOP}/${COMPONENT}-debug.a
+DEBUG = ${TOP}/${COMPONENT}-libxml-debug.a
# Objects
OBJS =
Modified: trunk/dom/bindings/xml/xmlparser.c
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlparser.c?rev=...
==============================================================================
--- trunk/dom/bindings/xml/xmlparser.c (original)
+++ trunk/dom/bindings/xml/xmlparser.c Sun Jul 15 23:09:07 2007
@@ -6,6 +6,7 @@
*/
#include <stdbool.h>
+#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/SAX2.h>
@@ -30,6 +31,37 @@
static void xml_parser_add_node(xml_parser *parser, struct dom_node *parent,
xmlNodePtr child);
+static void xml_parser_internal_subset(void *ctx, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID);
+static int xml_parser_is_standalone(void *ctx);
+static int xml_parser_has_internal_subset(void *ctx);
+static int xml_parser_has_external_subset(void *ctx);
+static xmlParserInputPtr xml_parser_resolve_entity(void *ctx,
+ const xmlChar *publicId, const xmlChar *systemId);
+static xmlEntityPtr xml_parser_get_entity(void *ctx, const xmlChar *name);
+static void xml_parser_entity_decl(void *ctx, const xmlChar *name,
+ int type, const xmlChar *publicId, const xmlChar *systemId,
+ xmlChar *content);
+static void xml_parser_notation_decl(void *ctx, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId);
+static void xml_parser_attribute_decl(void *ctx, const xmlChar *elem,
+ const xmlChar *fullname, int type, int def,
+ const xmlChar *defaultValue, xmlEnumerationPtr tree);
+static void xml_parser_element_decl(void *ctx, const xmlChar *name,
+ int type, xmlElementContentPtr content);
+static void xml_parser_unparsed_entity_decl(void *ctx, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId,
+ const xmlChar *notationName);
+static void xml_parser_set_document_locator(void *ctx, xmlSAXLocatorPtr loc);
+static void xml_parser_reference(void *ctx, const xmlChar *name);
+static void xml_parser_characters(void *ctx, const xmlChar *ch, int len);
+static void xml_parser_comment(void *ctx, const xmlChar *value);
+static xmlEntityPtr xml_parser_get_parameter_entity(void *ctx,
+ const xmlChar *name);
+static void xml_parser_cdata_block(void *ctx, const xmlChar *value, int len);
+static void xml_parser_external_subset(void *ctx, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID);
+
/**
* XML parser object
*/
@@ -48,38 +80,38 @@
* SAX callback dispatch table
*/
static xmlSAXHandler sax_handler = {
- .internalSubset = xmlSAX2InternalSubset,
- .isStandalone = xmlSAX2IsStandalone,
- .hasInternalSubset = xmlSAX2HasInternalSubset,
- .hasExternalSubset = xmlSAX2HasExternalSubset,
- .resolveEntity = xmlSAX2ResolveEntity,
- .getEntity = xmlSAX2GetEntity,
- .entityDecl = xmlSAX2EntityDecl,
- .notationDecl = xmlSAX2NotationDecl,
- .attributeDecl = xmlSAX2AttributeDecl,
- .elementDecl = xmlSAX2ElementDecl,
- .unparsedEntityDecl = xmlSAX2UnparsedEntityDecl,
- .setDocumentLocator = xmlSAX2SetDocumentLocator,
+ .internalSubset = xml_parser_internal_subset,
+ .isStandalone = xml_parser_is_standalone,
+ .hasInternalSubset = xml_parser_has_internal_subset,
+ .hasExternalSubset = xml_parser_has_external_subset,
+ .resolveEntity = xml_parser_resolve_entity,
+ .getEntity = xml_parser_get_entity,
+ .entityDecl = xml_parser_entity_decl,
+ .notationDecl = xml_parser_notation_decl,
+ .attributeDecl = xml_parser_attribute_decl,
+ .elementDecl = xml_parser_element_decl,
+ .unparsedEntityDecl = xml_parser_unparsed_entity_decl,
+ .setDocumentLocator = xml_parser_set_document_locator,
.startDocument = xml_parser_start_document,
.endDocument = xml_parser_end_document,
.startElement = NULL,
.endElement = NULL,
- .reference = xmlSAX2Reference,
- .characters = xmlSAX2Characters,
- .ignorableWhitespace = xmlSAX2Characters,
+ .reference = xml_parser_reference,
+ .characters = xml_parser_characters,
+ .ignorableWhitespace = xml_parser_characters,
.processingInstruction = NULL,
- .comment = xmlSAX2Comment,
- .warning = xmlParserWarning,
- .error = xmlParserError,
- .fatalError = xmlParserError,
- .getParameterEntity = xmlSAX2GetParameterEntity,
- .cdataBlock = xmlSAX2CDataBlock,
- .externalSubset = xmlSAX2ExternalSubset,
+ .comment = xml_parser_comment,
+ .warning = NULL,
+ .error = NULL,
+ .fatalError = NULL,
+ .getParameterEntity = xml_parser_get_parameter_entity,
+ .cdataBlock = xml_parser_cdata_block,
+ .externalSubset = xml_parser_external_subset,
.initialized = XML_SAX2_MAGIC,
._private = NULL,
.startElementNs = xml_parser_start_element_ns,
.endElementNs = xml_parser_end_element_ns,
- .serror = NULL,
+ .serror = NULL
};
/**
@@ -108,8 +140,7 @@
return NULL;
parser->xml_ctx =
- xmlCreatePushParserCtxt(&sax_handler, parser, "", 0,
- NULL);
+ xmlCreatePushParserCtxt(&sax_handler, parser, "", 0, NULL);
if (parser->xml_ctx == NULL) {
alloc(parser, 0, pw);
return NULL;
@@ -283,6 +314,10 @@
/* Invoke libxml2's default behaviour */
xmlSAX2EndDocument(parser->xml_ctx);
+
+ /* If there is no document, we can't do anything */
+ if (parser->doc == NULL)
+ return;
/* We need to mirror any child nodes at the end of the list of
* children which occur after the last Element node in the list */
@@ -356,6 +391,10 @@
nb_namespaces, namespaces, nb_attributes,
nb_defaulted, attributes);
+ /* If there is no document, we can't do anything */
+ if (parser->doc == NULL)
+ return;
+
if (parent == NULL) {
/* No parent; use document */
parent = (xmlNodePtr) parser->xml_ctx->myDoc;
@@ -416,6 +455,10 @@
/* Invoke libxml2's default behaviour */
xmlSAX2EndElementNs(parser->xml_ctx, localname, prefix, URI);
+ /* If there is no document, we can't do anything */
+ if (parser->doc == NULL)
+ return;
+
/* We need to mirror any child nodes at the end of the list of
* children which occur after the last Element node in the list */
@@ -452,7 +495,161 @@
{
UNUSED(parser);
UNUSED(parent);
- UNUSED(child);
-
- /** \todo implement */
-}
+
+ switch (child->type) {
+ case XML_ELEMENT_NODE:
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ case XML_DOCUMENT_NODE:
+ case XML_DOCUMENT_TYPE_NODE:
+ case XML_NOTATION_NODE:
+ case XML_DTD_NODE:
+ default:
+ fprintf(stderr, "Unsupported node type: %d\n", child->type);
+ }
+}
+
+/* */
+/* ------------------------------------------------------------------------*/
+/* */
+void xml_parser_internal_subset(void *ctx, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2InternalSubset(parser->xml_ctx, name, ExternalID, SystemID);
+}
+
+int xml_parser_is_standalone(void *ctx)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ return xmlSAX2IsStandalone(parser->xml_ctx);
+}
+
+int xml_parser_has_internal_subset(void *ctx)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ return xmlSAX2HasInternalSubset(parser->xml_ctx);
+}
+
+int xml_parser_has_external_subset(void *ctx)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ return xmlSAX2HasExternalSubset(parser->xml_ctx);
+}
+
+xmlParserInputPtr xml_parser_resolve_entity(void *ctx,
+ const xmlChar *publicId, const xmlChar *systemId)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ return xmlSAX2ResolveEntity(parser->xml_ctx, publicId, systemId);
+}
+
+xmlEntityPtr xml_parser_get_entity(void *ctx, const xmlChar *name)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ return xmlSAX2GetEntity(parser->xml_ctx, name);
+}
+
+void xml_parser_entity_decl(void *ctx, const xmlChar *name,
+ int type, const xmlChar *publicId, const xmlChar *systemId,
+ xmlChar *content)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2EntityDecl(parser->xml_ctx, name, type, publicId, systemId,
+ content);
+}
+
+void xml_parser_notation_decl(void *ctx, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2NotationDecl(parser->xml_ctx, name, publicId, systemId);
+}
+
+void xml_parser_attribute_decl(void *ctx, const xmlChar *elem,
+ const xmlChar *fullname, int type, int def,
+ const xmlChar *defaultValue, xmlEnumerationPtr tree)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2AttributeDecl(parser->xml_ctx, elem, fullname, type, def,
+ defaultValue, tree);
+}
+
+void xml_parser_element_decl(void *ctx, const xmlChar *name,
+ int type, xmlElementContentPtr content)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2ElementDecl(parser->xml_ctx, name, type, content);
+}
+
+void xml_parser_unparsed_entity_decl(void *ctx, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId,
+ const xmlChar *notationName)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2UnparsedEntityDecl(parser->xml_ctx, name, publicId,
+ systemId, notationName);
+}
+
+void xml_parser_set_document_locator(void *ctx, xmlSAXLocatorPtr loc)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2SetDocumentLocator(parser->xml_ctx, loc);
+}
+
+void xml_parser_reference(void *ctx, const xmlChar *name)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2Reference(parser->xml_ctx, name);
+}
+
+void xml_parser_characters(void *ctx, const xmlChar *ch, int len)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2Characters(parser->xml_ctx, ch, len);
+}
+
+void xml_parser_comment(void *ctx, const xmlChar *value)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2Comment(parser->xml_ctx, value);
+}
+
+xmlEntityPtr xml_parser_get_parameter_entity(void *ctx, const xmlChar *name)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ return xmlSAX2GetParameterEntity(parser->xml_ctx, name);
+}
+
+void xml_parser_cdata_block(void *ctx, const xmlChar *value, int len)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2CDataBlock(parser->xml_ctx, value, len);
+}
+
+void xml_parser_external_subset(void *ctx, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ xmlSAX2ExternalSubset(parser->xml_ctx, name, ExternalID, SystemID);
+}
16 years, 2 months
r3417 bursa - /trunk/netsurf/riscos/gui.c
by netsurf@semichrome.net
Author: bursa
Date: Sun Jul 15 18:20:25 2007
New Revision: 3417
URL: http://source.netsurf-browser.org?rev=3417&view=rev
Log:
Remove dead code at the end of ro_gui_default_language().
Modified:
trunk/netsurf/riscos/gui.c
Modified: trunk/netsurf/riscos/gui.c
URL: http://source.netsurf-browser.org/trunk/netsurf/riscos/gui.c?rev=3417&r1=...
==============================================================================
--- trunk/netsurf/riscos/gui.c (original)
+++ trunk/netsurf/riscos/gui.c Sun Jul 15 18:20:25 2007
@@ -3,7 +3,7 @@
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
* Copyright 2003 Phil Mellor <monkeyson(a)users.sourceforge.net>
- * Copyright 2004 James Bursa <bursa(a)users.sourceforge.net>
+ * Copyright 2004-2007 James Bursa <bursa(a)users.sourceforge.net>
* Copyright 2003 John M Bell <jmb202(a)ecs.soton.ac.uk>
* Copyright 2005 Richard Wilson <info(a)tinct.net>
* Copyright 2004 Andrew Timmins <atimmins(a)blueyonder.co.uk>
@@ -21,24 +21,24 @@
#include <features.h>
#include <unixlib/local.h>
#include <unixlib/sigstate.h>
-#include "curl/curl.h"
-#include "oslib/font.h"
-#include "oslib/help.h"
-#include "oslib/hourglass.h"
-#include "oslib/inetsuite.h"
-#include "oslib/os.h"
-#include "oslib/osbyte.h"
-#include "oslib/osfile.h"
-#include "oslib/osfscontrol.h"
-#include "oslib/osgbpb.h"
-#include "oslib/osmodule.h"
+#include <curl/curl.h>
+#include <oslib/font.h>
+#include <oslib/help.h>
+#include <oslib/hourglass.h>
+#include <oslib/inetsuite.h>
+#include <oslib/os.h>
+#include <oslib/osbyte.h>
+#include <oslib/osfile.h>
+#include <oslib/osfscontrol.h>
+#include <oslib/osgbpb.h>
+#include <oslib/osmodule.h>
#include <oslib/osspriteop.h>
-#include "oslib/pdriver.h"
-#include "oslib/plugin.h"
-#include "oslib/wimp.h"
-#include "oslib/wimpspriteop.h"
-#include "oslib/uri.h"
-#include "rufl.h"
+#include <oslib/pdriver.h>
+#include <oslib/plugin.h>
+#include <oslib/wimp.h>
+#include <oslib/wimpspriteop.h>
+#include <oslib/uri.h>
+#include <rufl.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/urldb.h"
@@ -579,9 +579,11 @@
}
option_language = strdup(ro_gui_default_language());
- assert(option_language);
+ if (!option_language)
+ die("Out of memory");
option_accept_language = strdup(option_language);
- assert(option_accept_language);
+ if (!option_accept_language)
+ die("Out of memory");
}
@@ -591,7 +593,9 @@
* RISC OS has no standard way of determining which language the user prefers.
* We have to guess from the 'Country' setting.
*/
-const char *ro_gui_default_language(void) {
+
+const char *ro_gui_default_language(void)
+{
char path[40];
const char *lang;
int country;
@@ -625,10 +629,6 @@
if (is_dir(path))
return lang;
return "en";
- option_language = strdup("en");
- assert(option_language);
- if (!option_accept_language)
- option_accept_language = strdup(option_language);
}
16 years, 2 months
r3416 jmb - /trunk/dom/bindings/xml/xmlparser.c
by netsurf@semichrome.net
Author: jmb
Date: Sun Jul 15 16:03:35 2007
New Revision: 3416
URL: http://source.netsurf-browser.org?rev=3416&view=rev
Log:
Further libxml binding work.
Modified:
trunk/dom/bindings/xml/xmlparser.c
Modified: trunk/dom/bindings/xml/xmlparser.c
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlparser.c?rev=...
==============================================================================
--- trunk/dom/bindings/xml/xmlparser.c (original)
+++ trunk/dom/bindings/xml/xmlparser.c Sun Jul 15 16:03:35 2007
@@ -18,11 +18,17 @@
#include "utils.h"
static void xml_parser_start_document(void *ctx);
+static void xml_parser_end_document(void *ctx);
static void xml_parser_start_element_ns(void *ctx, const xmlChar *localname,
const xmlChar *prefix, const xmlChar *URI,
int nb_namespaces, const xmlChar **namespaces,
int nb_attributes, int nb_defaulted,
const xmlChar **attributes);
+static void xml_parser_end_element_ns(void *ctx, const xmlChar *localname,
+ const xmlChar *prefix, const xmlChar *URI);
+
+static void xml_parser_add_node(xml_parser *parser, struct dom_node *parent,
+ xmlNodePtr child);
/**
* XML parser object
@@ -55,7 +61,7 @@
.unparsedEntityDecl = xmlSAX2UnparsedEntityDecl,
.setDocumentLocator = xmlSAX2SetDocumentLocator,
.startDocument = xml_parser_start_document,
- .endDocument = xmlSAX2EndDocument,
+ .endDocument = xml_parser_end_document,
.startElement = NULL,
.endElement = NULL,
.reference = xmlSAX2Reference,
@@ -72,7 +78,7 @@
.initialized = XML_SAX2_MAGIC,
._private = NULL,
.startElementNs = xml_parser_start_element_ns,
- .endElementNs = xmlSAX2EndElementNs,
+ .endElementNs = xml_parser_end_element_ns,
.serror = NULL,
};
@@ -263,6 +269,64 @@
}
/**
+ * Handle a document end SAX event
+ *
+ * \param ctx The callback context
+ */
+void xml_parser_end_document(void *ctx)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+ struct dom_string *key;
+ xmlNodePtr node;
+ xmlNodePtr n;
+ dom_exception err;
+
+ /* Invoke libxml2's default behaviour */
+ xmlSAX2EndDocument(parser->xml_ctx);
+
+ /* We need to mirror any child nodes at the end of the list of
+ * children which occur after the last Element node in the list */
+
+ /* Create key */
+ err = dom_string_create_from_const_ptr(parser->doc,
+ (const uint8_t *) "__xmlnode", SLEN("__xmlnode"),
+ &key);
+ if (err != DOM_NO_ERR)
+ return;
+
+ /* Get XML node */
+ err = dom_node_get_user_data((struct dom_node *) parser->doc, key,
+ (void **) &node);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(key);
+ return;
+ }
+
+ /* No longer need key */
+ dom_string_unref(key);
+
+ /* Find last Element node, if any */
+ for (n = node->last; n != NULL; n = n->prev) {
+ if (n->type == XML_ELEMENT_NODE)
+ break;
+ }
+
+ if (n == NULL) {
+ /* No Element node found; entire list needs mirroring */
+ n = node->children;
+ } else {
+ /* Found last Element; skip over it */
+ n = n->next;
+ }
+
+ /* Now, mirror nodes in the DOM */
+ for (; n != NULL; n = n->next) {
+ xml_parser_add_node(parser,
+ (struct dom_node *) node->_private, n);
+ }
+}
+
+/**
* Handle an element open SAX event
*
* \param ctx The callback context
@@ -271,10 +335,12 @@
* \param URI The element namespace URI
* \param nb_namespaces The number of namespace definitions
* \param namespaces Array of nb_namespaces prefix/URI pairs
- * \param nb_attributes The number of attributes
+ * \param nb_attributes The total number of attributes
* \param nb_defaulted The number of defaulted attributes
- * \param attributes Array of [nb_attributes + nb_defaulted] attribute
- * values
+ * \param attributes Array of nb_attributes attribute values
+ *
+ * The number of non-defaulted attributes is ::nb_attributes - ::nb_defaulted
+ * The defaulted attributes are at the end of the array ::attributes.
*/
void xml_parser_start_element_ns(void *ctx, const xmlChar *localname,
const xmlChar *prefix, const xmlChar *URI,
@@ -283,12 +349,110 @@
const xmlChar **attributes)
{
xml_parser *parser = (xml_parser *) ctx;
+ xmlNodePtr parent = parser->xml_ctx->node;
/* Invoke libxml2's default behaviour */
xmlSAX2StartElementNs(parser->xml_ctx, localname, prefix, URI,
nb_namespaces, namespaces, nb_attributes,
nb_defaulted, attributes);
- /** \todo mirror the xml tree in the DOM */
-}
-
+ if (parent == NULL) {
+ /* No parent; use document */
+ parent = (xmlNodePtr) parser->xml_ctx->myDoc;
+ }
+
+ if (parent->type == XML_DOCUMENT_NODE ||
+ parent->type == XML_ELEMENT_NODE) {
+ /* Mirror in the DOM all children of the parent node
+ * between the previous Element child (or the start,
+ * whichever is encountered first) and the Element
+ * just created */
+ xmlNodePtr n;
+
+ /* Find previous element node, if any */
+ for (n = parser->xml_ctx->node->prev; n != NULL;
+ n = n->prev) {
+ if (n->type == XML_ELEMENT_NODE)
+ break;
+ }
+
+ if (n == NULL) {
+ /* No previous Element; use parent's children */
+ n = parent->children;
+ } else {
+ /* Previous Element; skip over it */
+ n = n->next;
+ }
+
+ /* Now, mirror nodes in the DOM */
+ for (; n != parser->xml_ctx->node; n = n->next) {
+ xml_parser_add_node(parser,
+ (struct dom_node *) parent->_private,
+ n);
+ }
+ }
+
+ /* Mirror the created node and its attributes in the DOM */
+ xml_parser_add_node(parser, (struct dom_node *) parent->_private,
+ parser->xml_ctx->node);
+
+}
+
+/**
+ * Handle an element close SAX event
+ *
+ * \param ctx The callback context
+ * \param localname The local name of the element
+ * \param prefix The element namespace prefix
+ * \param URI The element namespace URI
+ */
+void xml_parser_end_element_ns(void *ctx, const xmlChar *localname,
+ const xmlChar *prefix, const xmlChar *URI)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+ xmlNodePtr node = parser->xml_ctx->node;
+ xmlNodePtr n;
+
+ /* Invoke libxml2's default behaviour */
+ xmlSAX2EndElementNs(parser->xml_ctx, localname, prefix, URI);
+
+ /* We need to mirror any child nodes at the end of the list of
+ * children which occur after the last Element node in the list */
+
+ /* Find last Element node, if any */
+ for (n = node->last; n != NULL; n = n->prev) {
+ if (n->type == XML_ELEMENT_NODE)
+ break;
+ }
+
+ if (n == NULL) {
+ /* No Element node found; entire list needs mirroring */
+ n = node->children;
+ } else {
+ /* Found last Element; skip over it */
+ n = n->next;
+ }
+
+ /* Now, mirror nodes in the DOM */
+ for (; n != NULL; n = n->next) {
+ xml_parser_add_node(parser,
+ (struct dom_node *) node->_private, n);
+ }
+}
+
+/**
+ * Add a node to the DOM
+ *
+ * \param parser The parser context
+ * \param parent The parent DOM node
+ * \param child The xmlNode to mirror in the DOM as a child of parent
+ */
+void xml_parser_add_node(xml_parser *parser, struct dom_node *parent,
+ xmlNodePtr child)
+{
+ UNUSED(parser);
+ UNUSED(parent);
+ UNUSED(child);
+
+ /** \todo implement */
+}
16 years, 2 months
r3415 jshaw - /trunk/dom/test/test-to-c.xsl
by netsurf@semichrome.net
Author: jshaw
Date: Sun Jul 15 16:02:37 2007
New Revision: 3415
URL: http://source.netsurf-browser.org?rev=3415&view=rev
Log:
Implement <load>. Extend <assertEquals> to handle equality test for
ints. Extend convert_var_type and convert_attribute_name in order to
generate the documentcreateelement test.
Modified:
trunk/dom/test/test-to-c.xsl
Modified: trunk/dom/test/test-to-c.xsl
URL: http://source.netsurf-browser.org/trunk/dom/test/test-to-c.xsl?rev=3415&r...
==============================================================================
--- trunk/dom/test/test-to-c.xsl (original)
+++ trunk/dom/test/test-to-c.xsl Sun Jul 15 16:02:37 2007
@@ -69,6 +69,11 @@
</xsl:template>
<xsl:template match="*[local-name() = 'test']">
+<xsl:text>#include <dom/dom.h>
+#include "testutils.h"
+
+</xsl:text>
+
<xsl:apply-templates select="*[local-name() = 'metadata']"/>
<xsl:text>
int main(int argc, char **argv)
@@ -82,8 +87,18 @@
</xsl:text>
</xsl:template>
+<xsl:template match="comment()[contains(., 'Copyright')]">
+/*
+This source file was generated by test-to-c.xsl
+and is a derived work from the source document.
+The source document contained the following notice:
+
+<xsl:value-of select="."/>
+*/
+</xsl:template>
+
<xsl:template match="*[local-name() = 'metadata']">
- <xsl:text>/**
+<xsl:text>/**
</xsl:text>
<xsl:call-template name="emit-description">
<xsl:with-param name="description" select="translate(*[local-name() = 'description'], '	', ' ')"/>
@@ -92,7 +107,29 @@
</xsl:template>
<!-- swallowing templates in body mode -->
-<xsl:template match="*[local-name()='metadata']" mode="body"/>
+<xsl:template match="*[local-name() = 'metadata']" mode="body"/>
+
+<xsl:template match="*[local-name() = 'load']" mode="body">
+ <!--
+ TODO: need to handle the case where we load more than one testObject.
+ append a counter to the variable name?
+ -->
+ <xsl:text>
+ TestObject testObject = test_object_create(argc, argv, "</xsl:text><xsl:value-of select="@href"/><xsl:text>.xml", false);
+ assert(testObject != NULL);
+
+ </xsl:text><xsl:value-of select="@var"/><xsl:text> = test_object_get_doc(testObject);
+ assert(</xsl:text><xsl:value-of select="@var"/><xsl:text> != NULL);
+</xsl:text>
+</xsl:template>
+
+<!--
+not sure what <contentType> is used for,
+but it's implemented in subclasses of DOMTestDocumentBuilderFactory.getContentType()
+-->
+<xsl:template match="*[local-name() = 'contentType']" mode="body">
+ <xsl:text>strcmp(test_object_get_mimetype(testObject), "</xsl:text><xsl:value-of select="@type"/><xsl:text>") == 0</xsl:text>
+</xsl:template>
<!--
================================
@@ -113,9 +150,9 @@
<xsl:text> }</xsl:text>
<xsl:for-each select="*[local-name() = 'else']">
<xsl:text> else {
- </xsl:text>
+</xsl:text>
<xsl:apply-templates mode="body"/>
- <xsl:text>}</xsl:text>
+ <xsl:text> }</xsl:text>
</xsl:for-each>
<xsl:text>
</xsl:text>
@@ -126,10 +163,6 @@
DOM templates
================================
-->
-
-<xsl:template match="*[local-name() = 'contentType']" mode="body">
- <xsl:text>strcmp(TODO, "</xsl:text><xsl:value-of select="@type"/><xsl:text>") == 0</xsl:text>
-</xsl:template>
<xsl:template name="produce-method">
<!-- TODO: implement me -->
@@ -207,21 +240,43 @@
</xsl:template>
<xsl:template match="*[local-name() = 'assertEquals']" mode="body">
- <!--
- TODO: this is hard, because we need to know what the types of the objects are
- that we're comparing
- -->
<xsl:variable name="actual" select="@actual"/>
<xsl:variable name="var_type" select="//*[local-name() = 'var' and @name = $actual]/@type"/>
+ <!-- implement equality test depending upon $var_type -->
<xsl:choose>
<xsl:when test="$var_type = 'DOMString'">
- <xsl:text> struct dom_string *match;
- err = dom_string_create_from_const_ptr(doc <!-- TODO: how do we obtain a handle to doc? We could lookup //var[@type = 'Document', but what if there's more than one? -->, </xsl:text><xsl:value-of select="@expected"/><xsl:text>,
+ <xsl:text>
+ struct dom_string *match;
+ struct dom_document *actualDoc;
+ err = dom_node_get_owner_document(</xsl:text><xsl:value-of select="@actual"/><xsl:text>, &actualDoc);
+ assert(err == DOM_NO_ERR);
+
+ err = dom_string_create_from_const_ptr(actualDoc, </xsl:text><xsl:value-of select="@expected"/><xsl:text>,
SLEN(</xsl:text><xsl:value-of select="@expected"/><xsl:text>), &match);
assert(err == DOM_NO_ERR); <!-- TODO: pull this line out, since it's reused everywhere -->
- assert(dom_string_cmp(</xsl:text><xsl:value-of select="@actual"/><xsl:text>, match) == 0); <!-- TODO: handle case insensitivity if @insensitive is set-->
-</xsl:text>
+
+ assert(</xsl:text>
+ <xsl:choose>
+ <xsl:when test="@ignoreCase = 'true'">
+ <xsl:text>dom_string_icmp</xsl:text>
+ </xsl:when>
+ <xsl:when test="@ignoreCase = 'auto'">
+ <!--
+ TODO: implement auto case comparison (see java's DOMTestCase.assertEqualsAutoCase()
+ -->
+ <xsl:message><assertEquals ignoreCase='auto'> not supported</xsl:message>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>dom_string_cmp</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>(</xsl:text><xsl:value-of select="@actual"/><xsl:text>, match) == 0);
+</xsl:text>
+ </xsl:when>
+ <xsl:when test="$var_type = 'int'">
+ <xsl:text>
+ assert(</xsl:text><xsl:value-of select="@actual"/><xsl:text> == </xsl:text><xsl:value-of select="@expected"/><xsl:text>);</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="no">Warning in assertEquals template: don't know how to compare variable type '<xsl:value-of select="$var_type"/>'</xsl:message>
@@ -234,19 +289,20 @@
<xsl:template name="convert_var_type">
<!-- TODO: convert certain types, e.g. from DocumentType to dom_document_type -->
<xsl:param name="var_type"/>
- <xsl:text>dom_</xsl:text>
<xsl:choose>
<xsl:when test="$var_type = 'Document'">
- <xsl:text>document</xsl:text>
+ <xsl:text>dom_document</xsl:text>
</xsl:when>
<xsl:when test="$var_type = 'DocumentType'">
- <xsl:text>document_type</xsl:text>
+ <xsl:text>dom_document_type</xsl:text>
</xsl:when>
<xsl:when test="$var_type = 'DOMString'">
- <xsl:text>string</xsl:text>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="no">Warning in convert_var_type template: unrecognised variable type '<xsl:value-of select="$var_type"/>'</xsl:message>
+ <xsl:text>dom_string</xsl:text>
+ </xsl:when>
+ <xsl:when test="$var_type = 'Element'">
+ <xsl:text>dom_element</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
<xsl:value-of select="$var_type"/>
</xsl:otherwise>
</xsl:choose>
@@ -256,8 +312,14 @@
<xsl:param name="attribute_name"/>
<xsl:message><xsl:value-of select="$attribute_name"/></xsl:message>
<xsl:choose>
+ <xsl:when test="$attribute_name = 'nodeName'">
+ <xsl:text>node_name</xsl:text>
+ </xsl:when>
<xsl:when test="$attribute_name = 'nodeValue'">
<xsl:text>node_value</xsl:text>
+ </xsl:when>
+ <xsl:when test="$attribute_name = 'nodeType'">
+ <xsl:text>node_type</xsl:text>
</xsl:when>
<xsl:otherwise>
<!-- assume no conversion is needed -->
16 years, 2 months
r3414 jshaw - in /trunk/dom: include/dom/core/node.h src/core/node.c
by netsurf@semichrome.net
Author: jshaw
Date: Sun Jul 15 13:56:37 2007
New Revision: 3414
URL: http://source.netsurf-browser.org?rev=3414&view=rev
Log:
Rename to dom_node_get_owner_document() in line with spec
Modified:
trunk/dom/include/dom/core/node.h
trunk/dom/src/core/node.c
Modified: trunk/dom/include/dom/core/node.h
URL: http://source.netsurf-browser.org/trunk/dom/include/dom/core/node.h?rev=3...
==============================================================================
--- trunk/dom/include/dom/core/node.h (original)
+++ trunk/dom/include/dom/core/node.h Sun Jul 15 13:56:37 2007
@@ -93,7 +93,7 @@
struct dom_node **result);
dom_exception dom_node_get_attributes(struct dom_node *node,
struct dom_named_node_map **result);
-dom_exception dom_node_get_owner(struct dom_node *node,
+dom_exception dom_node_get_owner_document(struct dom_node *node,
struct dom_document **result);
dom_exception dom_node_insert_before(struct dom_node *node,
struct dom_node *new_child, struct dom_node *ref_child,
Modified: trunk/dom/src/core/node.c
URL: http://source.netsurf-browser.org/trunk/dom/src/core/node.c?rev=3414&r1=3...
==============================================================================
--- trunk/dom/src/core/node.c (original)
+++ trunk/dom/src/core/node.c Sun Jul 15 13:56:37 2007
@@ -334,7 +334,7 @@
* the responsibility of the caller to unref the node once it has
* finished with it.
*/
-dom_exception dom_node_get_owner(struct dom_node *node,
+dom_exception dom_node_get_owner_document(struct dom_node *node,
struct dom_document **result)
{
/* If there is an owner, increase its reference count */
16 years, 2 months
r3413 jmb - in /trunk/dom: bindings/xml/xmlparser.c include/dom/dom.h
by netsurf@semichrome.net
Author: jmb
Date: Sun Jul 15 00:45:20 2007
New Revision: 3413
URL: http://source.netsurf-browser.org?rev=3413&view=rev
Log:
Populate dom.h
Beginnings of xmlparser SAX handling.
Modified:
trunk/dom/bindings/xml/xmlparser.c
trunk/dom/include/dom/dom.h
Modified: trunk/dom/bindings/xml/xmlparser.c
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlparser.c?rev=...
==============================================================================
--- trunk/dom/bindings/xml/xmlparser.c (original)
+++ trunk/dom/bindings/xml/xmlparser.c Sun Jul 15 00:45:20 2007
@@ -17,6 +17,13 @@
#include "xmlparser.h"
#include "utils.h"
+static void xml_parser_start_document(void *ctx);
+static void xml_parser_start_element_ns(void *ctx, const xmlChar *localname,
+ const xmlChar *prefix, const xmlChar *URI,
+ int nb_namespaces, const xmlChar **namespaces,
+ int nb_attributes, int nb_defaulted,
+ const xmlChar **attributes);
+
/**
* XML parser object
*/
@@ -34,44 +41,40 @@
/**
* SAX callback dispatch table
*/
-static xmlSAXHandler sax_handler;
-#if 0
- = {
- internalSubsetSAXFunc internalSubset;
- isStandaloneSAXFunc isStandalone;
- hasInternalSubsetSAXFunc hasInternalSubset;
- hasExternalSubsetSAXFunc hasExternalSubset;
- resolveEntitySAXFunc resolveEntity;
- getEntitySAXFunc getEntity;
- entityDeclSAXFunc entityDecl;
- notationDeclSAXFunc notationDecl;
- attributeDeclSAXFunc attributeDecl;
- elementDeclSAXFunc elementDecl;
- unparsedEntityDeclSAXFunc unparsedEntityDecl;
- setDocumentLocatorSAXFunc setDocumentLocator;
- startDocumentSAXFunc startDocument;
- endDocumentSAXFunc endDocument;
- startElementSAXFunc startElement;
- endElementSAXFunc endElement;
- referenceSAXFunc reference;
- charactersSAXFunc characters;
- ignorableWhitespaceSAXFunc ignorableWhitespace;
- processingInstructionSAXFunc processingInstruction;
- commentSAXFunc comment;
- warningSAXFunc warning;
- errorSAXFunc error;
- fatalErrorSAXFunc fatalError; /* unused error() get all the errors */
- getParameterEntitySAXFunc getParameterEntity;
- cdataBlockSAXFunc cdataBlock;
- externalSubsetSAXFunc externalSubset;
- unsigned int initialized;
- /* The following fields are extensions available only on version 2 */
- void *_private;
- startElementNsSAX2Func startElementNs;
- endElementNsSAX2Func endElementNs;
- xmlStructuredErrorFunc serror;
+static xmlSAXHandler sax_handler = {
+ .internalSubset = xmlSAX2InternalSubset,
+ .isStandalone = xmlSAX2IsStandalone,
+ .hasInternalSubset = xmlSAX2HasInternalSubset,
+ .hasExternalSubset = xmlSAX2HasExternalSubset,
+ .resolveEntity = xmlSAX2ResolveEntity,
+ .getEntity = xmlSAX2GetEntity,
+ .entityDecl = xmlSAX2EntityDecl,
+ .notationDecl = xmlSAX2NotationDecl,
+ .attributeDecl = xmlSAX2AttributeDecl,
+ .elementDecl = xmlSAX2ElementDecl,
+ .unparsedEntityDecl = xmlSAX2UnparsedEntityDecl,
+ .setDocumentLocator = xmlSAX2SetDocumentLocator,
+ .startDocument = xml_parser_start_document,
+ .endDocument = xmlSAX2EndDocument,
+ .startElement = NULL,
+ .endElement = NULL,
+ .reference = xmlSAX2Reference,
+ .characters = xmlSAX2Characters,
+ .ignorableWhitespace = xmlSAX2Characters,
+ .processingInstruction = NULL,
+ .comment = xmlSAX2Comment,
+ .warning = xmlParserWarning,
+ .error = xmlParserError,
+ .fatalError = xmlParserError,
+ .getParameterEntity = xmlSAX2GetParameterEntity,
+ .cdataBlock = xmlSAX2CDataBlock,
+ .externalSubset = xmlSAX2ExternalSubset,
+ .initialized = XML_SAX2_MAGIC,
+ ._private = NULL,
+ .startElementNs = xml_parser_start_element_ns,
+ .endElementNs = xmlSAX2EndElementNs,
+ .serror = NULL,
};
-#endif
/**
* Create an XML parser instance
@@ -185,3 +188,107 @@
{
return (parser->complete ? parser->doc : NULL);
}
+
+/**
+ * Handle a document start SAX event
+ *
+ * \param ctx The callback context
+ */
+void xml_parser_start_document(void *ctx)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+ struct dom_implementation *impl;
+ struct dom_string *features, *udkey;
+ struct dom_document *doc;
+ void *ignored;
+ dom_exception err;
+
+ /* Invoke libxml2's default behaviour */
+ xmlSAX2StartDocument(parser->xml_ctx);
+
+ /* Create a string representation of the features we want */
+ err = dom_string_create_from_ptr_no_doc((dom_alloc) parser->alloc,
+ parser->pw, (const uint8_t *) "XML", SLEN("XML"),
+ &features);
+ if (err != DOM_NO_ERR)
+ return;
+
+ /* Now, try to get an appropriate implementation from the registry */
+ err = dom_implregistry_get_dom_implementation(features, &impl,
+ (dom_alloc) parser->alloc, parser->pw);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(features);
+ return;
+ }
+
+ /* No longer need the features string */
+ dom_string_unref(features);
+
+ /* Attempt to create a document */
+ err = dom_implementation_create_document(impl, /* namespace */ NULL,
+ /* qname */ NULL, /* doctype */ NULL,
+ &doc, (dom_alloc) parser->alloc, parser->pw);
+ if (err != DOM_NO_ERR) {
+ dom_implementation_unref(impl);
+ return;
+ }
+
+ /* No longer need the implementation */
+ dom_implementation_unref(impl);
+
+ /* Create key for user data registration */
+ err = dom_string_create_from_const_ptr(doc,
+ (const uint8_t *) "__xmlnode", SLEN("__xmlnode"),
+ &udkey);
+ if (err != DOM_NO_ERR)
+ return;
+
+ /* Register xmlNode as userdata for document */
+ err = dom_node_set_user_data((struct dom_node *) doc,
+ udkey, parser->xml_ctx->myDoc, NULL, &ignored);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(udkey);
+ return;
+ }
+
+ /* No longer need the key */
+ dom_string_unref(udkey);
+
+ /* Register the DOM node with the xmlNode */
+ dom_node_ref((struct dom_node *) doc);
+ parser->xml_ctx->myDoc->_private = doc;
+
+ /* And squirrel the document away for later use */
+ parser->doc = doc;
+}
+
+/**
+ * Handle an element open SAX event
+ *
+ * \param ctx The callback context
+ * \param localname The local name of the element
+ * \param prefix The element namespace prefix
+ * \param URI The element namespace URI
+ * \param nb_namespaces The number of namespace definitions
+ * \param namespaces Array of nb_namespaces prefix/URI pairs
+ * \param nb_attributes The number of attributes
+ * \param nb_defaulted The number of defaulted attributes
+ * \param attributes Array of [nb_attributes + nb_defaulted] attribute
+ * values
+ */
+void xml_parser_start_element_ns(void *ctx, const xmlChar *localname,
+ const xmlChar *prefix, const xmlChar *URI,
+ int nb_namespaces, const xmlChar **namespaces,
+ int nb_attributes, int nb_defaulted,
+ const xmlChar **attributes)
+{
+ xml_parser *parser = (xml_parser *) ctx;
+
+ /* Invoke libxml2's default behaviour */
+ xmlSAX2StartElementNs(parser->xml_ctx, localname, prefix, URI,
+ nb_namespaces, namespaces, nb_attributes,
+ nb_defaulted, attributes);
+
+ /** \todo mirror the xml tree in the DOM */
+}
+
Modified: trunk/dom/include/dom/dom.h
URL: http://source.netsurf-browser.org/trunk/dom/include/dom/dom.h?rev=3413&r1...
==============================================================================
--- trunk/dom/include/dom/dom.h (original)
+++ trunk/dom/include/dom/dom.h Sun Jul 15 00:45:20 2007
@@ -5,13 +5,33 @@
* Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
*/
+/** \file
+ * This is the top-level header file for libdom. The intention of this is
+ * to allow client applications to simply include this file and get access
+ * to all the libdom API.
+ */
+
#ifndef dom_dom_h_
#define dom_dom_h_
-/** \todo populate this file */
+/* Base library headers */
+#include <dom/functypes.h>
-/* This is the top-level header file for libdom. The intention of this is
- * to allow client applications to simply include this file and get access
- * to all the libdom API. */
+/* DOM bootstrap headers */
+#include <dom/bootstrap/implregistry.h>
+
+/* DOM core headers */
+#include <dom/core/attr.h>
+#include <dom/core/characterdata.h>
+#include <dom/core/document.h>
+#include <dom/core/element.h>
+#include <dom/core/exceptions.h>
+#include <dom/core/implementation.h>
+#include <dom/core/impllist.h>
+#include <dom/core/namednodemap.h>
+#include <dom/core/node.h>
+#include <dom/core/nodelist.h>
+#include <dom/core/string.h>
+#include <dom/core/text.h>
#endif
16 years, 2 months
r3412 jmb - in /trunk/dom: bindings/ bindings/xml/ build/ include/dom/
by netsurf@semichrome.net
Author: jmb
Date: Sat Jul 14 18:37:09 2007
New Revision: 3412
URL: http://source.netsurf-browser.org?rev=3412&view=rev
Log:
LibXML 2 binding for libdom.
This is mostly stub, at present
Added:
trunk/dom/bindings/
trunk/dom/bindings/Makefile
trunk/dom/bindings/xml/
trunk/dom/bindings/xml/Makefile
trunk/dom/bindings/xml/README
trunk/dom/bindings/xml/functypes.h
trunk/dom/bindings/xml/utils.h
trunk/dom/bindings/xml/xmlbinding.c
trunk/dom/bindings/xml/xmlbinding.h
trunk/dom/bindings/xml/xmlerror.h
trunk/dom/bindings/xml/xmlparser.c
trunk/dom/bindings/xml/xmlparser.h
trunk/dom/include/dom/dom.h
Modified:
trunk/dom/build/Makefile.common
Added: trunk/dom/bindings/Makefile
URL: http://source.netsurf-browser.org/trunk/dom/bindings/Makefile?rev=3412&vi...
==============================================================================
--- trunk/dom/bindings/Makefile (added)
+++ trunk/dom/bindings/Makefile Sat Jul 14 18:37:09 2007
@@ -1,0 +1,72 @@
+# Makefile for libdom
+#
+# Toolchain is exported by top-level makefile
+#
+# Top-level makefile also exports the following variables:
+#
+# COMPONENT Name of component
+# EXPORT Absolute path of export directory
+# TOP Absolute path of source tree root
+#
+# The top-level makefile requires the following targets to exist:
+#
+# clean Clean source tree
+# debug Create a debug binary
+# distclean Fully clean source tree, back to pristine condition
+# export Export distributable components to ${EXPORT}
+# release Create a release binary
+# setup Perform any setup required prior to compilation
+# test Execute any test cases
+
+# Manipulate include paths
+CFLAGS += -I$(CURDIR)
+
+# Release output
+RELEASE = ${TOP}/${COMPONENT}.a
+
+# Debug output
+DEBUG = ${TOP}/${COMPONENT}-debug.a
+
+# Objects
+OBJS =
+
+.PHONY: clean debug distclean export release setup test
+
+# Targets
+release: $(addprefix Release/, $(addsuffix .o, $(OBJS)))
+ @${MAKE} -C xml release
+ @${AR} ${ARFLAGS} $(RELEASE) Release/*
+
+debug: $(addprefix Debug/, $(addsuffix .o, $(OBJS)))
+ @${MAKE} -C xml debug
+ @${AR} ${ARFLAGS} $(DEBUG) Debug/*
+
+clean:
+ @${MAKE} -C xml clean
+ifneq (${OBJS}, )
+ -@${RM} ${RMFLAGS} $(addprefix Release/, $(addsuffix .o, ${OBJS}))
+ -@${RM} ${RMFLAGS} $(addprefix Debug/, $(addsuffix .o, ${OBJS}))
+endif
+ -@${RM} ${RMFLAGS} $(RELEASE) $(DEBUG)
+
+distclean:
+ -@${RM} ${RMFLAGS} -r Release
+ -@${RM} ${RMFLAGS} -r Debug
+
+setup:
+ @${MKDIR} ${MKDIRFLAGS} Release
+ @${MKDIR} ${MKDIRFLAGS} Debug
+
+export:
+ @${CP} ${CPFLAGS} $(RELEASE) ${EXPORT}/lib/
+
+test:
+
+# Pattern rules
+Release/%.o: %.c
+ @${ECHO} ${ECHOFLAGS} "==> $<"
+ @${CC} -c ${CFLAGS} -DNDEBUG -o $@ $<
+
+Debug/%.o: %.c
+ @${ECHO} ${ECHOFLAGS} "==> $<"
+ @${CC} -c -g ${CFLAGS} -o $@ $<
Added: trunk/dom/bindings/xml/Makefile
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/Makefile?rev=341...
==============================================================================
--- trunk/dom/bindings/xml/Makefile (added)
+++ trunk/dom/bindings/xml/Makefile Sat Jul 14 18:37:09 2007
@@ -1,0 +1,53 @@
+# Makefile for libdom
+#
+# Toolchain is exported by top-level makefile
+#
+# Top-level makefile also exports the following variables:
+#
+# COMPONENT Name of component
+# EXPORT Absolute path of export directory
+# TOP Absolute path of source tree root
+#
+# The top-level makefile requires the following targets to exist:
+#
+# clean Clean source tree
+# debug Create a debug binary
+# distclean Fully clean source tree, back to pristine condition
+# export Export distributable components to ${EXPORT}
+# release Create a release binary
+# setup Perform any setup required prior to compilation
+# test Execute any test cases
+
+# Manipulate include paths
+CFLAGS += -I$(CURDIR) `pkg-config --cflags libxml-2.0` -D_POSIX_C_SOURCE
+
+# Objects
+OBJS = xmlbinding xmlparser
+
+.PHONY: clean debug distclean export release setup test
+
+# Targets
+release: $(addprefix ../Release/, $(addsuffix .o, $(OBJS)))
+
+debug: $(addprefix ../Debug/, $(addsuffix .o, $(OBJS)))
+
+clean:
+ -@${RM} ${RMFLAGS} $(addprefix ../Release/, $(addsuffix .o, ${OBJS}))
+ -@${RM} ${RMFLAGS} $(addprefix ../Debug/, $(addsuffix .o, ${OBJS}))
+
+distclean:
+
+setup:
+
+export:
+
+test:
+
+# Pattern rules
+../Release/%.o: %.c
+ @${ECHO} ${ECHOFLAGS} "==> $<"
+ @${CC} -c ${CFLAGS} -DNDEBUG -o $@ $<
+
+../Debug/%.o: %.c
+ @${ECHO} ${ECHOFLAGS} "==> $<"
+ @${CC} -c -g ${CFLAGS} -o $@ $<
Added: trunk/dom/bindings/xml/README
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/README?rev=3412&...
==============================================================================
--- trunk/dom/bindings/xml/README (added)
+++ trunk/dom/bindings/xml/README Sat Jul 14 18:37:09 2007
@@ -1,0 +1,35 @@
+LibXML binding for libdom
+=========================
+
+Overview
+--------
+
+ This is an example binding of libxml2 to libdom. It consists of two,
+ orthogonal, parts:
+
+ 1) libxml push parser wrapper
+ 2) libxml-specific DOMImplementationSource for libdom
+
+Push parser wrapper
+-------------------
+
+ This is a wrapper around libxml's push parser API, to facilitate
+ construction of a libdom DOM tree. The basic premise is that the wrapper
+ intercepts the SAX events emitted by libxml's tokeniser then invokes
+ libxml's own SAX handlers, wrapping the results up in libdom-specific
+ data structures.
+
+ The tree created is thus a tree of libdom nodes, each of which is linked
+ to the libxml node that backs it. This allows the binding to process the
+ DOM tree using libxml api, should it need to (e.g. for normalization
+ purposes).
+
+DOMImplementationSource
+-----------------------
+
+ The DOMImplementationSource exposes the APIs needed to create a new
+ document based upon the libxml binding. It also provides the utility
+ functions that libdom uses when performing some operations (such as
+ document normalization). This is needed as libdom is document language
+ agnostic; therefore, it requires support from the binding to perform
+ some operations.
Added: trunk/dom/bindings/xml/functypes.h
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/functypes.h?rev=...
==============================================================================
--- trunk/dom/bindings/xml/functypes.h (added)
+++ trunk/dom/bindings/xml/functypes.h Sat Jul 14 18:37:09 2007
@@ -1,0 +1,16 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#ifndef xml_functypes_h_
+#define xml_functypes_h_
+
+/**
+ * Type of XML parser allocation function
+ */
+typedef void *(*xml_alloc)(void *ptr, size_t len, void *pw);
+
+#endif
Added: trunk/dom/bindings/xml/utils.h
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/utils.h?rev=3412...
==============================================================================
--- trunk/dom/bindings/xml/utils.h (added)
+++ trunk/dom/bindings/xml/utils.h Sat Jul 14 18:37:09 2007
@@ -1,0 +1,28 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#ifndef xml_utils_h_
+#define xml_utils_h_
+
+#ifndef max
+#define max(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef SLEN
+/* Calculate length of a string constant */
+#define SLEN(s) (sizeof((s)) - 1) /* -1 for '\0' */
+#endif
+
+#ifndef UNUSED
+#define UNUSED(x) ((x)=(x))
+#endif
+
+#endif
Added: trunk/dom/bindings/xml/xmlbinding.c
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlbinding.c?rev...
==============================================================================
--- trunk/dom/bindings/xml/xmlbinding.c (added)
+++ trunk/dom/bindings/xml/xmlbinding.c Sat Jul 14 18:37:09 2007
@@ -1,0 +1,344 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <dom/bootstrap/implpriv.h>
+#include <dom/bootstrap/implregistry.h>
+
+#include "functypes.h"
+#include "xmlbinding.h"
+#include "utils.h"
+
+static dom_exception xml_dom_get_dom_implementation(
+ struct dom_string *features,
+ struct dom_implementation **impl, dom_alloc alloc, void *pw);
+static dom_exception xml_dom_get_dom_implementation_list(
+ struct dom_string *features,
+ struct dom_implementation_list **list,
+ dom_alloc alloc, void *pw);
+
+static dom_exception xml_dom_implementation_has_feature(
+ struct dom_implementation *impl,
+ struct dom_string *feature,
+ struct dom_string *version,
+ bool *result);
+static dom_exception xml_dom_implementation_create_document_type(
+ struct dom_implementation *impl,
+ struct dom_string *qname,
+ struct dom_string *public_id,
+ struct dom_string *system_id,
+ struct dom_document_type **doctype,
+ dom_alloc alloc, void *pw);
+static dom_exception xml_dom_implementation_create_document(
+ struct dom_implementation *impl,
+ struct dom_string *namespace,
+ struct dom_string *qname,
+ struct dom_document_type *doctype,
+ struct dom_document **doc,
+ dom_alloc alloc, void *pw);
+static dom_exception xml_dom_implementation_get_feature(
+ struct dom_implementation *impl,
+ struct dom_string *feature,
+ struct dom_string *version,
+ void **object,
+ dom_alloc alloc, void *pw);
+static void xml_dom_implementation_destroy(struct dom_implementation *impl);
+
+
+/**
+ * DOM implementation source for XML documents
+ */
+static struct dom_implementation_source xml_dom_impl_src = {
+ xml_dom_get_dom_implementation,
+ xml_dom_get_dom_implementation_list
+};
+
+/**
+ * DOM implementation for XML documents
+ */
+static struct dom_implementation xml_dom_impl = {
+ xml_dom_implementation_has_feature,
+ xml_dom_implementation_create_document_type,
+ xml_dom_implementation_create_document,
+ xml_dom_implementation_get_feature,
+ xml_dom_implementation_destroy,
+ 0
+};
+
+/**
+ * Get a DOM implementation that supports the requested features
+ *
+ * \param features String containing required features
+ * \param impl Pointer to location to receive implementation
+ * \param alloc Function to (de)allocate memory
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
+ *
+ * Any memory allocated by this call should be allocated using
+ * the provided memory (de)allocation function. The implementation's
+ * destroy() method will be called once it is no longer used.
+ *
+ * The implementation will be referenced, so the client need not
+ * do this explicitly. The client must unref the implementation
+ * once it has finished with it.
+ */
+dom_exception xml_dom_get_dom_implementation(
+ struct dom_string *features,
+ struct dom_implementation **impl, dom_alloc alloc, void *pw)
+{
+ UNUSED(features);
+ UNUSED(alloc);
+ UNUSED(pw);
+
+ xml_dom_impl.refcnt++;
+
+ *impl = &xml_dom_impl;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Get a list of DOM implementations that support the requested
+ * features
+ *
+ * \param features String containing required features
+ * \param list Pointer to location to receive list
+ * \param alloc Function to (de)allocate memory
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
+ *
+ * Any memory allocated by this call should be allocated using
+ * the provided memory (de)allocation function. The ::alloc/::pw
+ * pair must be stored on the list object, such that the list
+ * and its contents may be freed once they are no longer needed.
+ *
+ * List nodes reference the implementation objects they point to.
+ *
+ * The list will be referenced, so the client need not do this
+ * explicitly. The client must unref the list once it has finished
+ * with it.
+ */
+dom_exception xml_dom_get_dom_implementation_list(
+ struct dom_string *features,
+ struct dom_implementation_list **list,
+ dom_alloc alloc, void *pw)
+{
+ struct dom_implementation_list *l;
+ struct dom_implementation_list_item *i;
+
+ UNUSED(features);
+
+ l = alloc(NULL, sizeof(struct dom_implementation_list), pw);
+ if (l == NULL)
+ return DOM_NO_MEM_ERR;
+
+ i = alloc(NULL, sizeof(struct dom_implementation_list_item), pw);
+ if (i == NULL) {
+ alloc(l, 0, pw);
+ return DOM_NO_MEM_ERR;
+ }
+
+ i->impl = &xml_dom_impl;
+ i->next = NULL;
+ i->prev = NULL;
+
+ l->head = i;
+ l->alloc = alloc;
+ l->pw = pw;
+
+ l->refcnt = 1;
+
+ *list = l;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Test whether a DOM implementation implements a specific feature
+ * and version
+ *
+ * \param impl The DOM implementation to query
+ * \param feature The feature to test for
+ * \param version The version number of the feature to test for
+ * \param result Pointer to location to receive result
+ * \return DOM_NO_ERR.
+ */
+dom_exception xml_dom_implementation_has_feature(
+ struct dom_implementation *impl,
+ struct dom_string *feature,
+ struct dom_string *version,
+ bool *result)
+{
+ UNUSED(impl);
+ UNUSED(feature);
+ UNUSED(version);
+ UNUSED(result);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Create a document type node
+ *
+ * \param impl The implementation to create the node
+ * \param qname The qualified name of the document type
+ * \param public_id The external subset public identifier
+ * \param system_id The external subset system identifier
+ * \param doctype Pointer to location to receive result
+ * \param alloc Memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR on success,
+ * DOM_INVALID_CHARACTER_ERR if ::qname is invalid,
+ * DOM_NAMESPACE_ERR if ::qname is malformed,
+ * DOM_NOT_SUPPORTED_ERR if ::impl does not support the
+ * feature "XML" and the language
+ * exposed through Document does
+ * not support XML namespaces.
+ *
+ * Any memory allocated by this call should be allocated using
+ * the provided memory (de)allocation function.
+ *
+ * The doctype will be referenced, so the client need not do this
+ * explicitly. The client must unref the doctype once it has
+ * finished with it.
+ */
+dom_exception xml_dom_implementation_create_document_type(
+ struct dom_implementation *impl,
+ struct dom_string *qname,
+ struct dom_string *public_id,
+ struct dom_string *system_id,
+ struct dom_document_type **doctype,
+ dom_alloc alloc, void *pw)
+{
+ UNUSED(impl);
+ UNUSED(qname);
+ UNUSED(public_id);
+ UNUSED(system_id);
+ UNUSED(doctype);
+ UNUSED(alloc);
+ UNUSED(pw);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Create a document node
+ *
+ * \param impl The implementation to create the node
+ * \param namespace The namespace URI of the document element
+ * \param qname The qualified name of the document element
+ * \param doctype The type of document to create
+ * \param doc Pointer to location to receive result
+ * \param alloc Memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR on success,
+ * DOM_INVALID_CHARACTER_ERR if ::qname is invalid,
+ * DOM_NAMESPACE_ERR if ::qname is malformed, or if
+ * ::qname has a prefix and
+ * ::namespace is NULL, or if
+ * ::qname is NULL and ::namespace
+ * is non-NULL, or if ::qname has
+ * a prefix "xml" and ::namespace
+ * is not
+ * "http://www.w3.org/XML/1998/namespace",
+ * or if ::impl does not support
+ * the "XML" feature and
+ * ::namespace is non-NULL,
+ * DOM_WRONG_DOCUMENT_ERR if ::doctype is already being
+ * used by a document, or if it
+ * was not created by ::impl,
+ * DOM_NOT_SUPPORTED_ERR if ::impl does not support the
+ * feature "XML" and the language
+ * exposed through Document does
+ * not support XML namespaces.
+ *
+ * Any memory allocated by this call should be allocated using
+ * the provided memory (de)allocation function.
+ *
+ * The doctype will be referenced, so the client need not do this
+ * explicitly. The client must unref the doctype once it has
+ * finished with it.
+ */
+dom_exception xml_dom_implementation_create_document(
+ struct dom_implementation *impl,
+ struct dom_string *namespace,
+ struct dom_string *qname,
+ struct dom_document_type *doctype,
+ struct dom_document **doc,
+ dom_alloc alloc, void *pw)
+{
+ UNUSED(impl);
+ UNUSED(namespace);
+ UNUSED(qname);
+ UNUSED(doctype);
+ UNUSED(doc);
+ UNUSED(alloc);
+ UNUSED(pw);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Retrieve a specialized object which implements the specified
+ * feature and version
+ *
+ * \param impl The implementation to create the object
+ * \param feature The requested feature
+ * \param version The version number of the feature
+ * \param object Pointer to location to receive object
+ * \param alloc Memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR.
+ *
+ * Any memory allocated by this call should be allocated using
+ * the provided memory (de)allocation function.
+ */
+dom_exception xml_dom_implementation_get_feature(
+ struct dom_implementation *impl,
+ struct dom_string *feature,
+ struct dom_string *version,
+ void **object,
+ dom_alloc alloc, void *pw)
+{
+ UNUSED(impl);
+ UNUSED(feature);
+ UNUSED(version);
+ UNUSED(object);
+ UNUSED(alloc);
+ UNUSED(pw);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Destroy a DOM implementation instance
+ *
+ * \param impl The instance to destroy
+ */
+void xml_dom_implementation_destroy(struct dom_implementation *impl)
+{
+ UNUSED(impl);
+
+ /* Nothing to do -- we're statically allocated */
+}
+
+/**
+ * Initialise the XML DOM binding
+ *
+ * \param alloc Pointer to memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return XML_OK on success, XML_NOMEM on memory exhaustion
+ */
+xml_error xml_dom_binding_initialise(xml_alloc alloc, void *pw)
+{
+ dom_exception err;
+
+ err = dom_register_source(&xml_dom_impl_src, (dom_alloc) alloc, pw);
+ if (err != DOM_NO_ERR)
+ return XML_NOMEM;
+
+ return XML_OK;
+}
Added: trunk/dom/bindings/xml/xmlbinding.h
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlbinding.h?rev...
==============================================================================
--- trunk/dom/bindings/xml/xmlbinding.h (added)
+++ trunk/dom/bindings/xml/xmlbinding.h Sat Jul 14 18:37:09 2007
@@ -1,0 +1,17 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#ifndef xml_xmlbinding_h_
+#define xml_xmlbinding_h_
+
+#include "xmlerror.h"
+#include "functypes.h"
+
+/* Initialise the XML DOM binding */
+xml_error xml_dom_binding_initialise(xml_alloc alloc, void *pw);
+
+#endif
Added: trunk/dom/bindings/xml/xmlerror.h
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlerror.h?rev=3...
==============================================================================
--- trunk/dom/bindings/xml/xmlerror.h (added)
+++ trunk/dom/bindings/xml/xmlerror.h Sat Jul 14 18:37:09 2007
@@ -1,0 +1,19 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#ifndef xml_xmlerror_h_
+#define xml_xmlerror_h_
+
+typedef enum {
+ XML_OK = 0,
+
+ XML_NOMEM = 1,
+
+ XML_LIBXML_ERR = (1<<16),
+} xml_error;
+
+#endif
Added: trunk/dom/bindings/xml/xmlparser.c
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlparser.c?rev=...
==============================================================================
--- trunk/dom/bindings/xml/xmlparser.c (added)
+++ trunk/dom/bindings/xml/xmlparser.c Sat Jul 14 18:37:09 2007
@@ -1,0 +1,187 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#include <stdbool.h>
+
+#include <libxml/parser.h>
+#include <libxml/SAX2.h>
+#include <libxml/xmlerror.h>
+
+#include <dom/dom.h>
+
+#include "xmlerror.h"
+#include "xmlparser.h"
+#include "utils.h"
+
+/**
+ * XML parser object
+ */
+struct xml_parser {
+ xmlParserCtxtPtr xml_ctx; /**< libxml parser context */
+
+ struct dom_document *doc; /**< DOM Document we're building */
+
+ bool complete; /**< Indicate stream completion */
+
+ xml_alloc alloc; /**< Memory (de)allocation function */
+ void *pw; /**< Pointer to client data */
+};
+
+/**
+ * SAX callback dispatch table
+ */
+static xmlSAXHandler sax_handler;
+#if 0
+ = {
+ internalSubsetSAXFunc internalSubset;
+ isStandaloneSAXFunc isStandalone;
+ hasInternalSubsetSAXFunc hasInternalSubset;
+ hasExternalSubsetSAXFunc hasExternalSubset;
+ resolveEntitySAXFunc resolveEntity;
+ getEntitySAXFunc getEntity;
+ entityDeclSAXFunc entityDecl;
+ notationDeclSAXFunc notationDecl;
+ attributeDeclSAXFunc attributeDecl;
+ elementDeclSAXFunc elementDecl;
+ unparsedEntityDeclSAXFunc unparsedEntityDecl;
+ setDocumentLocatorSAXFunc setDocumentLocator;
+ startDocumentSAXFunc startDocument;
+ endDocumentSAXFunc endDocument;
+ startElementSAXFunc startElement;
+ endElementSAXFunc endElement;
+ referenceSAXFunc reference;
+ charactersSAXFunc characters;
+ ignorableWhitespaceSAXFunc ignorableWhitespace;
+ processingInstructionSAXFunc processingInstruction;
+ commentSAXFunc comment;
+ warningSAXFunc warning;
+ errorSAXFunc error;
+ fatalErrorSAXFunc fatalError; /* unused error() get all the errors */
+ getParameterEntitySAXFunc getParameterEntity;
+ cdataBlockSAXFunc cdataBlock;
+ externalSubsetSAXFunc externalSubset;
+ unsigned int initialized;
+ /* The following fields are extensions available only on version 2 */
+ void *_private;
+ startElementNsSAX2Func startElementNs;
+ endElementNsSAX2Func endElementNs;
+ xmlStructuredErrorFunc serror;
+};
+#endif
+
+/**
+ * Create an XML parser instance
+ *
+ * \param enc Source charset, or NULL
+ * \param int_enc Desired charset of document buffer (UTF-8 or UTF-16)
+ * \param alloc Memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return Pointer to instance, or NULL on memory exhaustion
+ *
+ * Neither ::enc nor ::int_enc are used here.
+ * libxml only supports a UTF-8 document buffer and forcibly setting the
+ * parser encoding is not yet implemented
+ */
+xml_parser *xml_parser_create(const char *enc, const char *int_enc,
+ xml_alloc alloc, void *pw)
+{
+ xml_parser *parser;
+
+ UNUSED(enc);
+ UNUSED(int_enc);
+
+ parser = alloc(NULL, sizeof(xml_parser), pw);
+ if (parser == NULL)
+ return NULL;
+
+ parser->xml_ctx =
+ xmlCreatePushParserCtxt(&sax_handler, parser, "", 0,
+ NULL);
+ if (parser->xml_ctx == NULL) {
+ alloc(parser, 0, pw);
+ return NULL;
+ }
+
+ parser->doc = NULL;
+
+ parser->complete = false;
+
+ parser->alloc = alloc;
+ parser->pw = pw;
+
+ return parser;
+}
+
+/**
+ * Destroy an XML parser instance
+ *
+ * \param parser The parser instance to destroy
+ */
+void xml_parser_destroy(xml_parser *parser)
+{
+ xmlFreeParserCtxt(parser->xml_ctx);
+
+ /** \todo Do we want to clean up the document here, too? */
+ /* Obviously, document cleanup wouldn't happen if the client has
+ * claimed the document from us via xml_parser_get_document() */
+
+ parser->alloc(parser, 0, parser->pw);
+}
+
+/**
+ * Parse a chunk of data
+ *
+ * \param parser The XML parser instance to use for parsing
+ * \param data Pointer to data chunk
+ * \param len Byte length of data chunk
+ * \return XML_OK on success, XML_LIBXML_ERR | <libxml error> on failure
+ */
+xml_error xml_parser_parse_chunk(xml_parser *parser,
+ uint8_t *data, size_t len)
+{
+ xmlParserErrors err;
+
+ err = xmlParseChunk(parser->xml_ctx, (char *) data, len, 0);
+ if (err != XML_ERR_OK)
+ return XML_LIBXML_ERR | err;
+
+ return XML_OK;
+}
+
+/**
+ * Notify parser that datastream is empty
+ *
+ * \param parser The XML parser instance to notify
+ * \return XML_OK on success, XML_LIBXML_ERR | <libxml error> on failure
+ *
+ * This will force any remaining data through the parser
+ */
+xml_error xml_parser_completed(xml_parser *parser)
+{
+ xmlParserErrors err;
+
+ err = xmlParseChunk(parser->xml_ctx, "", 0, 1);
+ if (err != XML_ERR_OK)
+ return XML_LIBXML_ERR | err;
+
+ parser->complete = true;
+
+ return XML_OK;
+}
+
+/**
+ * Retrieve the created DOM Document from a parser
+ *
+ * \param parser The parser instance to retrieve the document from
+ * \return Pointer to document, or NULL if parsing is not complete
+ *
+ * This may only be called after xml_parser_completed().
+ */
+struct dom_document *xml_parser_get_document(xml_parser *parser)
+{
+ return (parser->complete ? parser->doc : NULL);
+}
Added: trunk/dom/bindings/xml/xmlparser.h
URL: http://source.netsurf-browser.org/trunk/dom/bindings/xml/xmlparser.h?rev=...
==============================================================================
--- trunk/dom/bindings/xml/xmlparser.h (added)
+++ trunk/dom/bindings/xml/xmlparser.h Sat Jul 14 18:37:09 2007
@@ -1,0 +1,38 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#ifndef xml_xmlparser_h_
+#define xml_xmlparser_h_
+
+#include <stddef.h>
+#include <inttypes.h>
+
+#include "xmlerror.h"
+#include "functypes.h"
+
+struct dom_document;
+
+typedef struct xml_parser xml_parser;
+
+/* Create an XML parser instance */
+xml_parser *xml_parser_create(const char *enc, const char *int_enc,
+ xml_alloc alloc, void *pw);
+
+/* Destroy an XML parser instance */
+void xml_parser_destroy(xml_parser *parser);
+
+/* Parse a chunk of data */
+xml_error xml_parser_parse_chunk(xml_parser *parser,
+ uint8_t *data, size_t len);
+
+/* Notify parser that datastream is empty */
+xml_error xml_parser_completed(xml_parser *parser);
+
+/* Retrieve the created DOM Document */
+struct dom_document *xml_parser_get_document(xml_parser *parser);
+
+#endif
Modified: trunk/dom/build/Makefile.common
URL: http://source.netsurf-browser.org/trunk/dom/build/Makefile.common?rev=341...
==============================================================================
--- trunk/dom/build/Makefile.common (original)
+++ trunk/dom/build/Makefile.common Sat Jul 14 18:37:09 2007
@@ -11,29 +11,35 @@
# Rules
release: setup
+ @$(MAKE) $(MAKEFLAGS) -C bindings release
@$(MAKE) $(MAKEFLAGS) -C src release
debug: setup
+ @$(MAKE) $(MAKEFLAGS) -C bindings debug
@$(MAKE) $(MAKEFLAGS) -C src debug
test: debug
@$(MAKE) $(MAKEFLAGS) -C test test
clean:
+ @$(MAKE) $(MAKEFLAGS) -C bindings clean
@$(MAKE) $(MAKEFLAGS) -C src clean
@$(MAKE) $(MAKEFLAGS) -C test clean
setup:
+ @$(MAKE) $(MAKEFLAGS) -C bindings setup
@$(MAKE) $(MAKEFLAGS) -C src setup
@$(MAKE) $(MAKEFLAGS) -C test setup
export: release
@$(MKDIR) $(MKDIRFLAGS) $(TOP)/dist/lib
@$(CP) $(CPFLAGS) -r include $(EXPORT)/
+ @$(MAKE) $(MAKEFLAGS) -C bindings export
@$(MAKE) $(MAKEFLAGS) -C src export
@$(MAKE) $(MAKEFLAGS) -C test export
distclean: clean
-@$(RM) $(RMFLAGS) -r $(TOP)/dist
+ @$(MAKE) $(MAKEFLAGS) -C bindings distclean
@$(MAKE) $(MAKEFLAGS) -C src distclean
@$(MAKE) $(MAKEFLAGS) -C test distclean
Added: trunk/dom/include/dom/dom.h
URL: http://source.netsurf-browser.org/trunk/dom/include/dom/dom.h?rev=3412&vi...
==============================================================================
--- trunk/dom/include/dom/dom.h (added)
+++ trunk/dom/include/dom/dom.h Sat Jul 14 18:37:09 2007
@@ -1,0 +1,17 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 John-Mark Bell <jmb(a)netsurf-browser.org>
+ */
+
+#ifndef dom_dom_h_
+#define dom_dom_h_
+
+/** \todo populate this file */
+
+/* This is the top-level header file for libdom. The intention of this is
+ * to allow client applications to simply include this file and get access
+ * to all the libdom API. */
+
+#endif
16 years, 2 months
r3411 jmb - in /trunk/dom: include/dom/core/string.h src/core/string.c
by netsurf@semichrome.net
Author: jmb
Date: Sat Jul 14 15:30:41 2007
New Revision: 3411
URL: http://source.netsurf-browser.org?rev=3411&view=rev
Log:
Add extra dom_string constructor that permits strings to be manufactured in the situation where there exists no document.
This should only be used in order to create dom_strings for use by DocumentType and Document constructors -- in any other situation, a suitable document already exists.
Modified:
trunk/dom/include/dom/core/string.h
trunk/dom/src/core/string.c
Modified: trunk/dom/include/dom/core/string.h
URL: http://source.netsurf-browser.org/trunk/dom/include/dom/core/string.h?rev...
==============================================================================
--- trunk/dom/include/dom/core/string.h (original)
+++ trunk/dom/include/dom/core/string.h Sat Jul 14 15:30:41 2007
@@ -11,6 +11,7 @@
#include <inttypes.h>
#include <stddef.h>
+#include <dom/functypes.h>
#include <dom/core/exceptions.h>
struct dom_document;
@@ -30,6 +31,10 @@
/* Create a DOM string from a constant string of characters */
dom_exception dom_string_create_from_const_ptr(struct dom_document *doc,
const uint8_t *ptr, size_t len, struct dom_string **str);
+/* Create a DOM string from a string of characters that does not belong
+ * to a document */
+dom_exception dom_string_create_from_ptr_no_doc(dom_alloc alloc, void *pw,
+ const uint8_t *ptr, size_t len, struct dom_string **str);
/* Get a pointer to the string of characters within a DOM string */
dom_exception dom_string_get_data(struct dom_string *str,
Modified: trunk/dom/src/core/string.c
URL: http://source.netsurf-browser.org/trunk/dom/src/core/string.c?rev=3411&r1...
==============================================================================
--- trunk/dom/src/core/string.c (original)
+++ trunk/dom/src/core/string.c Sat Jul 14 15:30:41 2007
@@ -24,8 +24,10 @@
struct dom_string {
enum { DOM_STRING_PTR,
DOM_STRING_CONST_PTR,
- DOM_STRING_OFFSET
+ DOM_STRING_OFFSET,
+ DOM_STRING_PTR_NODOC
} type; /**< String type */
+
union {
uint8_t *ptr;
const uint8_t *cptr;
@@ -34,7 +36,14 @@
size_t len; /**< Byte length of string */
- struct dom_document *doc; /**< Owning document */
+ union {
+ struct dom_document *doc; /**< Owning document */
+ struct {
+ dom_alloc alloc; /**< Memory (de)allocation
+ * function */
+ void *pw; /**< Client-specific data */
+ } nodoc;
+ } ctx; /**< Allocation context */
uint32_t refcnt; /**< Reference count */
};
@@ -60,10 +69,19 @@
void dom_string_unref(struct dom_string *str)
{
if (--str->refcnt == 0) {
- if (str->type == DOM_STRING_PTR)
- dom_document_alloc(str->doc, str->data.ptr, 0);
-
- dom_document_alloc(str->doc, str, 0);
+ if (str->type == DOM_STRING_PTR_NODOC) {
+ str->ctx.nodoc.alloc(str->data.ptr, 0,
+ str->ctx.nodoc.pw);
+
+ str->ctx.nodoc.alloc(str, 0, str->ctx.nodoc.pw);
+ } else {
+ if (str->type == DOM_STRING_PTR) {
+ dom_document_alloc(str->ctx.doc,
+ str->data.ptr, 0);
+ }
+
+ dom_document_alloc(str->ctx.doc, str, 0);
+ }
}
}
@@ -94,7 +112,7 @@
ret->len = len;
- ret->doc = doc;
+ ret->ctx.doc = doc;
ret->refcnt = 1;
@@ -139,7 +157,7 @@
ret->len = len;
- ret->doc = doc;
+ ret->ctx.doc = doc;
ret->refcnt = 1;
@@ -178,7 +196,55 @@
ret->len = len;
- ret->doc = doc;
+ ret->ctx.doc = doc;
+
+ ret->refcnt = 1;
+
+ *str = ret;
+
+ return DOM_NO_ERR;
+}
+
+/**
+ * Create a DOM string from a string of characters that does not belong
+ * to a document
+ *
+ * \param alloc Memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \param ptr Pointer to string of characters
+ * \param len Length, in bytes, of string of characters
+ * \param str Pointer to location to receive result
+ * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
+ *
+ * The returned string will already be referenced, so there is no need
+ * to explicitly reference it.
+ *
+ * The string of characters passed in will be copied for use by the
+ * returned DOM string.
+ */
+dom_exception dom_string_create_from_ptr_no_doc(dom_alloc alloc, void *pw,
+ const uint8_t *ptr, size_t len, struct dom_string **str)
+{
+ struct dom_string *ret;
+
+ ret = alloc(NULL, sizeof(struct dom_string), pw);
+ if (ret == NULL)
+ return DOM_NO_MEM_ERR;
+
+ ret->data.ptr = alloc(NULL, len, pw);
+ if (ret->data.ptr == NULL) {
+ alloc(ret, 0, pw);
+ return DOM_NO_MEM_ERR;
+ }
+
+ ret->type = DOM_STRING_PTR_NODOC;
+
+ memcpy(ret->data.ptr, ptr, len);
+
+ ret->len = len;
+
+ ret->ctx.nodoc.alloc = alloc;
+ ret->ctx.nodoc.pw = pw;
ret->refcnt = 1;
@@ -209,7 +275,11 @@
*data = str->data.cptr;
break;
case DOM_STRING_OFFSET:
- *data = dom_document_get_base(str->doc) + str->data.offset;
+ *data = dom_document_get_base(str->ctx.doc) +
+ str->data.offset;
+ break;
+ case DOM_STRING_PTR_NODOC:
+ *data = str->data.ptr;
break;
}
16 years, 2 months