From 20267c9da40d931146cd2259001e6e94f511b870 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Thu, 12 Jul 2007 21:24:08 +0000 Subject: Add DOMImplementation, DOMImplementationList Add DOMImplementationRegistry Define DOMImplementationSource and provide API to allow their registration This little lot should permit some kind of sensible DOM bootstrapping. svn path=/trunk/dom/; revision=3403 --- src/bootstrap/Makefile | 53 +++++++++++++ src/bootstrap/implregistry.c | 184 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 src/bootstrap/Makefile create mode 100644 src/bootstrap/implregistry.c (limited to 'src/bootstrap') diff --git a/src/bootstrap/Makefile b/src/bootstrap/Makefile new file mode 100644 index 0000000..6c904cc --- /dev/null +++ b/src/bootstrap/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 = implregistry + +.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/bootstrap/implregistry.c b/src/bootstrap/implregistry.c new file mode 100644 index 0000000..9407ee1 --- /dev/null +++ b/src/bootstrap/implregistry.c @@ -0,0 +1,184 @@ +/* + * 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 + +/** + * Item in list of registered DOM implementation sources + */ +struct dom_impl_src_item { + struct dom_implementation_source *source; /**< Source */ + + struct dom_impl_src_item *next; /**< Next in list */ + struct dom_impl_src_item *prev; /**< Previous in list */ +}; + +static struct dom_impl_src_item *sources; /**< List of registered sources */ + +/** + * 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 + * 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 dom_implregistry_get_dom_implementation( + struct dom_string *features, + struct dom_implementation **impl, + dom_alloc alloc, void *pw) +{ + 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); + if (err != DOM_NO_ERR) + return err; + + if (found != NULL) + break; + } + + *impl = found; + + return DOM_NO_ERR; +} + +/** + * Get a list of DOM implementations that support the requested + * features + * + * \param features String containing required features + * \param list Pointer to location to receive list + * \param alloc Function to (de)allocate memory + * \param pw Pointer to client-specific private data + * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion + * + * Any memory allocated by this call should be allocated using + * the provided memory (de)allocation function. The ::alloc/::pw + * pair must be stored on the list object, such that the list + * and its contents may be freed once they are no longer needed. + * + * List nodes reference the implementation objects they point to. + * + * The list will be referenced, so the client need not do this + * explicitly. The client must unref the list once it has finished + * with it. + */ +dom_exception dom_implregistry_get_dom_implementation_list( + struct dom_string *features, + struct dom_implementation_list **list, + dom_alloc alloc, void *pw) +{ + struct dom_implementation_list *l; + struct dom_impl_src_item *item; + dom_exception err; + + l = alloc(NULL, sizeof(struct dom_implementation_list), pw); + if (l == NULL) + return DOM_NO_MEM_ERR; + + l->head = NULL; + l->alloc = alloc; + l->pw = pw; + l->refcnt = 1; + + 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); + if (err != DOM_NO_ERR) { + dom_implementation_list_unref(l); + return err; + } + + if (plist == NULL) + continue; + + if (plist->head == NULL) { + dom_implementation_list_unref(plist); + continue; + } + + /* Get last item in list for this source */ + for (plast = plist->head; plast; plast = plast->next) { + if (plast->next == NULL) + break; + } + + /* Prepend list for this source onto result list */ + plast->next = l->head; + if (l->head != NULL) + l->head->prev = plast; + l->head = plist->head; + + /* Invalidate entire content of list for this source */ + plist->head = NULL; + + /* And unref it */ + dom_implementation_list_unref(plist); + } + + if (l->head == NULL) { + *list = NULL; + dom_implementation_list_unref(l); + } else { + *list = l; + } + + return DOM_NO_ERR; +} + +/** + * 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) +{ + struct dom_impl_src_item *item; + + item = alloc(NULL, sizeof(struct dom_impl_src_item), pw); + if (item == NULL) + return DOM_NO_MEM_ERR; + + item->source = source; + + item->next = sources; + item->prev = NULL; + + if (sources != NULL) + sources->prev = item; + + sources = item; + + return DOM_NO_ERR; +} + -- cgit v1.2.3