diff options
Diffstat (limited to 'src/libmowgli/object')
-rw-r--r-- | src/libmowgli/object/Makefile | 21 | ||||
-rw-r--r-- | src/libmowgli/object/class.c | 131 | ||||
-rw-r--r-- | src/libmowgli/object/class.h | 60 | ||||
-rw-r--r-- | src/libmowgli/object/message.c | 142 | ||||
-rw-r--r-- | src/libmowgli/object/message.h | 42 | ||||
-rw-r--r-- | src/libmowgli/object/metadata.c | 104 | ||||
-rw-r--r-- | src/libmowgli/object/metadata.h | 36 | ||||
-rw-r--r-- | src/libmowgli/object/object.c | 164 | ||||
-rw-r--r-- | src/libmowgli/object/object.h | 42 |
9 files changed, 742 insertions, 0 deletions
diff --git a/src/libmowgli/object/Makefile b/src/libmowgli/object/Makefile new file mode 100644 index 0000000..1ac3ff3 --- /dev/null +++ b/src/libmowgli/object/Makefile @@ -0,0 +1,21 @@ +include ../../../extra.mk + +STATIC_PIC_LIB_NOINST = ${LIBMOWGLI_SHARED_OBJECT} +STATIC_LIB_NOINST = ${LIBMOWGLI_STATIC_OBJECT} + +SRCS = object.c \ + class.c \ + message.c \ + metadata.c + +INCLUDES = object.h \ + class.h \ + message.h \ + metadata.h + +include ../../../buildsys.mk + +includesubdir = $(PACKAGE_NAME)/object + +CPPFLAGS += -I. -I.. -I../../.. -DMOWGLI_CORE + diff --git a/src/libmowgli/object/class.c b/src/libmowgli/object/class.c new file mode 100644 index 0000000..9bddf79 --- /dev/null +++ b/src/libmowgli/object/class.c @@ -0,0 +1,131 @@ +/* + * libmowgli: A collection of useful routines for programming. + * class.c: Object class and type management, cast checking. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mowgli.h" + +static mowgli_patricia_t *mowgli_object_class_dict = NULL; + +static void _object_key_canon(char *str) +{ + while (*str) + { + *str = toupper(*str); + str++; + } +} + +void mowgli_object_class_init(mowgli_object_class_t *klass, const char *name, mowgli_destructor_t des, mowgli_boolean_t dynamic) +{ + /* if the object_class dictionary has not yet been initialized, we will want to do that. */ + if (mowgli_object_class_dict == NULL) + mowgli_object_class_dict = mowgli_patricia_create(_object_key_canon); + + if (klass == NULL) + mowgli_throw_exception_fatal(mowgli.object_class.invalid_object_class_exception); + + if (mowgli_object_class_find_by_name(name) != NULL) + mowgli_throw_exception_fatal(mowgli.object_class.duplicate_object_class_exception); + + /* initialize object_class::name */ + klass->name = mowgli_strdup(name); + + /* initialize object_class::derivitives */ + klass->derivitives.head = NULL; + klass->derivitives.tail = NULL; + klass->derivitives.count = 0; + + /* initialize object_class::destructor */ + klass->destructor = des != NULL ? des : mowgli_free; + + /* initialize object_class::dynamic */ + klass->dynamic = dynamic; + + /* add to the object_class index */ + mowgli_patricia_add(mowgli_object_class_dict, klass->name, klass); +} + +int mowgli_object_class_check_cast(mowgli_object_class_t *klass1, mowgli_object_class_t *klass2) +{ + mowgli_node_t *n; + + if (klass1 == NULL || klass2 == NULL) + mowgli_throw_exception_val(mowgli.object_class.invalid_object_class_exception, 0); + + MOWGLI_LIST_FOREACH(n, klass1->derivitives.head) + { + mowgli_object_class_t *tklass = (mowgli_object_class_t *) n->data; + + if (tklass == klass2) + return 1; + } + + return 0; +} + +void mowgli_object_class_set_derivitive(mowgli_object_class_t *klass, mowgli_object_class_t *parent) +{ + if (klass == NULL || parent == NULL) + mowgli_throw_exception_fatal(mowgli.object_class.invalid_object_class_exception); + + mowgli_node_add(klass, mowgli_node_create(), &parent->derivitives); +} + +void *mowgli_object_class_reinterpret_impl(/* mowgli_object_t */ void *opdata, mowgli_object_class_t *klass) +{ + mowgli_object_t *object = mowgli_object(opdata); + + /* this can possibly happen at runtime .. lets not make it a fatal exception. */ + return_val_if_fail(object != NULL, NULL); + return_val_if_fail(klass != NULL, NULL); + + if (mowgli_object_class_check_cast(object->klass, klass)) + return object; + + mowgli_log("Invalid reinterpreted cast from %s<%p> to %s", object->klass->name, klass->name); + return NULL; +} + +mowgli_object_class_t *mowgli_object_class_find_by_name(const char *name) +{ + return mowgli_patricia_retrieve(mowgli_object_class_dict, name); +} + +void mowgli_object_class_destroy(mowgli_object_class_t *klass) +{ + mowgli_node_t *n, *tn; + + if (klass == NULL) + mowgli_throw_exception_fatal(mowgli.object_class.invalid_object_class_exception); + + if (klass->dynamic != TRUE) + mowgli_throw_exception_fatal(mowgli.object_class.nondynamic_object_class_exception); + + MOWGLI_LIST_FOREACH_SAFE(n, tn, klass->derivitives.head) + { + mowgli_node_delete(n, &klass->derivitives); + mowgli_node_free(n); + } + + mowgli_free(klass->name); + mowgli_free(klass); +} diff --git a/src/libmowgli/object/class.h b/src/libmowgli/object/class.h new file mode 100644 index 0000000..9612aa4 --- /dev/null +++ b/src/libmowgli/object/class.h @@ -0,0 +1,60 @@ +/* + * libmowgli: A collection of useful routines for programming. + * class.h: Object class and type management, cast checking. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MOWGLI_OBJECT_CLASS_H__ +#define __MOWGLI_OBJECT_CLASS_H__ + +typedef void (*mowgli_destructor_t)(void *); + +typedef struct { + char *name; + mowgli_list_t derivitives; + mowgli_destructor_t destructor; + mowgli_boolean_t dynamic; + mowgli_list_t message_handlers; +} mowgli_object_class_t; + +extern void mowgli_object_class_init(mowgli_object_class_t *klass, const char *name, mowgli_destructor_t des, mowgli_boolean_t dynamic); +extern int mowgli_object_class_check_cast(mowgli_object_class_t *klass1, mowgli_object_class_t *klass2); +extern void mowgli_object_class_set_derivitive(mowgli_object_class_t *klass, mowgli_object_class_t *parent); +extern void *mowgli_object_class_reinterpret_impl(/* mowgli_object_t */ void *object, mowgli_object_class_t *klass); +extern mowgli_object_class_t *mowgli_object_class_find_by_name(const char *name); +extern void mowgli_object_class_destroy(mowgli_object_class_t *klass); + +#define MOWGLI_REINTERPRET_CAST(object, klass) (klass *) mowgli_object_class_reinterpret_impl(object, mowgli_object_class_find_by_name( # klass )); + +#define mowgli_forced_cast(from_type, to_type, from, to)\ +do { \ + union cast_union \ + { \ + to_type out; \ + from_type in; \ + } u; \ + typedef int cant_use_union_cast[ \ + sizeof (from_type) == sizeof (u) \ + && sizeof (from_type) == sizeof (to_type) ? 1 : -1];\ + u.in = from; \ + to = u.out; \ +} while (0) + +#endif diff --git a/src/libmowgli/object/message.c b/src/libmowgli/object/message.c new file mode 100644 index 0000000..e4328c8 --- /dev/null +++ b/src/libmowgli/object/message.c @@ -0,0 +1,142 @@ +/* + * libmowgli: A collection of useful routines for programming. + * messaging.c: Object event notification and message passing. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mowgli.h" + +void mowgli_object_class_message_handler_attach(mowgli_object_class_t *klass, mowgli_object_message_handler_t *sig) +{ + if (klass == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_object_class_exception); + + if (sig == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_signal_exception); + + mowgli_node_add(sig, mowgli_node_create(), &klass->message_handlers); +} + +void mowgli_object_class_message_handler_detach(mowgli_object_class_t *klass, mowgli_object_message_handler_t *sig) +{ + mowgli_node_t *n; + + if (klass == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_object_class_exception); + + if (sig == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_signal_exception); + + n = mowgli_node_find(sig, &klass->message_handlers); + mowgli_node_delete(n, &klass->message_handlers); + mowgli_node_free(n); +} + +void mowgli_object_message_handler_attach(mowgli_object_t *self, mowgli_object_message_handler_t *sig) +{ + if (self == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_object_exception); + + if (sig == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_signal_exception); + + mowgli_node_add(sig, mowgli_node_create(), &self->message_handlers); +} + +void mowgli_object_message_handler_detach(mowgli_object_t *self, mowgli_object_message_handler_t *sig) +{ + mowgli_node_t *n; + + if (self == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_object_exception); + + if (sig == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_signal_exception); + + n = mowgli_node_find(sig, &self->message_handlers); + mowgli_node_delete(n, &self->message_handlers); + mowgli_node_free(n); +} + +void mowgli_object_message_broadcast(mowgli_object_t *self, const char *name, ...) +{ + mowgli_argstack_t *stack; + mowgli_object_message_handler_t *sig = NULL; + mowgli_node_t *n; + va_list va; + + if (self == NULL) + mowgli_throw_exception(mowgli.object_messaging.invalid_object_exception); + + if (name == NULL) + mowgli_throw_exception(mowgli.null_pointer_exception); + + /* try to find a signal to compile the argument stack from, we start with self::klass first. */ + MOWGLI_LIST_FOREACH(n, self->klass->message_handlers.head) + { + mowgli_object_message_handler_t *sig2 = (mowgli_object_message_handler_t *) n->data; + + if (!strcasecmp(sig2->name, name)) + { + sig = sig2; + break; + } + } + + if (sig == NULL) + { + MOWGLI_LIST_FOREACH(n, self->klass->message_handlers.head) + { + mowgli_object_message_handler_t *sig2 = (mowgli_object_message_handler_t *) n->data; + + if (!strcasecmp(sig2->name, name)) + { + sig = sig2; + break; + } + } + } + + /* return if no signals found, else compile the argstack */ + if (sig == NULL) + return; + + va_start(va, name); + stack = mowgli_argstack_create_from_va_list(sig->descstr, va); + va_end(va); + + MOWGLI_LIST_FOREACH(n, self->klass->message_handlers.head) + { + sig = (mowgli_object_message_handler_t *) n->data; + + if (!strcasecmp(sig->name, name) && sig->handler != NULL) + sig->handler(self, sig, stack); + } + + MOWGLI_LIST_FOREACH(n, self->message_handlers.head) + { + sig = (mowgli_object_message_handler_t *) n->data; + + if (!strcasecmp(sig->name, name) && sig->handler != NULL) + sig->handler(self, sig, stack); + } + + mowgli_object_unref(stack); +} diff --git a/src/libmowgli/object/message.h b/src/libmowgli/object/message.h new file mode 100644 index 0000000..4a49d00 --- /dev/null +++ b/src/libmowgli/object/message.h @@ -0,0 +1,42 @@ +/* + * libmowgli: A collection of useful routines for programming. + * message.h: Object event notification and message passing. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MOWGLI_OBJECT_MESSAGING_H__ +#define __MOWGLI_OBJECT_MESSAGING_H__ + +typedef struct mowgli_object_message_handler_ mowgli_object_message_handler_t; +typedef void (*mowgli_object_messaging_func_t)(mowgli_object_t *self, mowgli_object_message_handler_t *sig, mowgli_argstack_t *argstack); + +struct mowgli_object_message_handler_ { + char *name; + char *descstr; + mowgli_object_messaging_func_t handler; +}; + +extern void mowgli_object_class_message_handler_attach(mowgli_object_class_t *klass, mowgli_object_message_handler_t *sig); +extern void mowgli_object_class_message_handler_detach(mowgli_object_class_t *klass, mowgli_object_message_handler_t *sig); +extern void mowgli_object_message_handler_attach(mowgli_object_t *self, mowgli_object_message_handler_t *sig); +extern void mowgli_object_message_handler_detach(mowgli_object_t *self, mowgli_object_message_handler_t *sig); +extern void mowgli_object_message_broadcast(mowgli_object_t *self, const char *name, ...); + +#endif diff --git a/src/libmowgli/object/metadata.c b/src/libmowgli/object/metadata.c new file mode 100644 index 0000000..742e0dc --- /dev/null +++ b/src/libmowgli/object/metadata.c @@ -0,0 +1,104 @@ +/* + * libmowgli: A collection of useful routines for programming. + * metadata.c: Object metadata. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mowgli.h" + +void mowgli_object_metadata_associate(mowgli_object_t *self, const char *key, void *value) +{ + mowgli_object_metadata_entry_t *e = NULL; + mowgli_node_t *n; + + if (self == NULL) + mowgli_throw_exception(mowgli.object_metadata.invalid_object_exception); + + if (key == NULL) + mowgli_throw_exception(mowgli.null_pointer_exception); + + MOWGLI_LIST_FOREACH(n, self->metadata.head) + { + e = (mowgli_object_metadata_entry_t *) n->data; + + if (!strcasecmp(e->name, key)) + break; + } + + if (e != NULL) + { + e->data = value; + return; + } + + e = mowgli_alloc(sizeof(mowgli_object_metadata_entry_t)); + e->name = mowgli_strdup(key); + e->data = value; + + mowgli_node_add(e, mowgli_node_create(), &self->metadata); +} + +void mowgli_object_metadata_dissociate(mowgli_object_t *self, const char *key) +{ + mowgli_object_metadata_entry_t *e; + mowgli_node_t *n, *tn; + + if (self == NULL) + mowgli_throw_exception(mowgli.object_metadata.invalid_object_exception); + + if (key == NULL) + mowgli_throw_exception(mowgli.null_pointer_exception); + + MOWGLI_LIST_FOREACH_SAFE(n, tn, self->metadata.head) + { + e = (mowgli_object_metadata_entry_t *) n->data; + + if (!strcasecmp(e->name, key)) + { + mowgli_node_delete(n, &self->metadata); + mowgli_node_free(n); + + mowgli_free(e->name); + mowgli_free(e); + } + } +} + +void *mowgli_object_metadata_retrieve(mowgli_object_t *self, const char *key) +{ + mowgli_object_metadata_entry_t *e; + mowgli_node_t *n; + + if (self == NULL) + mowgli_throw_exception_val(mowgli.object_metadata.invalid_object_exception, NULL); + + if (key == NULL) + mowgli_throw_exception_val(mowgli.null_pointer_exception, NULL); + + MOWGLI_LIST_FOREACH(n, self->metadata.head) + { + e = (mowgli_object_metadata_entry_t *) n->data; + + if (!strcasecmp(e->name, key)) + return e->data; + } + + return NULL; +} diff --git a/src/libmowgli/object/metadata.h b/src/libmowgli/object/metadata.h new file mode 100644 index 0000000..0cdda69 --- /dev/null +++ b/src/libmowgli/object/metadata.h @@ -0,0 +1,36 @@ +/* + * libmowgli: A collection of useful routines for programming. + * metadata.h: Object metadata. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MOWGLI_OBJECT_METADATA_H__ +#define __MOWGLI_OBJECT_METADATA_H__ + +typedef struct { + char *name; + void *data; +} mowgli_object_metadata_entry_t; + +extern void mowgli_object_metadata_associate(mowgli_object_t *self, const char *key, void *value); +extern void mowgli_object_metadata_dissociate(mowgli_object_t *self, const char *key); +extern void *mowgli_object_metadata_retrieve(mowgli_object_t *self, const char *key); + +#endif diff --git a/src/libmowgli/object/object.c b/src/libmowgli/object/object.c new file mode 100644 index 0000000..7b24ea7 --- /dev/null +++ b/src/libmowgli/object/object.c @@ -0,0 +1,164 @@ +/* + * libmowgli: A collection of useful routines for programming. + * object.c: Object management. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mowgli.h" + +/* + * mowgli_object_init + * + * Populates the object manager part of an object. + * + * Inputs: + * - pointer to object manager area + * - (optional) name of object + * - (optional) class of object + * - (optional) custom destructor + * + * Outputs: + * - none + * + * Side Effects: + * - none + */ +void mowgli_object_init(mowgli_object_t *obj, const char *name, mowgli_object_class_t *klass, mowgli_destructor_t des) +{ + return_if_fail(obj != NULL); + + if (name != NULL) + obj->name = mowgli_strdup(name); + + if (klass != NULL) + obj->klass = klass; + else + { + mowgli_object_class_t *tmp = mowgli_alloc(sizeof(mowgli_object_class_t)); + mowgli_object_class_init(tmp, name, des, TRUE); + obj->klass = tmp; + } + + obj->refcount = 1; + + obj->message_handlers.head = NULL; + obj->message_handlers.tail = NULL; + obj->message_handlers.count = 0; + + obj->metadata.head = NULL; + obj->metadata.tail = NULL; + obj->metadata.count = 0; + + mowgli_object_message_broadcast(obj, "create"); +} + +/* + * mowgli_object_init_from_class + * + * Populates the object manager part of an object from an object class. + * + * Inputs: + * - pointer to object manager area + * - class of object + * + * Outputs: + * - none + * + * Side Effects: + * - none + */ +void +mowgli_object_init_from_class(mowgli_object_t *obj, const char *name, + mowgli_object_class_t *klass) +{ + return_if_fail(obj != NULL); + return_if_fail(klass != NULL); + + mowgli_object_init(obj, name, klass, NULL); +} + +/* + * mowgli_object_ref + * + * Increment the reference counter on an object. + * + * Inputs: + * - the object to refcount + * + * Outputs: + * - none + * + * Side Effects: + * - none + */ +void * mowgli_object_ref(void *object) +{ + return_val_if_fail(object != NULL, NULL); + + mowgli_object(object)->refcount++; + + return object; +} + +/* + * mowgli_object_unref + * + * Decrement the reference counter on an object. + * + * Inputs: + * - the object to refcount + * + * Outputs: + * - none + * + * Side Effects: + * - if the refcount is 0, the object is destroyed. + */ +void mowgli_object_unref(void *object) +{ + mowgli_object_t *obj = mowgli_object(object); + + return_if_fail(object != NULL); + + obj->refcount--; + + if (obj->refcount <= 0) + { + mowgli_object_message_broadcast(obj, "destroy"); + + if (obj->name != NULL) + free(obj->name); + + if (obj->klass != NULL) + { + mowgli_destructor_t destructor = obj->klass->destructor; + + if (obj->klass->dynamic == TRUE) + mowgli_object_class_destroy(obj->klass); + + if (destructor != NULL) + destructor(obj); + else + free(obj); + } + else + mowgli_throw_exception(mowgli.object.invalid_object_class_exception); + } +} diff --git a/src/libmowgli/object/object.h b/src/libmowgli/object/object.h new file mode 100644 index 0000000..0f13ce1 --- /dev/null +++ b/src/libmowgli/object/object.h @@ -0,0 +1,42 @@ +/* + * libmowgli: A collection of useful routines for programming. + * object.h: Object management. + * + * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MOWGLI_OBJECT_H__ +#define __MOWGLI_OBJECT_H__ + +typedef struct { + char *name; + int refcount; + mowgli_object_class_t *klass; + mowgli_list_t message_handlers; + mowgli_list_t metadata; +} mowgli_object_t; + +extern void mowgli_object_init(mowgli_object_t *, const char *name, mowgli_object_class_t *klass, mowgli_destructor_t destructor); +extern void mowgli_object_init_from_class(mowgli_object_t *, const char *, mowgli_object_class_t *klass); +extern void *mowgli_object_ref(void *); +extern void mowgli_object_unref(void *); + +#define mowgli_object(x) ((mowgli_object_t *) x) + +#endif |