From 399da01ae4eb5c5e3e9349bacc2063c946c3d4a1 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Tue, 11 Aug 2009 11:17:23 +0000 Subject: Merge the branches/struggleyb/libdom-remain back to trunk. svn path=/trunk/dom/; revision=9191 --- src/bootstrap/Makefile | 2 +- src/bootstrap/implementation.c | 423 +++++++++++++++++++++++++++++++++++++++++ src/bootstrap/implementation.h | 14 ++ src/bootstrap/implregistry.c | 71 +++++-- src/bootstrap/init_fini.c | 19 +- 5 files changed, 500 insertions(+), 29 deletions(-) create mode 100644 src/bootstrap/implementation.c create mode 100644 src/bootstrap/implementation.h (limited to 'src/bootstrap') 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 + * Copyright 2009 Bo Yang + */ + +/** + * 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 +#include +#include + +#include + +#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 + */ + +#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 #include +#include + +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 #include +#include -#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; } -- cgit v1.2.3