From 7f29141f5069d02843468785a54543a2f6d9260a Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Fri, 6 Jul 2007 14:32:44 +0000 Subject: Import DOM library. This is mainly stub functions atm (and is missing a number of key interfaces). svn path=/trunk/dom/; revision=3384 --- COPYING | 19 + Makefile | 34 ++ Makefile-riscos | 38 ++ README | 39 ++ build/Makefile.common | 39 ++ docs/Todo | 14 + include/dom/core/attr.h | 37 ++ include/dom/core/document.h | 105 ++++ include/dom/core/exceptions.h | 34 ++ include/dom/core/node.h | 170 +++++++ include/dom/core/string.h | 40 ++ include/dom/ctx.h | 26 + src/Makefile | 72 +++ src/core/Makefile | 53 ++ src/core/attr.c | 173 +++++++ src/core/document.c | 356 ++++++++++++++ src/core/document.h | 19 + src/core/node.c | 1069 +++++++++++++++++++++++++++++++++++++++++ src/core/node.h | 60 +++ src/core/string.c | 222 +++++++++ src/utils/utils.h | 28 ++ test/INDEX | 4 + test/Makefile | 60 +++ test/testrunner.pl | 147 ++++++ 24 files changed, 2858 insertions(+) create mode 100644 COPYING create mode 100644 Makefile create mode 100644 Makefile-riscos create mode 100644 README create mode 100644 build/Makefile.common create mode 100644 docs/Todo create mode 100644 include/dom/core/attr.h create mode 100644 include/dom/core/document.h create mode 100644 include/dom/core/exceptions.h create mode 100644 include/dom/core/node.h create mode 100644 include/dom/core/string.h create mode 100644 include/dom/ctx.h create mode 100644 src/Makefile create mode 100644 src/core/Makefile create mode 100644 src/core/attr.c create mode 100644 src/core/document.c create mode 100644 src/core/document.h create mode 100644 src/core/node.c create mode 100644 src/core/node.h create mode 100644 src/core/string.c create mode 100644 src/utils/utils.h create mode 100644 test/INDEX create mode 100644 test/Makefile create mode 100644 test/testrunner.pl diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..7646f4c --- /dev/null +++ b/COPYING @@ -0,0 +1,19 @@ +Copyright (C) 2007 J-M Bell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..db5a35b --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +# Toolchain definitions for building on the destination platform +export CC = gcc +export AR = ar +export LD = gcc + +export CP = cp +export RM = rm +export MKDIR = mkdir +export MV = mv +export ECHO = echo +export MAKE = make +export PERL = perl +export PKGCONFIG = pkg-config + +# Toolchain flags +WARNFLAGS = -Wall -Wextra -Wundef -Wpointer-arith -Wcast-align \ + -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ + -Wmissing-declarations -Wnested-externs -Werror -pedantic +export CFLAGS = -std=c99 -D_BSD_SOURCE -I$(TOP)/include/ $(WARNFLAGS) +export ARFLAGS = -cru +export LDFLAGS = -L$(TOP)/ + +export CPFLAGS = +export RMFLAGS = +export MKDIRFLAGS = -p +export MVFLAGS = +export ECHOFLAGS = +export MAKEFLAGS = +export PKGCONFIGFLAGS = + +export EXEEXT = + + +include build/Makefile.common diff --git a/Makefile-riscos b/Makefile-riscos new file mode 100644 index 0000000..f1d8cf0 --- /dev/null +++ b/Makefile-riscos @@ -0,0 +1,38 @@ +# Toolchain definitions for building for RISC OS using the GCCSDK cross-compiler +GCCSDK_INSTALL_CROSSBIN ?= /home/riscos/cross/bin +GCCSDK_INSTALL_ENV ?= /home/riscos/env + +export CC = $(GCCSDK_INSTALL_CROSSBIN)/gcc +export AR = $(GCCSDK_INSTALL_CROSSBIN)/ar +export LD = $(GCCSDK_INSTALL_CROSSBIN)/gcc + +export CP = cp +export RM = rm +export MKDIR = mkdir +export MV = mv +export ECHO = echo +export MAKE = make +export PERL = perl +export PKGCONFIG = pkg-config + +# Toolchain flags +WARNFLAGS = -Wall -Wextra -Wundef -Wpointer-arith -Wcast-align \ + -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ + -Wmissing-declarations -Wnested-externs -Werror -pedantic +export CFLAGS = -std=c99 -D_BSD_SOURCE -I$(TOP)/include/ $(WARNFLAGS) \ + -mpoke-function-name +export ARFLAGS = -cru +export LDFLAGS = -L$(TOP)/ + +export CPFLAGS = +export RMFLAGS = +export MKDIRFLAGS = -p +export MVFLAGS = +export ECHOFLAGS = +export MAKEFLAGS = +export PKGCONFIGFLAGS = + +export EXEEXT = ,ff8 + + +include build/Makefile.common diff --git a/README b/README new file mode 100644 index 0000000..beeaa91 --- /dev/null +++ b/README @@ -0,0 +1,39 @@ +libdom -- an implementation of the W3C DOM +========================================== + +Overview +-------- + + libdom is an implementation of the W3C DOM API in C. + +Requirements +------------ + + libdom requires the following tools: + + + A C99 capable C compiler + + GNU make or compatible + + Perl (for the testcases) + +Compilation +----------- + + If necessary, modify the toolchain settings in the Makefile. + Invoke make: + $ make + +Verification +------------ + + To verify that the library is working, it is necessary to specify a + different makefile target than that used for normal compilation, thus: + + $ make test + +API documentation +----------------- + + Currently, there is none. However, the code is well commented and the + public API may be found in the "include" directory. The testcase sources + may also be of use in working out how to use it. + diff --git a/build/Makefile.common b/build/Makefile.common new file mode 100644 index 0000000..3b3f92c --- /dev/null +++ b/build/Makefile.common @@ -0,0 +1,39 @@ +# Top-level Makefile fragment for DOM library + +# Name of component +export COMPONENT = libdom + +# Environment +export EXPORT = $(CURDIR)/dist +export TOP = $(CURDIR) + +.PHONY: release debug test clean setup export distclean + +# Rules +release: setup + @$(MAKE) $(MAKEFLAGS) -C src release + +debug: setup + @$(MAKE) $(MAKEFLAGS) -C src debug + +test: debug + @$(MAKE) $(MAKEFLAGS) -C test test + +clean: + @$(MAKE) $(MAKEFLAGS) -C src clean + @$(MAKE) $(MAKEFLAGS) -C test clean + +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 src export + @$(MAKE) $(MAKEFLAGS) -C test export + +distclean: clean + -@$(RM) $(RMFLAGS) -r $(TOP)/dist + @$(MAKE) $(MAKEFLAGS) -C src distclean + @$(MAKE) $(MAKEFLAGS) -C test distclean diff --git a/docs/Todo b/docs/Todo new file mode 100644 index 0000000..507eee9 --- /dev/null +++ b/docs/Todo @@ -0,0 +1,14 @@ +TODO list +========= + + + Sort out the mess that is dom_ctx - I really don't like it; everything (except dom_strings) + should be allocated in the context of a document and, thus, the context is easily found + through foo->owner->blah. dom_strings are somewhat awkward here, as they aren't necessarily + allocated in the context of a document, but they still need access to an allocator. Perhaps + the simplest solution is for the string constructors to take an allocator and private word + as parameters, then store them within the string. This does, however, add an overhead of + 8 (or 16 on 64bit platforms) bytes per dom_string, which isn't exactly great. + + Fill out stub functions for DOM3 core + + Rest of DOM level 3 + + DOM level 2 + + DOM level 1 diff --git a/include/dom/core/attr.h b/include/dom/core/attr.h new file mode 100644 index 0000000..782513e --- /dev/null +++ b/include/dom/core/attr.h @@ -0,0 +1,37 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#ifndef dom_core_attr_h_ +#define dom_core_attr_h_ + +#include + +#include + +struct dom_ctx; +struct dom_element; +struct dom_typeinfo; +struct dom_node; +struct dom_attr; +struct dom_string; + +dom_exception dom_attr_get_name(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_string **result); +dom_exception dom_attr_get_specified(struct dom_ctx *ctx, + struct dom_attr *attr, bool *result); +dom_exception dom_attr_get_value(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_string **result); +dom_exception dom_attr_set_value(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_string *value); +dom_exception dom_attr_get_owner(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_element **result); +dom_exception dom_attr_get_typeinfo(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_typeinfo **result); +dom_exception dom_attr_is_id(struct dom_ctx *ctx, + struct dom_attr *attr, bool *result); + +#endif diff --git a/include/dom/core/document.h b/include/dom/core/document.h new file mode 100644 index 0000000..347fdc4 --- /dev/null +++ b/include/dom/core/document.h @@ -0,0 +1,105 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#ifndef dom_core_document_h_ +#define dom_core_document_h_ + +#include + +#include + +struct dom_attr; +struct dom_configuration; +struct dom_ctx; +struct dom_document; +struct dom_document_type; +struct dom_element; +struct dom_implementation; +struct dom_node; +struct dom_nodelist; +struct dom_string; +struct dom_text; + +dom_exception dom_document_get_doctype(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_document_type **result); +dom_exception dom_document_get_implementation(struct dom_ctx *ctx, + struct dom_document *doc, + struct dom_implementation **result); +dom_exception dom_document_get_element(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_element **result); +dom_exception dom_document_create_element(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *tag_name, + struct dom_element **result); +dom_exception dom_document_create_document_fragment(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node **result); +dom_exception dom_document_create_text_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *data, + struct dom_text **result); +dom_exception dom_document_create_cdata_section(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *data, + struct dom_text **result); +dom_exception dom_document_create_processing_instruction(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *target, + struct dom_string *data, + struct dom_node **result); +dom_exception dom_document_create_attribute(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *name, + struct dom_attr **result); +dom_exception dom_document_create_entity_reference(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *name, + struct dom_node **result); +dom_exception dom_document_get_elements_by_tag_name(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *tagname, + struct dom_nodelist **result); +dom_exception dom_document_import_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node *node, + bool deep, struct dom_node **result); +dom_exception dom_document_create_element_ns(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *namespace, + struct dom_string *qname, struct dom_element **result); +dom_exception dom_document_create_attribute_ns(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *namespace, + struct dom_string *qname, struct dom_attr **result); +dom_exception dom_document_get_elements_by_tag_name_ns(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *namespace, + struct dom_string *localname, struct dom_nodelist **result); +dom_exception dom_document_get_element_by_id(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *id, + struct dom_element **result); +dom_exception dom_document_get_input_encoding(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result); +dom_exception dom_document_get_xml_encoding(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result); +dom_exception dom_document_get_xml_standalone(struct dom_ctx *ctx, + struct dom_document *doc, bool *result); +dom_exception dom_document_set_xml_standalone(struct dom_ctx *ctx, + struct dom_document *doc, bool standalone); +dom_exception dom_document_get_xml_version(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result); +dom_exception dom_document_set_xml_version(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *version); +dom_exception dom_document_get_strict_error_checking(struct dom_ctx *ctx, + struct dom_document *doc, bool *result); +dom_exception dom_document_set_strict_error_checking(struct dom_ctx *ctx, + struct dom_document *doc, bool strict); +dom_exception dom_document_get_uri(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result); +dom_exception dom_document_set_uri(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *uri); +dom_exception dom_document_adopt_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node *node, + struct dom_node **result); +dom_exception dom_document_get_dom_config(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_configuration **result); +dom_exception dom_document_normalize(struct dom_ctx *ctx, + struct dom_document *doc); +dom_exception dom_document_rename_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node *node, + struct dom_string *namespace, struct dom_string *qname, + struct dom_node **result); + +#endif diff --git a/include/dom/core/exceptions.h b/include/dom/core/exceptions.h new file mode 100644 index 0000000..d735013 --- /dev/null +++ b/include/dom/core/exceptions.h @@ -0,0 +1,34 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#ifndef dom_errors_h_ +#define dom_errors_h_ + +/* The DOM spec says that this is actually an unsigned short */ +typedef enum { + DOM_NO_ERR = 0, + DOM_INDEX_SIZE_ERR = 1, + DOM_DOMSTRING_SIZE_ERR = 2, + DOM_HIERARCHY_REQUEST_ERR = 3, + DOM_WRONG_DOCUMENT_ERR = 4, + DOM_INVALID_CHARACTER_ERR = 5, + DOM_NO_DATA_ALLOWED_ERR = 6, + DOM_NO_MODIFICATION_ALLOWED_ERR = 7, + DOM_NOT_FOUND_ERR = 8, + DOM_NOT_SUPPORTED_ERR = 9, + DOM_INUSE_ATTRIBUTE_ERR = 10, + DOM_INVALID_STATE_ERR = 11, + DOM_SYNTAX_ERR = 12, + DOM_INVALID_MODIFICATION_ERR = 13, + DOM_NAMESPACE_ERR = 14, + DOM_INVALID_ACCESS_ERR = 15, + DOM_VALIDATION_ERR = 16, + DOM_TYPE_MISMATCH_ERR = 17, + DOM_NO_MEM_ERR = (1<<16) /* our own internal error */ +} dom_exception; + +#endif diff --git a/include/dom/core/node.h b/include/dom/core/node.h new file mode 100644 index 0000000..e37d99b --- /dev/null +++ b/include/dom/core/node.h @@ -0,0 +1,170 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#ifndef dom_core_node_h_ +#define dom_core_node_h_ + +#include +#include + +#include + +struct dom_ctx; +struct dom_document; +struct dom_node; +struct dom_node_list; +struct dom_named_node_map; +struct dom_string; + +/** + * Bits defining position of a node in a document relative to some other node + */ +typedef enum { + DOM_DOCUMENT_POSITION_DISCONNECTED = 0x01, + DOM_DOCUMENT_POSITION_PRECEDING = 0x02, + DOM_DOCUMENT_POSITION_FOLLOWING = 0x04, + DOM_DOCUMENT_POSITION_CONTAINS = 0x08, + DOM_DOCUMENT_POSITION_CONTAINED_BY = 0x10, + DOM_DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20 +} dom_document_position; + +/** + * Type of node operation being notified to user_data_handler + */ +typedef enum { + DOM_NODE_CLONED = 1, + DOM_NODE_IMPORTED = 2, + DOM_NODE_DELETED = 3, + DOM_NODE_RENAMED = 4, + DOM_NODE_ADOPTED = 5 +} dom_node_operation; + +/** + * Type of handler function for user data registered on a DOM node + */ +typedef void (*dom_user_data_handler)(dom_node_operation operation, + struct dom_string *key, void *data, struct dom_node *src, + struct dom_node *dst); + +/** + * Type of a DOM node + */ +typedef enum { + DOM_ELEMENT_NODE = 1, + DOM_ATTRIBUTE_NODE = 2, + DOM_TEXT_NODE = 3, + DOM_CDATA_SECTION_NODE = 4, + DOM_ENTITY_REFERENCE_NODE = 5, + DOM_ENTITY_NODE = 6, + DOM_PROCESSING_INSTRUCTION_NODE = 7, + DOM_COMMENT_NODE = 8, + DOM_DOCUMENT_NODE = 9, + DOM_DOCUMENT_TYPE_NODE = 10, + DOM_DOCUMENT_FRAGMENT_NODE = 11, + DOM_NOTATION_NODE = 12 +} dom_node_type; + + +void dom_node_ref(struct dom_ctx *ctx, struct dom_node *node); +void dom_node_unref(struct dom_ctx *ctx, struct dom_node *node); + +dom_exception dom_node_get_name(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result); +dom_exception dom_node_get_value(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result); +dom_exception dom_node_set_value(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *value); +dom_exception dom_node_get_type(struct dom_ctx *ctx, + struct dom_node *node, dom_node_type *result); +dom_exception dom_node_get_parent(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result); +dom_exception dom_node_get_children(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node_list **result); +dom_exception dom_node_get_first_child(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result); +dom_exception dom_node_get_last_child(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result); +dom_exception dom_node_get_previous(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result); +dom_exception dom_node_get_next(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result); +dom_exception dom_node_get_attributes(struct dom_ctx *ctx, + struct dom_node *node, struct dom_named_node_map **result); +dom_exception dom_node_get_owner(struct dom_ctx *ctx, + struct dom_node *node, struct dom_document **result); +dom_exception dom_node_insert_before(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *new_child, struct dom_node *ref_child, + struct dom_node **result); +dom_exception dom_node_replace_child(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *new_child, struct dom_node *old_child, + struct dom_node **result); +dom_exception dom_node_remove_child(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *old_child, + struct dom_node **result); +dom_exception dom_node_append_child(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *new_child, + struct dom_node **result); +dom_exception dom_node_has_children(struct dom_ctx *ctx, + struct dom_node *node, bool *result); +dom_exception dom_node_clone(struct dom_ctx *ctx, + struct dom_node *node, bool deep, + struct dom_node **result); +dom_exception dom_node_normalize(struct dom_ctx *ctx, + struct dom_node *node); +dom_exception dom_node_is_supported(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *feature, + struct dom_node *version, bool *result); +dom_exception dom_node_get_namespace(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result); +dom_exception dom_node_get_prefix(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result); +dom_exception dom_node_set_prefix(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *prefix); +dom_exception dom_node_get_local_name(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result); +dom_exception dom_node_has_attributes(struct dom_ctx *ctx, + struct dom_node *node, bool *result); +dom_exception dom_node_get_base(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result); +dom_exception dom_node_compare_document_position(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node *other, + uint16_t *result); +dom_exception dom_node_get_text_content(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result); +dom_exception dom_node_set_text_content(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *content); +dom_exception dom_node_is_same(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node *other, + bool *result); +dom_exception dom_node_lookup_prefix(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *namespace, + struct dom_string **result); +dom_exception dom_node_is_default_namespace(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *namespace, + bool *result); +dom_exception dom_node_lookup_namespace(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *prefix, + struct dom_string **result); +dom_exception dom_node_is_equal(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node *other, + bool *result); +dom_exception dom_node_get_feature(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *feature, + struct dom_string *version, void **result); +dom_exception dom_node_set_user_data(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *key, + void *data, dom_user_data_handler handler, + void **result); +dom_exception dom_node_get_user_data(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *key, + void **result); + +#endif diff --git a/include/dom/core/string.h b/include/dom/core/string.h new file mode 100644 index 0000000..f79eaa7 --- /dev/null +++ b/include/dom/core/string.h @@ -0,0 +1,40 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#ifndef dom_string_h_ +#define dom_string_h_ + +#include +#include + +#include + +struct dom_ctx; +struct dom_document; +struct dom_string; + +/* Claim a reference on a DOM string */ +void dom_string_ref(struct dom_ctx *ctx, struct dom_string *str); +/* Release a reference on a DOM string */ +void dom_string_unref(struct dom_ctx *ctx, struct dom_string *str); + +/* Create a DOM string from an offset into the document buffer */ +dom_exception dom_string_create_from_off(struct dom_ctx *ctx, + struct dom_document *doc, uint32_t off, size_t len, + struct dom_string **str); +/* Create a DOM string from a string of characters */ +dom_exception dom_string_create_from_ptr(struct dom_ctx *ctx, + const uint8_t *ptr, size_t len, struct dom_string **str); +/* Create a DOM string from a constant string of characters */ +dom_exception dom_string_create_from_const_ptr(struct dom_ctx *ctx, + 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_ctx *ctx, + struct dom_string *str, const uint8_t **data, size_t *len); + +#endif diff --git a/include/dom/ctx.h b/include/dom/ctx.h new file mode 100644 index 0000000..f69ec65 --- /dev/null +++ b/include/dom/ctx.h @@ -0,0 +1,26 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#ifndef dom_ctx_h_ +#define dom_ctx_h_ + +#include + +/** + * Type of allocation function for DOM implementation + */ +typedef void *(*dom_alloc)(void *ptr, size_t size, void *pw); + +/** + * DOM allocation context + */ +struct dom_ctx { + dom_alloc alloc; /**< Memory (de)allocation function */ + void *pw; /**< Pointer to client data */ +}; + +#endif diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..ae0c9eb --- /dev/null +++ b/src/Makefile @@ -0,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 core release + @${AR} ${ARFLAGS} $(RELEASE) Release/* + +debug: $(addprefix Debug/, $(addsuffix .o, $(OBJS))) + @${MAKE} -C core debug + @${AR} ${ARFLAGS} $(DEBUG) Debug/* + +clean: + @${MAKE} -C core 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 $@ $< diff --git a/src/core/Makefile b/src/core/Makefile new file mode 100644 index 0000000..3924ebb --- /dev/null +++ b/src/core/Makefile @@ -0,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) + +# Objects +OBJS = attr document node string + +.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 $@ $< diff --git a/src/core/attr.c b/src/core/attr.c new file mode 100644 index 0000000..32fa66f --- /dev/null +++ b/src/core/attr.c @@ -0,0 +1,173 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#include + +#include "core/node.h" +#include "utils/utils.h" + +struct dom_element; +struct dom_typeinfo; + +/** + * DOM node attribute + */ +struct dom_attr { + struct dom_node base; /**< Base node */ + + bool specified; /**< Whether attribute was specified + * or defaulted */ + + struct dom_element *owner; /**< Owning element */ + + struct dom_typeinfo *schema_type_info; /**< Type information */ + + bool is_id; /**< Attribute is of type ID */ +}; + +/** + * Retrieve an attribute's name + * + * \param ctx The context in which the attribute resides + * \param attr Attribute to retrieve name from + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_attr_get_name(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(attr); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Determine if attribute was specified or defaulted + * + * \param ctx The context in which the attribute resides + * \param attr Attribute to inspect + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_attr_get_specified(struct dom_ctx *ctx, + struct dom_attr *attr, bool *result) +{ + UNUSED(ctx); + + *result = attr->specified; + + return DOM_NO_ERR; +} + +/** + * Retrieve an attribute's value + * + * \param ctx The context in which the attribute resides + * \param attr Attribute to retrieve value from + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_attr_get_value(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(attr); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Set an attribute's value + * + * \param ctx The context in which the attribute resides + * \param attr Attribute to retrieve value from + * \param value New value for attribute + * \return DOM_NO_ERR on success, + * DOM_NO_MODIFICATION_ALLOWED_ERR if attribute is readonly. + */ +dom_exception dom_attr_set_value(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_string *value) +{ + UNUSED(ctx); + UNUSED(attr); + UNUSED(value); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the owning element of an attribute + * + * \param ctx The context in which the attribute resides + * \param attr The attribute to extract owning element from + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * The returned node will have its reference count increased. The caller + * should unref it once it has finished with it. + */ +dom_exception dom_attr_get_owner(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_element **result) +{ + /* If there is an owning element, increase its reference count */ + if (attr->owner != NULL) + dom_node_ref(ctx, (struct dom_node *) attr->owner); + + *result = attr->owner; + + return DOM_NO_ERR; +} + +/** + * Retrieve an attribute's type information + * + * \param ctx The context in which the attribute resides + * \param attr The attribute to extract type information from + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * The returned typeinfo will have its reference count increased. The caller + * should unref it once it has finished with it. + */ +dom_exception dom_attr_get_typeinfo(struct dom_ctx *ctx, + struct dom_attr *attr, struct dom_typeinfo **result) +{ + UNUSED(ctx); + UNUSED(attr); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Determine if an attribute if of type ID + * + * \param ctx The context in which the attribute resides + * \param attr The attribute to inspect + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_attr_is_id(struct dom_ctx *ctx, + struct dom_attr *attr, bool *result) +{ + UNUSED(ctx); + + *result = attr->is_id; + + return DOM_NO_ERR; +} diff --git a/src/core/document.c b/src/core/document.c new file mode 100644 index 0000000..1d54dfd --- /dev/null +++ b/src/core/document.c @@ -0,0 +1,356 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#include + +#include "core/node.h" +#include "utils/utils.h" + +/** + * DOM document + */ +struct dom_document { + struct dom_node base; /**< Base node */ +}; + + +dom_exception dom_document_get_doctype(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_document_type **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_implementation(struct dom_ctx *ctx, + struct dom_document *doc, + struct dom_implementation **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_element(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_element **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_element(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *tag_name, + struct dom_element **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(tag_name); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_document_fragment(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_text_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *data, + struct dom_text **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(data); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_cdata_section(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *data, + struct dom_text **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(data); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_processing_instruction(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *target, + struct dom_string *data, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(target); + UNUSED(data); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_attribute(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *name, + struct dom_attr **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(name); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_entity_reference(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *name, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(name); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_elements_by_tag_name(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *tagname, + struct dom_nodelist **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(tagname); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_import_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node *node, + bool deep, struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(node); + UNUSED(deep); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_element_ns(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *namespace, + struct dom_string *qname, struct dom_element **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(namespace); + UNUSED(qname); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_create_attribute_ns(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *namespace, + struct dom_string *qname, struct dom_attr **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(namespace); + UNUSED(qname); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_elements_by_tag_name_ns(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *namespace, + struct dom_string *localname, struct dom_nodelist **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(namespace); + UNUSED(localname); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_element_by_id(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *id, + struct dom_element **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(id); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_input_encoding(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_xml_encoding(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_xml_standalone(struct dom_ctx *ctx, + struct dom_document *doc, bool *result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_set_xml_standalone(struct dom_ctx *ctx, + struct dom_document *doc, bool standalone) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(standalone); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_xml_version(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_set_xml_version(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *version) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(version); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_strict_error_checking(struct dom_ctx *ctx, + struct dom_document *doc, bool *result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_set_strict_error_checking(struct dom_ctx *ctx, + struct dom_document *doc, bool strict) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(strict); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_uri(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_set_uri(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_string *uri) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(uri); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_adopt_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node *node, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(node); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_get_dom_config(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_configuration **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_normalize(struct dom_ctx *ctx, + struct dom_document *doc) +{ + UNUSED(ctx); + UNUSED(doc); + + return DOM_NOT_SUPPORTED_ERR; +} + +dom_exception dom_document_rename_node(struct dom_ctx *ctx, + struct dom_document *doc, struct dom_node *node, + struct dom_string *namespace, struct dom_string *qname, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(doc); + UNUSED(node); + UNUSED(namespace); + UNUSED(qname); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} diff --git a/src/core/document.h b/src/core/document.h new file mode 100644 index 0000000..399b2c8 --- /dev/null +++ b/src/core/document.h @@ -0,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 + */ + +#ifndef dom_internal_document_h_ +#define dom_internal_document_h_ + +#include + +struct dom_ctx; +struct dom_document; + +const uint8_t *dom_document_get_base(struct dom_ctx *ctx, + struct dom_document *doc); + +#endif diff --git a/src/core/node.c b/src/core/node.c new file mode 100644 index 0000000..4c2af88 --- /dev/null +++ b/src/core/node.c @@ -0,0 +1,1069 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#include + +#include "core/node.h" +#include "utils/utils.h" + +/** + * Create a DOM node + * + * \param ctx The context in which the node resides + * \param doc The document which owns the node + * \param type The node type required + * \param name The node name, or NULL + * \param value The node value, or NULL + * \param node Pointer to location to receive created node + * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion + * + * The returned node will be referenced, so there is no need for the caller + * to explicitly reference it. + */ +dom_exception dom_node_create(struct dom_ctx *ctx, + struct dom_document *doc, dom_node_type type, + struct dom_string *name, struct dom_string *value, + struct dom_node **node) +{ + struct dom_node *n; + + n = ctx->alloc(NULL, sizeof(struct dom_node), ctx->pw); + if (n == NULL) + return DOM_NO_MEM_ERR; + + if (name != NULL) + dom_string_ref(ctx, name); + n->name = name; + + if (value != NULL) + dom_string_ref(ctx, value); + n->value = value; + + n->type = type; + + n->parent = NULL; + n->first_child = NULL; + n->last_child = NULL; + n->previous = NULL; + n->next = NULL; + n->attributes = NULL; + + dom_node_ref(ctx, (struct dom_node *) doc); + n->owner = doc; + + /** \todo Namespace handling */ + n->namespace = NULL; + n->prefix = NULL; + n->localname = NULL; + + n->user_data = NULL; + + n->refcnt = 1; + + *node = n; + + return DOM_NO_ERR; +} + +/** + * Claim a reference on a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to claim a reference on + */ +void dom_node_ref(struct dom_ctx *ctx, struct dom_node *node) +{ + UNUSED(ctx); + + node->refcnt++; +} + +/** + * Release a reference on a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to release the reference from + * + * If the reference count reaches zero, any memory claimed by the + * node will be released + */ +void dom_node_unref(struct dom_ctx *ctx, struct dom_node *node) +{ + UNUSED(ctx); + + if (--node->refcnt == 0) { + /** \todo implement */ + } +} + +/** + * Retrieve the name of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the name of + * \param result Pointer to location to receive node name + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_node_get_name(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the value of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the value of + * \param result Pointer to location to receive node value + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + * + * DOM3Core states that this can raise DOMSTRING_SIZE_ERR. It will not in + * this implementation; dom_strings are unbounded. + */ +dom_exception dom_node_get_value(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Set the value of a DOM node + * + * \param ctx The context in which the node resides + * \param node Node to set the value of + * \param value New value for node + * \return DOM_NO_ERR on success, + * DOM_NO_MODIFICATION_ALLOWED_ERR if the node is readonly and the + * value is not defined to be null. + * + * The new value will have its reference count increased, so the caller + * should unref it after the call (as the caller should have already claimed + * a reference on the string). The node's existing value will be unrefed. + */ +dom_exception dom_node_set_value(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *value) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(value); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the type of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the type of + * \param result Pointer to location to receive node type + * \return DOM_NO_ERR. + */ +dom_exception dom_node_get_type(struct dom_ctx *ctx, + struct dom_node *node, dom_node_type *result) +{ + UNUSED(ctx); + + *result = node->type; + + return DOM_NO_ERR; +} + +/** + * Retrieve the parent of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the parent of + * \param result Pointer to location to receive node parent + * \return DOM_NO_ERR. + * + * The returned node will have its reference count increased. It is + * the responsibility of the caller to unref the node once it has + * finished with it. + */ +dom_exception dom_node_get_parent(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result) +{ + /* If there is a parent node, then increase its reference count */ + if (node->parent != NULL) + dom_node_ref(ctx, node->parent); + + *result = node->parent; + + return DOM_NO_ERR; +} + +/** + * Retrieve a list of children of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the children of + * \param result Pointer to location to receive child list + * \return DOM_NO_ERR. + * + * \todo Work out reference counting semantics of dom_node_list + */ +dom_exception dom_node_get_children(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node_list **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the first child of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the first child of + * \param result Pointer to location to receive node's first child + * \return DOM_NO_ERR. + * + * The returned node will have its reference count increased. It is + * the responsibility of the caller to unref the node once it has + * finished with it. + */ +dom_exception dom_node_get_first_child(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result) +{ + /* If there is a first child, increase its reference count */ + if (node->first_child != NULL) + dom_node_ref(ctx, node->first_child); + + *result = node->first_child; + + return DOM_NO_ERR; +} + +/** + * Retrieve the last child of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the last child of + * \param result Pointer to location to receive node's last child + * \return DOM_NO_ERR. + * + * The returned node will have its reference count increased. It is + * the responsibility of the caller to unref the node once it has + * finished with it. + */ +dom_exception dom_node_get_last_child(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result) +{ + /* If there is a last child, increase its reference count */ + if (node->last_child != NULL) + dom_node_ref(ctx, node->last_child); + + *result = node->last_child; + + return DOM_NO_ERR; +} + +/** + * Retrieve the previous sibling of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the previous sibling of + * \param result Pointer to location to receive node's previous sibling + * \return DOM_NO_ERR. + * + * The returned node will have its reference count increased. It is + * the responsibility of the caller to unref the node once it has + * finished with it. + */ +dom_exception dom_node_get_previous(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result) +{ + /* If there is a previous sibling, increase its reference count */ + if (node->previous != NULL) + dom_node_ref(ctx, node->previous); + + *result = node->previous; + + return DOM_NO_ERR; +} + +/** + * Retrieve the subsequent sibling of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the subsequent sibling of + * \param result Pointer to location to receive node's subsequent sibling + * \return DOM_NO_ERR. + * + * The returned node will have its reference count increased. It is + * the responsibility of the caller to unref the node once it has + * finished with it. + */ +dom_exception dom_node_get_next(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node **result) +{ + /* If there is a subsequent sibling, increase its reference count */ + if (node->next != NULL) + dom_node_ref(ctx, node->next); + + *result = node->next; + + return DOM_NO_ERR; +} + +/** + * Retrieve a map of attributes associated with a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the attributes of + * \param result Pointer to location to receive attribute map + * \return DOM_NO_ERR. + * + * \todo Work out reference counting semantics of dom_named_node_map + */ +dom_exception dom_node_get_attributes(struct dom_ctx *ctx, + struct dom_node *node, struct dom_named_node_map **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the owning document of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the owner of + * \param result Pointer to location to receive node's owner + * \return DOM_NO_ERR. + * + * The returned node will have its reference count increased. It is + * the responsibility of the caller to unref the node once it has + * finished with it. + */ +dom_exception dom_node_get_owner(struct dom_ctx *ctx, + struct dom_node *node, struct dom_document **result) +{ + /* If there is an owner, increase its reference count */ + if (node->owner != NULL) + dom_node_ref(ctx, (struct dom_node *) node->owner); + + *result = node->owner; + + return DOM_NO_ERR; +} + +/** + * Insert a child into a node + * + * \param ctx The context in which the nodes reside + * \param node Node to insert into + * \param new_child Node to insert + * \param ref_child Node to insert before, or NULL to insert as last child + * \param result Pointer to location to receive node being inserted + * \return DOM_NO_ERR on success, + * DOM_HIERARCHY_REQUEST_ERR if ::new_child's type is not + * permitted as a child of ::node, + * or ::new_child is an ancestor of + * ::node (or is ::node itself), or + * ::node is of type Document and a + * second DocumentType or Element is + * being inserted, + * DOM_WRONG_DOCUMENT_ERR if ::new_child was created from a + * different document than ::node, + * DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly, or + * ::new_child's parent is readonly, + * DOM_NOT_FOUND_ERR if ::ref_child is not a child of + * ::node, + * DOM_NOT_SUPPORTED_ERR if ::node is of type Document and + * ::new_child is of type + * DocumentType or Element. + * + * If ::new_child is a DocumentFragment, all of its children are inserted. + * If ::new_child is already in the tree, it is first removed. + * + * ::new_child's reference count will be increased. The caller should unref + * it (as they should already have held a reference on the node) + */ +dom_exception dom_node_insert_before(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *new_child, struct dom_node *ref_child, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(new_child); + UNUSED(ref_child); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Replace a node's child with a new one + * + * \param ctx The context in which the nodes reside + * \param node Node whose child to replace + * \param new_child Replacement node + * \param old_child Child to replace + * \param result Pointer to location to receive replaced node + * \return DOM_NO_ERR on success, + * DOM_HIERARCHY_REQUEST_ERR if ::new_child's type is not + * permitted as a child of ::node, + * or ::new_child is an ancestor of + * ::node (or is ::node itself), or + * ::node is of type Document and a + * second DocumentType or Element is + * being inserted, + * DOM_WRONG_DOCUMENT_ERR if ::new_child was created from a + * different document than ::node, + * DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly, or + * ::new_child's parent is readonly, + * DOM_NOT_FOUND_ERR if ::old_child is not a child of + * ::node, + * DOM_NOT_SUPPORTED_ERR if ::node is of type Document and + * ::new_child is of type + * DocumentType or Element. + * + * If ::new_child is a DocumentFragment, ::old_child is replaced by all of + * ::new_child's children. + * If ::new_child is already in the tree, it is first removed. + * + * ::new_child's reference count will be increased. The caller should unref + * it (as they should already have held a reference on the node) + * + * ::old_child's reference count remains unmodified (::node's reference is + * transferred to the caller). The caller should unref ::old_child once it + * is finished with it. + */ +dom_exception dom_node_replace_child(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *new_child, struct dom_node *old_child, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(new_child); + UNUSED(old_child); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Remove a child from a node + * + * \param ctx The context in which the nodes reside + * \param node Node whose child to replace + * \param old_child Child to remove + * \param result Pointer to location to receive removed node + * \return DOM_NO_ERR on success, + * DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly + * DOM_NOT_FOUND_ERR if ::old_child is not a child of + * ::node, + * DOM_NOT_SUPPORTED_ERR if ::node is of type Document and + * ::new_child is of type + * DocumentType or Element. + * + * ::old_child's reference count remains unmodified (::node's reference is + * transferred to the caller). The caller should unref ::old_child once it + * is finished with it. + */ +dom_exception dom_node_remove_child(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *old_child, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(old_child); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Append a child to the end of a node's child list + * + * \param ctx The context in which the nodes reside + * \param node Node to insert into + * \param new_child Node to append + * \param result Pointer to location to receive node being inserted + * \return DOM_NO_ERR on success, + * DOM_HIERARCHY_REQUEST_ERR if ::new_child's type is not + * permitted as a child of ::node, + * or ::new_child is an ancestor of + * ::node (or is ::node itself), or + * ::node is of type Document and a + * second DocumentType or Element is + * being inserted, + * DOM_WRONG_DOCUMENT_ERR if ::new_child was created from a + * different document than ::node, + * DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly, or + * ::new_child's parent is readonly, + * DOM_NOT_SUPPORTED_ERR if ::node is of type Document and + * ::new_child is of type + * DocumentType or Element. + * + * If ::new_child is a DocumentFragment, all of its children are inserted. + * If ::new_child is already in the tree, it is first removed. + * + * ::new_child's reference count will be increased. The caller should unref + * it (as they should already have held a reference on the node) + */ +dom_exception dom_node_append_child(struct dom_ctx *ctx, + struct dom_node *node, + struct dom_node *new_child, + struct dom_node **result) +{ + /* This is just a veneer over insert_before */ + return dom_node_insert_before(ctx, node, new_child, NULL, result); +} + +/** + * Determine if a node has any children + * + * \param ctx The context in which the node resides + * \param node Node to inspect + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_node_has_children(struct dom_ctx *ctx, + struct dom_node *node, bool *result) +{ + UNUSED(ctx); + + *result = node->first_child != NULL; + + return DOM_NO_ERR; +} + +/** + * Clone a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to clone + * \param deep True to deep-clone the node's sub-tree + * \param result Pointer to location to receive result + * \return DOM_NO_ERR on success, + * DOM_NO_MEMORY_ERR on memory exhaustion. + * + * The returned node will already be referenced. + * + * The duplicate node will have no parent and no user data. + * + * If ::node has registered user_data_handlers, then they will be called. + * + * Cloning an Element copies all attributes & their values (including those + * generated by the XML processor to represent defaulted attributes). It + * does not copy any child nodes unless it is a deep copy (this includes + * text contained within the Element, as the text is contained in a child + * Text node). + * + * Cloning an Attr directly, as opposed to cloning as part of an Element, + * returns a specified attribute. Cloning an Attr always clones its children, + * since they represent its value, no matter whether this is a deep clone or + * not. + * + * Cloning an EntityReference automatically constructs its subtree if a + * corresponding Entity is available, no matter whether this is a deep clone + * or not. + * + * Cloning any other type of node simply returns a copy. + * + * Note that cloning an immutable subtree results in a mutable copy, but + * the children of an EntityReference clone are readonly. In addition, clones + * of unspecified Attr nodes are specified. + * + * \todo work out what happens when cloning Document, DocumentType, Entity + * and Notation nodes. + */ +dom_exception dom_node_clone(struct dom_ctx *ctx, + struct dom_node *node, bool deep, + struct dom_node **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(deep); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Normalize a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to normalize + * \return DOM_NO_ERR. + * + * Puts all Text nodes in the full depth of the sub-tree beneath ::node, + * including Attr nodes into "normal" form, where only structure separates + * Text nodes. + */ +dom_exception dom_node_normalize(struct dom_ctx *ctx, + struct dom_node *node) +{ + UNUSED(ctx); + UNUSED(node); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Test whether the DOM implementation implements a specific feature and + * that feature is supported by the node. + * + * \param ctx The context in which the node resides + * \param node The node to test + * \param feature The name of the feature to test + * \param version The version number of the feature to test + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_node_is_supported(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *feature, + struct dom_node *version, bool *result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(feature); + UNUSED(version); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the namespace of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the namespace of + * \param result Pointer to location to receive node's namespace + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_node_get_namespace(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result) +{ + /* If there is a namespace, increase its reference count */ + if (node->namespace != NULL) + dom_string_ref(ctx, node->namespace); + + *result = node->namespace; + + return DOM_NO_ERR; +} + +/** + * Retrieve the prefix of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the prefix of + * \param result Pointer to location to receive node's prefix + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_node_get_prefix(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result) +{ + /* If there is a prefix, increase its reference count */ + if (node->prefix != NULL) + dom_string_ref(ctx, node->prefix); + + *result = node->prefix; + + return DOM_NO_ERR; +} + +/** + * Set the prefix of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to set the prefix of + * \param prefix Pointer to prefix string + * \return DOM_NO_ERR on success, + * DOM_INVALID_CHARACTER_ERR if the specified prefix contains + * an illegal character, + * DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly, + * DOM_NAMESPACE_ERR if the specified prefix is + * malformed, if the namespaceURI of + * ::node is null, if the specified + * prefix is "xml" and the + * namespaceURI is different from + * "http://www.w3.org/XML/1998/namespace", + * if ::node is an attribute and the + * specified prefix is "xmlns" and + * the namespaceURI is different from + * "http://www.w3.org/2000/xmlns", + * or if this node is an attribute + * and the qualifiedName of ::node + * is "xmlns". + */ +dom_exception dom_node_set_prefix(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *prefix) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(prefix); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the local part of a node's qualified name + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the local name of + * \param result Pointer to location to receive local name + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_node_get_local_name(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result) +{ + /* If there is a local name, increase its reference count */ + if (node->localname != NULL) + dom_string_ref(ctx, node->localname); + + *result = node->localname; + + return DOM_NO_ERR; +} + +/** + * Determine if a node has any attributes + * + * \param ctx The context in which the node resides + * \param node Node to inspect + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_node_has_attributes(struct dom_ctx *ctx, + struct dom_node *node, bool *result) +{ + UNUSED(ctx); + + *result = node->attributes != NULL; + + return DOM_NO_ERR; +} + +/** + * Retrieve the base URI of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the base URI of + * \param result Pointer to location to receive base URI + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_node_get_base(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Compare the positions of two nodes in a DOM tree + * + * \param ctx The context in which the nodes reside + * \param node The reference node + * \param other The node to compare + * \param result Pointer to location to receive result + * \return DOM_NO_ERR on success, + * DOM_NOT_SUPPORTED_ERR when the nodes are from different DOM + * implementations. + * + * The result is a bitfield of dom_document_position values. + */ +dom_exception dom_node_compare_document_position(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node *other, + uint16_t *result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(other); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve the text content of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve the text content of + * \param result Pointer to location to receive text content + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + * + * DOM3Core states that this can raise DOMSTRING_SIZE_ERR. It will not in + * this implementation; dom_strings are unbounded. + */ +dom_exception dom_node_get_text_content(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Set the text content of a DOM node + * + * \param ctx The context in which the node resides + * \param node The node to set the text content of + * \param content New text content for node + * \return DOM_NO_ERR on success, + * DOM_NO_MODIFICATION_ALLOWED_ERR if ::node is readonly. + * + * Any child nodes ::node may have are removed and replaced with a single + * Text node containing the new content. + */ +dom_exception dom_node_set_text_content(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *content) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(content); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Determine if two DOM nodes are the same + * + * \param ctx The context in which the nodes reside + * \param node The node to compare + * \param other The node to compare against + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * This tests if the two nodes reference the same object. + */ +dom_exception dom_node_is_same(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node *other, + bool *result) +{ + UNUSED(ctx); + + *result = (node == other); + + return DOM_NO_ERR; +} + +/** + * Lookup the prefix associated with the given namespace URI + * + * \param ctx The context in which the node resides + * \param node The node to start prefix search from + * \param namespace The namespace URI + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_node_lookup_prefix(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *namespace, + struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(namespace); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Determine if the specified namespace is the default namespace + * + * \param ctx The context in which the node resides + * \param node The node to query + * \param namespace The namespace URI to test + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_node_is_default_namespace(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *namespace, + bool *result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(namespace); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Lookup the namespace URI associated with the given prefix + * + * \param ctx The context in which the node resides + * \param node The node to start namespace search from + * \param prefix The prefix to look for, or NULL to find default. + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * The returned string will have its reference count increased. It is + * the responsibility of the caller to unref the string once it has + * finished with it. + */ +dom_exception dom_node_lookup_namespace(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *prefix, + struct dom_string **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(prefix); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Determine if two DOM nodes are equal + * + * \param ctx The context in which the nodes reside + * \param node The node to compare + * \param other The node to compare against + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + * + * Two nodes are equal iff: + * + They are of the same type + * + nodeName, localName, namespaceURI, prefix, nodeValue are equal + * + The node attributes are equal + * + The child nodes are equal + * + * Two DocumentType nodes are equal iff: + * + publicId, systemId, internalSubset are equal + * + The node entities are equal + * + The node notations are equal + */ +dom_exception dom_node_is_equal(struct dom_ctx *ctx, + struct dom_node *node, struct dom_node *other, + bool *result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(other); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieve an object which implements the specialized APIs of the specified + * feature and version. + * + * \param ctx The context in which the node resides + * \param node The node to query + * \param feature The requested feature + * \param version The version number of the feature + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_node_get_feature(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *feature, + struct dom_string *version, void **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(feature); + UNUSED(version); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Associate an object to a key on this node + * + * \param ctx The context in which the node resides + * \param node The node to insert object into + * \param key The key associated with the object + * \param data The object to associate with key, or NULL to remove + * \param handler User handler function, or NULL if none + * \param result Pointer to location to receive previously associated object + * \return DOM_NO_ERR. + */ +dom_exception dom_node_set_user_data(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *key, + void *data, dom_user_data_handler handler, + void **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(key); + UNUSED(data); + UNUSED(handler); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} + +/** + * Retrieves the object associated to a key on this node + * + * \param ctx The context in which the node resides + * \param node The node to retrieve object from + * \param key The key to search for + * \param result Pointer to location to receive result + * \return DOM_NO_ERR. + */ +dom_exception dom_node_get_user_data(struct dom_ctx *ctx, + struct dom_node *node, struct dom_string *key, + void **result) +{ + UNUSED(ctx); + UNUSED(node); + UNUSED(key); + UNUSED(result); + + return DOM_NOT_SUPPORTED_ERR; +} diff --git a/src/core/node.h b/src/core/node.h new file mode 100644 index 0000000..b39ac40 --- /dev/null +++ b/src/core/node.h @@ -0,0 +1,60 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#ifndef dom_internal_core_node_h_ +#define dom_internal_core_node_h_ + +#include +#include + +struct dom_attr; + +/** + * User data context attached to a DOM node + */ +struct dom_user_data { + struct dom_string *key; /**< Key for data */ + void *data; /**< Client-specific data */ + dom_user_data_handler handler; /**< Callback function */ + + struct dom_user_data *next; /**< Next in list */ + struct dom_user_data *prev; /**< Previous in list */ +}; + +/** + * DOM node object + * + * DOM nodes are reference counted + */ +struct dom_node { + struct dom_string *name; /**< Node name */ + struct dom_string *value; /**< Node value */ + dom_node_type type; /**< Node type */ + struct dom_node *parent; /**< Parent node */ + struct dom_node *first_child; /**< First child node */ + struct dom_node *last_child; /**< Last child node */ + struct dom_node *previous; /**< Previous sibling */ + struct dom_node *next; /**< Next sibling */ + struct dom_attr *attributes; /**< Node attributes */ + + struct dom_document *owner; /**< Owning document */ + + struct dom_string *namespace; /**< Namespace URI */ + struct dom_string *prefix; /**< Namespace prefix */ + struct dom_string *localname; /**< Local part of qualified name */ + + struct dom_user_data *user_data; /**< User data list */ + + uint32_t refcnt; /**< Reference count */ +}; + +dom_exception dom_node_create(struct dom_ctx *ctx, + struct dom_document *doc, dom_node_type type, + struct dom_string *name, struct dom_string *value, + struct dom_node **node); + +#endif diff --git a/src/core/string.c b/src/core/string.c new file mode 100644 index 0000000..070af75 --- /dev/null +++ b/src/core/string.c @@ -0,0 +1,222 @@ +/* + * This file is part of libdom. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2007 John-Mark Bell + */ + +#include +#include + +#include +#include + +#include "core/document.h" +#include "utils/utils.h" + +/** + * A DOM string + * + * DOM strings store either a pointer to allocated data, a pointer + * to constant data or an offset into a document buffer. + * + * They are reference counted so freeing is performed correctly. + */ +struct dom_string { + enum { DOM_STRING_PTR, + DOM_STRING_CONST_PTR, + DOM_STRING_OFFSET + } type; + union { + uint8_t *ptr; + const uint8_t *cptr; + struct { + struct dom_document *doc; + uint32_t off; + } offset; + } data; + + size_t len; + + uint32_t refcnt; +}; + +/** + * Claim a reference on a DOM string + * + * \param ctx The context in which the string resides + * \param str The string to claim a reference on + */ +void dom_string_ref(struct dom_ctx *ctx, struct dom_string *str) +{ + UNUSED(ctx); + + str->refcnt++; +} + +/** + * Release a reference on a DOM string + * + * \param ctx The context in which the string resides + * \param str The string to release the reference from + * + * If the reference count reaches zero, any memory claimed by the + * string will be released + */ +void dom_string_unref(struct dom_ctx *ctx, struct dom_string *str) +{ + if (--str->refcnt == 0) { + if (str->type == DOM_STRING_PTR) + ctx->alloc(str->data.ptr, 0, ctx->pw); + + ctx->alloc(str, 0, ctx->pw); + } +} + +/** + * Create a DOM string from an offset into the document buffer + * + * \param ctx The context in which the string resides + * \param doc The document in which the string resides + * \param off Offset from start of document buffer + * \param len Length, in bytes, of string + * \param str Pointer to location to receive pointer to new string + * \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. + */ +dom_exception dom_string_create_from_off(struct dom_ctx *ctx, + struct dom_document *doc, uint32_t off, size_t len, + struct dom_string **str) +{ + struct dom_string *ret; + + ret = ctx->alloc(NULL, sizeof(struct dom_string), ctx->pw); + if (ret == NULL) + return DOM_NO_MEM_ERR; + + ret->type = DOM_STRING_OFFSET; + ret->data.offset.doc = doc; + ret->data.offset.off = off; + ret->len = len; + + ret->refcnt = 1; + + *str = ret; + + return DOM_NO_ERR; +} + +/** + * Create a DOM string from a string of characters + * + * \param ctx The context in which the string resides + * \param ptr Pointer to string of characters + * \param len Length, in bytes, of string of characters + * \param str Pointer to location to receive pointer to new string + * \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(struct dom_ctx *ctx, + const uint8_t *ptr, size_t len, struct dom_string **str) +{ + struct dom_string *ret; + + ret = ctx->alloc(NULL, sizeof(struct dom_string), ctx->pw); + if (ret == NULL) + return DOM_NO_MEM_ERR; + + ret->data.ptr = ctx->alloc(NULL, len, ctx->pw); + if (ret->data.ptr == NULL) { + ctx->alloc(ret, 0, ctx->pw); + return DOM_NO_MEM_ERR; + } + + ret->type = DOM_STRING_PTR; + + memcpy(ret->data.ptr, ptr, len); + + ret->len = len; + + ret->refcnt = 1; + + *str = ret; + + return DOM_NO_ERR; +} + +/** + * Create a DOM string from a constant string of characters + * + * \param ctx The context in which the string resides + * \param ptr Pointer to string of characters + * \param len Length, in bytes, of string of characters + * \param str Pointer to location to receive pointer to new string + * \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 _not_ be copied for use by the + * returned DOM string. + */ +dom_exception dom_string_create_from_const_ptr(struct dom_ctx *ctx, + const uint8_t *ptr, size_t len, struct dom_string **str) +{ + struct dom_string *ret; + + ret = ctx->alloc(NULL, sizeof(struct dom_string), ctx->pw); + if (ret == NULL) + return DOM_NO_MEM_ERR; + + ret->data.cptr = ptr; + + ret->type = DOM_STRING_CONST_PTR; + + ret->len = len; + + ret->refcnt = 1; + + *str = ret; + + return DOM_NO_ERR; +} + +/** + * Get a pointer to the string of characters within a DOM string + * + * \param ctx The context in which the string resides + * \param str Pointer to DOM string to retrieve pointer from + * \param data Pointer to location to receive data + * \param len Pointer to location to receive byte length of data + * \return DOM_NO_ERR on success + * + * The caller must have previously claimed a reference on the DOM string. + * The returned pointer must not be freed. + */ +dom_exception dom_string_get_data(struct dom_ctx *ctx, + struct dom_string *str, const uint8_t **data, size_t *len) +{ + switch (str->type) { + case DOM_STRING_PTR: + *data = str->data.ptr; + break; + case DOM_STRING_CONST_PTR: + *data = str->data.cptr; + break; + case DOM_STRING_OFFSET: + *data = dom_document_get_base(ctx, str->data.offset.doc) + + str->data.offset.off; + break; + } + + *len = str->len; + + return DOM_NO_ERR; +} diff --git a/src/utils/utils.h b/src/utils/utils.h new file mode 100644 index 0000000..ae861c7 --- /dev/null +++ b/src/utils/utils.h @@ -0,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 + */ + +#ifndef dom_utils_h_ +#define dom_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 diff --git a/test/INDEX b/test/INDEX new file mode 100644 index 0000000..a1b7297 --- /dev/null +++ b/test/INDEX @@ -0,0 +1,4 @@ +# Index for libdom testcases +# +# Test Description DataDir + diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..d9bb137 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,60 @@ +# Makefile for Hubbub testcases +# +# 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 + +# Extend toolchain settings +CFLAGS += -I${TOP}/src/ -I$(CURDIR) + +# Release output +RELEASE = + +# Debug output +DEBUG = + +# Objects +OBJS = + +.PHONY: clean debug export release setup test + +# Targets +release: + +debug: + +clean: +ifneq (${OBJS}, ) + -@${RM} ${RMFLAGS} $(addsuffix ${EXEEXT}, $(OBJS)) +endif + +distclean: + -@${RM} ${RMFLAGS} log + +setup: + +export: + +test: $(OBJS) + @${PERL} testrunner.pl ${EXEEXT} + +# Pattern rules +%: %.c + @${ECHO} ${ECHOFLAGS} "==> $<" + @${CC} -c -g ${CFLAGS} -o $@.o $< + @${LD} -g -o $@ $@.o ${LDFLAGS} -ldom-debug + @${RM} ${RMFLAGS} $@.o diff --git a/test/testrunner.pl b/test/testrunner.pl new file mode 100644 index 0000000..00c54e7 --- /dev/null +++ b/test/testrunner.pl @@ -0,0 +1,147 @@ +#!/bin/perl +# +# Testcase runner for libhubbub +# +# Usage: testrunner +# +# Operates upon INDEX files described in the README. +# Locates and executes testcases, feeding data files to programs +# as appropriate. +# Logs testcase output to file. +# Aborts test sequence on detection of error. +# + +use warnings; +use strict; +use File::Spec; +use IPC::Open3; + +# Get EXE extension (if any) +my $exeext = ""; +$exeext = shift @ARGV if (@ARGV > 0); + +# Open log file and /dev/null +open(LOG, ">log") or die "Failed opening test log"; +open(NULL, "+<", File::Spec->devnull) or die "Failed opening /dev/null"; + +# Open testcase index +open(TINDEX, ") { + next if ($line =~ /^(#.*)?$/); + + # Found one; decompose + (my $test, my $desc, my $data) = split /\t+/, $line; + + # Strip whitespace + $test =~ s/^\s+|\s+$//g; + $desc =~ s/^\s+|\s+$//g; + $data =~ s/^\s+|\s+$//g if ($data); + + # Append EXE extension to binary name + $test = $test . $exeext; + + print "Test: $desc\n"; + + my $pid; + + if ($data) { + # Testcase has external data files + + # Open datafile index + open(DINDEX, "<./data/$data/INDEX") or + die "Failed opening ./data/$data/INDEX"; + + # Parse datafile index, looking for datafiles + while (my $dentry = ) { + next if ($dentry =~ /^(#.*)?$/); + + # Found one; decompose + (my $dtest, my $ddesc) = split /\t+/, $dentry; + + # Strip whitespace + $dtest =~ s/^\s+|\s+$//g; + $ddesc =~ s/^\s+|\s+$//g; + + print LOG "Running ./$test ./data/Aliases " . + "./data/$data/$dtest\n"; + + # Make message fit on an 80 column terminal + my $msg = " ==> $test [$data/$dtest]"; + $msg = $msg . "." x (80 - length($msg) - 8); + + print $msg; + + # Run testcase + $pid = open3("&&NULL", + "./$test", "./data/Aliases", + "./data/$data/$dtest"); + + my $last; + + # Marshal testcase output to log file + while (my $output = ) { + print LOG " $output"; + $last = $output; + } + + # Wait for child to finish + waitpid($pid, 0); + + print substr($last, 0, 4) . "\n"; + + # Bail, noisily, on failure + if (substr($last, 0, 4) eq "FAIL") { + print "\n\nFailure detected: " . + "consult log file\n\n\n"; + + exit(1); + } + } + + close(DINDEX); + } else { + # Testcase has no external data files + print LOG "Running ./$test ./data/Aliases\n"; + + # Make message fit on an 80 column terminal + my $msg = " ==> $test"; + $msg = $msg . "." x (80 - length($msg) - 8); + + print $msg; + + # Run testcase + $pid = open3("&NULL", + "./$test", "./data/Aliases"); + + my $last; + + # Marshal testcase output to log file + while (my $output = ) { + print LOG " $output"; + $last = $output; + } + + # Wait for child to finish + waitpid($pid, 0); + + print substr($last, 0, 4) . "\n"; + + # Bail, noisily, on failure + if (substr($last, 0, 4) eq "FAIL") { + print "\n\nFailure detected: " . + "consult log file\n\n\n"; + + exit(1); + } + } + + print "\n"; +} + +# Clean up +close(TINDEX); + +close(NULL); +close(LOG); -- cgit v1.2.3