diff options
Diffstat (limited to 'tinySAK/src/tsk_object.h')
-rw-r--r-- | tinySAK/src/tsk_object.h | 173 |
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 */ + |