summaryrefslogtreecommitdiff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorBo Yang <struggleyb.nku@gmail.com>2009-08-11 11:17:23 +0000
committerBo Yang <struggleyb.nku@gmail.com>2009-08-11 11:17:23 +0000
commit399da01ae4eb5c5e3e9349bacc2063c946c3d4a1 (patch)
tree433c8bcde94fc7a6e6f2e5cbf23842a84db98146 /src/bootstrap
parenteec057c7437e19b59ca1e698ce548cb56ce37240 (diff)
downloadlibdom-399da01ae4eb5c5e3e9349bacc2063c946c3d4a1.tar.gz
libdom-399da01ae4eb5c5e3e9349bacc2063c946c3d4a1.tar.bz2
Merge the branches/struggleyb/libdom-remain back to trunk.
svn path=/trunk/dom/; revision=9191
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/Makefile2
-rw-r--r--src/bootstrap/implementation.c423
-rw-r--r--src/bootstrap/implementation.h14
-rw-r--r--src/bootstrap/implregistry.c71
-rw-r--r--src/bootstrap/init_fini.c19
5 files changed, 500 insertions, 29 deletions
diff --git a/src/bootstrap/Makefile b/src/bootstrap/Makefile
index 820a4f4..e969d87 100644
--- a/src/bootstrap/Makefile
+++ b/src/bootstrap/Makefile
@@ -1,3 +1,3 @@
-DIR_SOURCES := implregistry.c init_fini.c
+DIR_SOURCES := implregistry.c init_fini.c implementation.c
include build/makefiles/Makefile.subdir
diff --git a/src/bootstrap/implementation.c b/src/bootstrap/implementation.c
new file mode 100644
index 0000000..d14fa5b
--- /dev/null
+++ b/src/bootstrap/implementation.c
@@ -0,0 +1,423 @@
+/*
+ * 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@netsurf-browser.org>
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+/**
+ * Note: The DOMImplementation Object here is a singleton object. It is
+ * initialised when the libDOM is initialised, it registers itself into
+ * the implreg and clients of it can get it by calling:
+ *
+ * dom_implregistry_get_dom_implementation or
+ * dom_implregistry_get_dom_implementation_list
+ *
+ */
+
+#include <dom/bootstrap/implpriv.h>
+#include <dom/bootstrap/implregistry.h>
+#include <dom/dom.h>
+
+#include <libwapcaplet/libwapcaplet.h>
+
+#include "core/node.h"
+#include "core/document_type.h"
+
+#include "utils/utils.h"
+#include "utils/validate.h"
+#include "utils/namespace.h"
+
+#include "bootstrap/implementation.h"
+
+static dom_alloc _alloc;
+static void *_pw;
+
+static dom_exception impl_get_dom_implementation(
+ struct dom_string *features,
+ struct dom_implementation **impl);
+static dom_exception impl_get_dom_implementation_list(
+ struct dom_string *features,
+ struct dom_implementation_list **list);
+
+static dom_exception impl_implementation_has_feature(
+ struct dom_implementation *impl,
+ struct dom_string *feature,
+ struct dom_string *version,
+ bool *result);
+static dom_exception impl_implementation_create_document_type(
+ struct dom_implementation *impl,
+ struct dom_string *qname,
+ struct dom_string *public_id,
+ struct dom_string *system_id,
+ dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ struct dom_document_type **doctype);
+static dom_exception impl_implementation_create_document(
+ struct dom_implementation *impl,
+ struct dom_string *namespace,
+ struct dom_string *qname,
+ struct dom_document_type *doctype,
+ dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ struct dom_document **doc);
+static dom_exception impl_implementation_get_feature(
+ struct dom_implementation *impl,
+ struct dom_string *feature,
+ struct dom_string *version,
+ void **object);
+static void dom_implementation_destroy(struct dom_implementation *impl);
+
+
+static struct dom_implementation_source dom_impl_src = {
+ impl_get_dom_implementation,
+ impl_get_dom_implementation_list
+};
+
+static struct dom_implementation dom_impl = {
+ impl_implementation_has_feature,
+ impl_implementation_create_document_type,
+ impl_implementation_create_document,
+ impl_implementation_get_feature,
+ 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
+ * \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 impl_get_dom_implementation(
+ struct dom_string *features,
+ struct dom_implementation **impl)
+{
+ UNUSED(features);
+
+ dom_impl.refcnt++;
+
+ *impl = &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
+ * \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 impl_get_dom_implementation_list(
+ struct dom_string *features,
+ struct dom_implementation_list **list)
+{
+ 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 = &dom_impl;
+ i->next = NULL;
+ i->prev = NULL;
+
+ l->head = i;
+
+ 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 impl_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
+ * \return DOM_NO_ERR on success,
+ * DOM_INVALID_CHARACTER_ERR if ::qname is invalid,
+ * DOM_NAMESPACE_ERR if ::qname is malformed.
+ *
+ * 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 impl_implementation_create_document_type(
+ struct dom_implementation *impl,
+ struct dom_string *qname,
+ struct dom_string *public_id,
+ struct dom_string *system_id,
+ dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ struct dom_document_type **doctype)
+{
+ struct dom_document_type *d;
+ struct dom_string *prefix = NULL, *lname = NULL;
+ dom_exception err;
+
+ UNUSED(impl);
+
+ if (qname != NULL && _dom_validate_name(qname) == false)
+ return DOM_INVALID_CHARACTER_ERR;
+
+ err = _dom_namespace_split_qname(qname, &prefix, &lname);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ if ((prefix != NULL && _dom_validate_ncname(prefix) == false) ||
+ (lname != NULL && _dom_validate_ncname(lname) == false))
+ return DOM_NAMESPACE_ERR;
+
+ /* Create the doctype */
+ err = dom_document_type_create(qname, public_id, system_id,
+ alloc, pw, ctx, &d);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ *doctype = d;
+ if (prefix != NULL)
+ dom_string_unref(prefix);
+ if (lname != NULL)
+ dom_string_unref(lname);
+
+ return DOM_NO_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
+ * \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 document will be referenced, so the client need not do this
+ * explicitly. The client must unref the document once it has
+ * finished with it.
+ */
+dom_exception impl_implementation_create_document(
+ struct dom_implementation *impl,
+ struct dom_string *namespace,
+ struct dom_string *qname,
+ struct dom_document_type *doctype,
+ dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ struct dom_document **doc)
+{
+ struct dom_document *d;
+ dom_exception err;
+
+ if (qname != NULL && _dom_validate_name(qname) == false)
+ return DOM_INVALID_CHARACTER_ERR;
+
+ err = _dom_namespace_validate_qname(qname, namespace);
+ if (err != DOM_NO_ERR)
+ return DOM_NAMESPACE_ERR;
+
+ if (doctype != NULL) {
+ if (dom_node_get_parent(doctype) != NULL ||
+ _dom_document_type_get_impl(doctype) !=
+ impl)
+ return DOM_WRONG_DOCUMENT_ERR;
+ }
+
+ /* Create document object */
+ err = dom_document_create(impl, alloc, pw, ctx, &d);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ /* Set its doctype, if necessary */
+ if (doctype != NULL) {
+ struct dom_node *ins_doctype = NULL;
+
+ err = dom_node_append_child((struct dom_node *) d,
+ (struct dom_node *) doctype, &ins_doctype);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref((struct dom_node *) d);
+ return err;
+ }
+
+ /* Not interested in inserted doctype */
+ if (ins_doctype != NULL)
+ dom_node_unref(ins_doctype);
+ }
+
+ /* Create root element and attach it to document */
+ if (qname != NULL) {
+ struct dom_element *e;
+ struct dom_node *inserted;
+
+ err = dom_document_create_element_ns(d, namespace, qname, &e);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref((struct dom_node *) d);
+ return err;
+ }
+
+ err = dom_node_append_child((struct dom_node *) d,
+ (struct dom_node *) e, &inserted);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref((struct dom_node *) e);
+ dom_node_unref((struct dom_node *) d);
+ return err;
+ }
+
+ /* No longer interested in inserted node */
+ dom_node_unref(inserted);
+
+ /* Done with element */
+ dom_node_unref((struct dom_node *) e);
+ }
+
+ *doc = d;
+
+ return DOM_NO_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
+ * \return DOM_NO_ERR.
+ *
+ * Any memory allocated by this call should be allocated using
+ * the provided memory (de)allocation function.
+ */
+dom_exception impl_implementation_get_feature(
+ struct dom_implementation *impl,
+ struct dom_string *feature,
+ struct dom_string *version,
+ void **object)
+{
+ UNUSED(impl);
+ UNUSED(feature);
+ UNUSED(version);
+ UNUSED(object);
+
+ return DOM_NOT_SUPPORTED_ERR;
+}
+
+/**
+ * Destroy a DOM implementation instance
+ *
+ * \param impl The instance to destroy
+ */
+void dom_implementation_destroy(struct dom_implementation *impl)
+{
+ UNUSED(impl);
+
+ /* Nothing to do -- we're statically allocated */
+}
+
+/**
+ * Initialise the DOM implementation
+ *
+ * \param alloc Pointer to memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \return DOM_NO_ERR on success
+ */
+dom_exception _dom_implementation_initialise(dom_alloc alloc, void *pw)
+{
+ _alloc = alloc;
+ _pw = pw;
+
+ return dom_register_source(&dom_impl_src);
+}
+
+/**
+ * Finalise the DOM implementation
+ */
+void _dom_implementation_finalise(void)
+{
+ _alloc = NULL;
+ _pw = NULL;
+}
+
+
diff --git a/src/bootstrap/implementation.h b/src/bootstrap/implementation.h
new file mode 100644
index 0000000..f62077c
--- /dev/null
+++ b/src/bootstrap/implementation.h
@@ -0,0 +1,14 @@
+/*
+ * This file is part of libdom.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
+ */
+
+#ifndef dom_bootstrap_implementation_h_
+#define dom_bootstrap_implementation_h_
+
+dom_exception _dom_implementation_initialise(dom_alloc alloc, void *pw);
+void _dom_implementation_finalise(void);
+
+#endif
diff --git a/src/bootstrap/implregistry.c b/src/bootstrap/implregistry.c
index 9407ee1..91e4068 100644
--- a/src/bootstrap/implregistry.c
+++ b/src/bootstrap/implregistry.c
@@ -11,6 +11,9 @@
#include <dom/bootstrap/implregistry.h>
#include <dom/core/impllist.h>
+#include <dom/core/implementation.h>
+
+void dom_implementation_list_destroy(struct dom_implementation_list *list);
/**
* Item in list of registered DOM implementation sources
@@ -23,14 +26,30 @@ struct dom_impl_src_item {
};
static struct dom_impl_src_item *sources; /**< List of registered sources */
+static dom_alloc alloc;
+static void *pw;
+
+/**
+ * Initialise the implementation registry
+ *
+ * \param allocator The memory allocator
+ * \param ptr Private data pointer of allocator
+ * \return DOM_NO_ERR on success
+ */
+dom_exception dom_implregistry_initialise(
+ dom_alloc allocator, void *ptr)
+{
+ alloc = allocator;
+ pw = ptr;
+
+ return DOM_NO_ERR;
+}
/**
* Retrieve a DOM implementation from the registry
*
* \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
@@ -43,16 +62,14 @@ static struct dom_impl_src_item *sources; /**< List of registered sources */
*/
dom_exception dom_implregistry_get_dom_implementation(
struct dom_string *features,
- struct dom_implementation **impl,
- dom_alloc alloc, void *pw)
+ struct dom_implementation **impl)
{
struct dom_impl_src_item *item;
struct dom_implementation *found = NULL;
dom_exception err;
for (item = sources; item; item = item->next) {
- err = item->source->get_dom_implementation(features, &found,
- alloc, pw);
+ err = item->source->get_dom_implementation(features, &found);
if (err != DOM_NO_ERR)
return err;
@@ -71,14 +88,10 @@ dom_exception dom_implregistry_get_dom_implementation(
*
* \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.
+ * the provided memory (de)allocation function.
*
* List nodes reference the implementation objects they point to.
*
@@ -88,8 +101,7 @@ dom_exception dom_implregistry_get_dom_implementation(
*/
dom_exception dom_implregistry_get_dom_implementation_list(
struct dom_string *features,
- struct dom_implementation_list **list,
- dom_alloc alloc, void *pw)
+ struct dom_implementation_list **list)
{
struct dom_implementation_list *l;
struct dom_impl_src_item *item;
@@ -100,16 +112,15 @@ dom_exception dom_implregistry_get_dom_implementation_list(
return DOM_NO_MEM_ERR;
l->head = NULL;
- l->alloc = alloc;
- l->pw = pw;
l->refcnt = 1;
+ l->destroy = dom_implementation_list_destroy;
for (item = sources; item; item = item->next) {
struct dom_implementation_list *plist = NULL;
struct dom_implementation_list_item *plast = NULL;
err = item->source->get_dom_implementation_list(features,
- &plist, alloc, pw);
+ &plist);
if (err != DOM_NO_ERR) {
dom_implementation_list_unref(l);
return err;
@@ -156,12 +167,9 @@ dom_exception dom_implregistry_get_dom_implementation_list(
* Register a DOM implementation source with the DOM library
*
* \param source The implementation source to register
- * \param alloc Memory (de)allocation function
- * \param pw Pointer to client-specific private data
* \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion.
*/
-dom_exception dom_register_source(struct dom_implementation_source *source,
- dom_alloc alloc, void *pw)
+dom_exception dom_register_source(struct dom_implementation_source *source)
{
struct dom_impl_src_item *item;
@@ -182,3 +190,26 @@ dom_exception dom_register_source(struct dom_implementation_source *source,
return DOM_NO_ERR;
}
+/**
+ * Destroy a dom_implementation_list
+ *
+ * \param list The list to destory
+ */
+void dom_implementation_list_destroy(struct dom_implementation_list *list)
+{
+ struct dom_implementation_list_item *i, *j;
+
+ /* Destroy all list entries */
+ for (i = list->head; i; i = j) {
+ j = i->next;
+
+ /* Unreference the implementation */
+ dom_implementation_unref(i->impl);
+
+ /* And free the entry */
+ alloc(i, 0, pw);
+ }
+
+ /* Free the list object */
+ alloc(list, 0, pw);
+}
diff --git a/src/bootstrap/init_fini.c b/src/bootstrap/init_fini.c
index a5a62a1..f3c7290 100644
--- a/src/bootstrap/init_fini.c
+++ b/src/bootstrap/init_fini.c
@@ -8,9 +8,10 @@
#include <stdbool.h>
#include <dom/bootstrap/init_fini.h>
+#include <dom/bootstrap/implregistry.h>
-#include "core/document.h"
#include "utils/namespace.h"
+#include "bootstrap/implementation.h"
static bool __initialised;
@@ -32,16 +33,21 @@ dom_exception dom_initialise(dom_alloc alloc, void *pw)
return DOM_NO_ERR;
}
- err = _dom_document_initialise(alloc, pw);
+ err = _dom_namespace_initialise(alloc, pw);
if (err != DOM_NO_ERR) {
return err;
}
- err = _dom_namespace_initialise(alloc, pw);
+ err = dom_implregistry_initialise(alloc, pw);
if (err != DOM_NO_ERR) {
return err;
}
+ err = _dom_implementation_initialise(alloc, pw);
+ if (err != DOM_NO_ERR) {
+ return err;
+ }
+
__initialised = true;
return DOM_NO_ERR;
@@ -63,12 +69,9 @@ dom_exception dom_finalise(void)
return DOM_NO_ERR;
}
- err = _dom_namespace_finalise();
- if (err != DOM_NO_ERR) {
- return err;
- }
+ _dom_implementation_finalise();
- err = _dom_document_finalise();
+ err = _dom_namespace_finalise();
if (err != DOM_NO_ERR) {
return err;
}