summaryrefslogtreecommitdiffstats
path: root/tinySAK/src/tsk_object.h
diff options
context:
space:
mode:
Diffstat (limited to 'tinySAK/src/tsk_object.h')
-rw-r--r--tinySAK/src/tsk_object.h173
1 files changed, 173 insertions, 0 deletions
diff --git a/tinySAK/src/tsk_object.h b/tinySAK/src/tsk_object.h
new file mode 100644
index 0000000..00ac3e7
--- /dev/null
+++ b/tinySAK/src/tsk_object.h
@@ -0,0 +1,173 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_object.h
+ * @brief Base object implementation.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TSK_OBJECT_H
+#define TSK_OBJECT_H
+
+#include "tinysak_config.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_object_group
+* Plain object.
+*/
+typedef void tsk_object_t;
+
+/**@ingroup tsk_object_group
+* @def TSK_OBJECT_SAFE_FREE
+* Safely free any well-defined object. If the reference count of the object was equal to 1 then this
+ * object will be freed otherwise the refrence counter will be decremented.
+ * In all case this operation will set the pointer (the object itself) to NULL.<br>
+ * <b>Very Important</b>: Mutexes, Semaphores and CondVars are not well-defined objects. You should never use this macro to destroy them.
+ * @param self The object to free or unref.
+**/
+#define TSK_OBJECT_SAFE_FREE(self) if(self) tsk_object_unref(self), self = tsk_null
+
+/**@ingroup tsk_object_group
+* tag a structure as an object. If this macro is used then you MUST
+* provide a constructor and a destructor functions into an object definition (or meta-data).
+* @ref tsk_object_new or @ref tsk_object_new_2 are used to create the object and @ref tsk_object_unref or @ref tsk_object_delete to destroy it.
+* @code
+* typedef struct person_s{
+* TSK_DECLARE_OBJECT;
+* int id;
+* char* firstName;
+* char* lastName;
+* } person_t;
+* @endcode
+* To create the object:
+* @code
+* // person_def_t: See bellow to understand how to create an object definition.
+* person_t* person = tsk_object_new(person_def_t, "My First Name", "My last Name");
+* @endcode
+* To safely free the object:
+* @code
+* TSK_OBJECT_SAFE_FREE(person);
+* @endcode
+*/
+#define TSK_DECLARE_OBJECT \
+ const void* __base__; \
+ tsk_size_t refCount
+
+/**@ingroup tsk_object_group
+* Internal macro to get the definition of the object.
+*/
+#define TSK_OBJECT_DEF(self) ((const tsk_object_def_t*)self)
+
+/**@ingroup tsk_object_group
+* Meta-data used of define an object.
+* You MUST provide at least a constructor and a destructor. The comparator should
+* be provided if you would like to compare opaque object or sort linked lists.
+* @code
+*
+* // constructor
+* static void* person_create(tsk_object_t * self, va_list * app)
+* {
+* static int unique_id = 0;
+* person_t *person = self;
+* if(person){
+* person->id = ++unique_id;
+* person->firstName = tsk_strdup(va_arg(*app, const char *));
+* person->lastName = tsk_strdup(va_arg(*app, const char *));
+* }
+* return self;
+* }
+*
+* // destructor
+* static void* person_destroy(tsk_object_t * self)
+* {
+* person_t *person = self;
+* if(person){
+* TSK_FREE(person->firstName);
+* TSK_FREE(person->lastName);
+* }
+* return self;
+* }
+*
+* // comparator
+* static int person_cmp(const tsk_object_t *object1, const tsk_object_t *object1)
+* {
+* const person_t *person1 = object1;
+* const person_t *person2 = object2;
+*
+* return (person1 && person2) ? (person1->id - person2->id) : -1;
+* }
+*
+* // Meta-data (Object defnition)
+* static const tsk_object_def_t person_def_s =
+* {
+* sizeof(person_t),
+* person_create,
+* person_destroy,
+* person_cmp,
+* }person_def_t;
+*
+* @endcode
+* Now, to create your object:
+* @code
+* person_t* person = tsk_object_new(person_def_t, "My First Name", "My last Name"); // Will call "person_create" function.
+* @endcode
+* Or
+* @code
+* #define PERSON_CREATE(firstName, lastName) tsk_object_new(person_def_t, firstName, lastName)
+* person_t* person = PERSON_CREATE("My First Name", "My last Name") // For clarity, this form will be used in all projects declared using @ref TSK_DECLARE_OBJECT.
+* @endcode
+* To safely free your object:
+* @code
+* TSK_OBJECT_SAFE_FREE(person); // Will call "person_destroy" function.
+* @endcode
+*/
+typedef struct tsk_object_def_s
+{
+ //! The size of the object.
+ tsk_size_t size;
+ //! Pointer to the constructor.
+ tsk_object_t* (* constructor) (tsk_object_t *, va_list *);
+ //! Pointer to the destructor.
+ tsk_object_t* (* destructor) (tsk_object_t *);
+ //! Pointer to the comparator.
+ int (* comparator) (const tsk_object_t *, const tsk_object_t *);
+}
+tsk_object_def_t;
+
+TINYSAK_API tsk_object_t* tsk_object_new(const tsk_object_def_t *objdef, ...);
+TINYSAK_API tsk_object_t* tsk_object_new_2(const tsk_object_def_t *objdef, va_list* ap);
+TINYSAK_API tsk_size_t tsk_object_sizeof(const tsk_object_t *);
+TINYSAK_API int tsk_object_cmp(const void *self, const tsk_object_t *object);
+TINYSAK_API tsk_object_t* tsk_object_ref(tsk_object_t *self);
+TINYSAK_API tsk_object_t* tsk_object_unref(tsk_object_t *self);
+TINYSAK_API void tsk_object_delete(tsk_object_t *self);
+
+TSK_END_DECLS
+
+#endif /* TSK_OBJECT_H */
+
OpenPOWER on IntegriCloud