183 lines
5.9 KiB
C
Executable File
183 lines
5.9 KiB
C
Executable File
/* Copyright (C) 2010-2013 Mamadou Diop.
|
|
* Copyright (C) 2013 Doubango Telecom <http://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.
|
|
*/
|
|
#ifndef TSK_OBJECT_H
|
|
#define TSK_OBJECT_H
|
|
|
|
#include "tinysak_config.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
TSK_BEGIN_DECLS
|
|
|
|
#define TSK_OBJECT(self) ((tsk_object_t*)(self))
|
|
|
|
/**@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
|
|
|
|
#define TSK_OBJECT_SAFE_FREE_ARRAY(self, count) { \
|
|
int __i; \
|
|
for(__i = 0; __i < (count); ++__i) \
|
|
TSK_OBJECT_SAFE_FREE((self)[__i]); \
|
|
}
|
|
#define TSK_OBJECT_SAFE_FREE_TABLE(self) TSK_OBJECT_SAFE_FREE_ARRAY((self), (sizeof((self))/sizeof((self)[0])))
|
|
|
|
/**@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* __def__; /**< Opaque data holding a pointer to the actual meta-data(size, constructor, destructor and comparator) */ \
|
|
volatile long refCount /**< Reference counter. */
|
|
|
|
/**@ingroup tsk_object_group
|
|
* Internal macro to get the definition of the object.
|
|
*/
|
|
#define TSK_OBJECT_DEF(self) ((const tsk_object_def_t*)self)
|
|
|
|
/** Object meta-data (definition) */
|
|
typedef struct tsk_object_header_s {
|
|
TSK_DECLARE_OBJECT;
|
|
}
|
|
tsk_object_header_t;
|
|
#define TSK_OBJECT_HEADER(object) ((tsk_object_header_t*)object)
|
|
|
|
/**@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 tsk_size_t tsk_object_get_refcount(tsk_object_t *self);
|
|
TINYSAK_API void tsk_object_delete(tsk_object_t *self);
|
|
|
|
TSK_END_DECLS
|
|
|
|
#endif /* TSK_OBJECT_H */
|
|
|