summaryrefslogtreecommitdiff
path: root/src/libmowgli/object/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmowgli/object/class.c')
-rw-r--r--src/libmowgli/object/class.c131
1 files changed, 131 insertions, 0 deletions
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);
+}