2012-09-04 00:03:02 -07:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2012-04-05 08:31:15 -07:00
# include <Eina.h>
2012-05-01 00:40:14 -07:00
# include "Eo.h"
# include "eo_private.h"
2012-04-05 08:31:15 -07:00
2012-06-03 01:42:12 -07:00
/* The last id that should be reserved for statically allocated classes. */
2012-08-20 00:56:17 -07:00
# define EO_CLASS_IDS_FIRST 1
2012-07-10 07:01:45 -07:00
# define EO_OP_IDS_FIRST 1
2012-04-16 05:36:42 -07:00
2012-05-01 00:40:14 -07:00
/* Used inside the class_get functions of classes, see #EO_DEFINE_CLASS */
EAPI Eina_Lock _eo_class_creation_lock ;
int _eo_log_dom = - 1 ;
2012-04-05 08:31:15 -07:00
2012-05-01 00:40:14 -07:00
static Eo_Class * * _eo_classes ;
static Eo_Class_Id _eo_classes_last_id ;
static Eina_Bool _eo_init_count = 0 ;
2012-07-10 07:01:45 -07:00
static Eo_Op _eo_ops_last_id = 0 ;
2012-04-05 08:31:15 -07:00
2012-06-10 07:04:53 -07:00
static void _eo_condtor_reset ( Eo * obj ) ;
2012-05-06 05:03:21 -07:00
static inline void * _eo_data_get ( const Eo * obj , const Eo_Class * klass ) ;
2012-05-06 05:03:26 -07:00
static inline Eo * _eo_ref ( Eo * obj ) ;
static inline void _eo_unref ( Eo * obj ) ;
2012-07-26 05:21:01 -07:00
static const Eo_Class * _eo_op_class_get ( Eo_Op op ) ;
static const Eo_Op_Description * _eo_op_id_desc_get ( Eo_Op op ) ;
2012-04-05 08:31:15 -07:00
2012-05-06 05:03:13 -07:00
typedef struct
{
2012-07-18 05:27:09 -07:00
const Eo_Class * kls ;
2012-05-06 05:03:13 -07:00
} Eo_Kls_Itr ;
2012-05-01 00:40:14 -07:00
struct _Eo {
2012-04-15 04:57:25 -07:00
EINA_MAGIC
2012-06-06 04:41:47 -07:00
EINA_INLIST ;
2012-05-01 00:40:14 -07:00
Eo * parent ;
2012-06-06 04:41:47 -07:00
Eina_Inlist * children ;
2012-05-01 00:40:14 -07:00
const Eo_Class * klass ;
2012-04-05 08:31:15 -07:00
int refcount ;
2012-04-17 08:22:22 -07:00
# ifndef NDEBUG
Eina_Inlist * xrefs ;
# endif
2012-04-05 08:31:15 -07:00
Eina_List * composite_objects ;
2012-05-06 05:03:13 -07:00
Eo_Kls_Itr mro_itr ;
2012-04-05 08:31:15 -07:00
2012-06-13 04:38:56 -07:00
Eina_Bool do_error : 1 ;
2012-06-10 07:04:53 -07:00
Eina_Bool condtor_done : 1 ;
2012-06-07 03:54:15 -07:00
Eina_Bool composite : 1 ;
2012-05-07 23:56:59 -07:00
Eina_Bool del : 1 ;
2012-05-21 04:45:32 -07:00
Eina_Bool manual_free : 1 ;
2012-04-05 08:31:15 -07:00
} ;
/* Start of Dich */
2012-07-10 07:01:54 -07:00
/* How we search and store the implementations in classes. */
2012-07-10 07:01:45 -07:00
# define DICH_CHAIN_LAST_BITS 5
# define DICH_CHAIN_LAST_SIZE (1 << DICH_CHAIN_LAST_BITS)
# define DICH_CHAIN1(x) ((x) / DICH_CHAIN_LAST_SIZE)
# define DICH_CHAIN_LAST(x) ((x) % DICH_CHAIN_LAST_SIZE)
2012-04-05 08:31:15 -07:00
2012-06-03 01:42:12 -07:00
# define OP_CLASS_OFFSET_GET(x) (((x) >> EO_OP_CLASS_OFFSET) & 0xffff)
2012-04-05 08:31:15 -07:00
2012-05-06 05:03:23 -07:00
# define ID_CLASS_GET(id) ({ \
( Eo_Class * ) ( ( id < = _eo_classes_last_id ) & & ( id > 0 ) ) ? \
( _eo_classes [ id - 1 ] ) : NULL ; \
} )
2012-05-01 00:40:14 -07:00
# define EO_ALIGN_SIZE(size) \
2012-04-19 01:52:25 -07:00
( ( size ) + ( sizeof ( void * ) - ( ( size ) % sizeof ( void * ) ) ) )
2012-04-05 08:31:15 -07:00
typedef struct _Dich_Chain1 Dich_Chain1 ;
typedef struct
{
2012-05-01 00:40:14 -07:00
eo_op_func_type func ;
2012-05-07 23:56:57 -07:00
const Eo_Class * src ;
2012-04-05 08:31:15 -07:00
} op_type_funcs ;
struct _Dich_Chain1
{
2012-05-06 05:03:23 -07:00
op_type_funcs * funcs ;
2012-04-05 08:31:15 -07:00
} ;
2012-04-19 01:52:25 -07:00
typedef struct
{
2012-07-10 07:01:54 -07:00
const Eo_Class * klass ;
size_t offset ;
2012-05-01 00:40:14 -07:00
} Eo_Extension_Data_Offset ;
2012-04-19 01:52:25 -07:00
2012-05-01 00:40:14 -07:00
struct _Eo_Class
2012-04-05 08:31:15 -07:00
{
2012-04-23 01:10:04 -07:00
EINA_MAGIC
2012-05-01 00:40:14 -07:00
Eo_Class_Id class_id ;
const Eo_Class * parent ;
const Eo_Class_Description * desc ;
2012-07-15 05:27:56 -07:00
Dich_Chain1 * chain ; /**< The size is chain size */
2012-07-10 07:01:45 -07:00
size_t chain_size ;
size_t base_id ;
2012-06-13 04:39:02 -07:00
const Eo_Class * * extensions ;
2012-04-11 00:05:14 -07:00
2012-05-01 00:40:14 -07:00
Eo_Extension_Data_Offset * extn_data_off ;
2012-04-19 01:52:25 -07:00
size_t extn_data_size ;
2012-05-01 00:40:14 -07:00
const Eo_Class * * mro ;
2012-05-15 07:16:58 -07:00
Eo_Kls_Itr mro_itr ;
2012-04-11 00:05:14 -07:00
2012-04-11 00:05:39 -07:00
size_t data_offset ; /* < Offset of the data within object data. */
2012-04-05 08:31:15 -07:00
Eina_Bool constructed : 1 ;
} ;
2012-05-07 23:56:57 -07:00
static inline void
2012-07-10 07:01:45 -07:00
_dich_chain_alloc ( Dich_Chain1 * chain1 )
2012-05-07 23:56:57 -07:00
{
if ( ! chain1 - > funcs )
{
2012-07-10 07:01:45 -07:00
chain1 - > funcs = calloc ( DICH_CHAIN_LAST_SIZE , sizeof ( * ( chain1 - > funcs ) ) ) ;
2012-05-07 23:56:57 -07:00
}
}
static inline void
_dich_copy_all ( Eo_Class * dst , const Eo_Class * src )
{
2012-07-15 00:56:02 -07:00
Eo_Op i ;
2012-05-07 23:56:57 -07:00
const Dich_Chain1 * sc1 = src - > chain ;
Dich_Chain1 * dc1 = dst - > chain ;
2012-07-15 05:27:56 -07:00
for ( i = 0 ; i < src - > chain_size ; i + + , sc1 + + , dc1 + + )
2012-05-07 23:56:57 -07:00
{
if ( sc1 - > funcs )
{
size_t j ;
2012-05-14 08:20:46 -07:00
2012-07-10 07:01:45 -07:00
_dich_chain_alloc ( dc1 ) ;
2012-05-07 23:56:57 -07:00
const op_type_funcs * sf = sc1 - > funcs ;
op_type_funcs * df = dc1 - > funcs ;
2012-07-10 07:01:45 -07:00
for ( j = 0 ; j < DICH_CHAIN_LAST_SIZE ; j + + , df + + , sf + + )
2012-05-07 23:56:57 -07:00
{
if ( sf - > func )
{
memcpy ( df , sf , sizeof ( * df ) ) ;
}
}
}
}
}
static inline const op_type_funcs *
2012-07-10 07:01:45 -07:00
_dich_func_get ( const Eo_Class * klass , Eo_Op op )
2012-04-05 08:31:15 -07:00
{
2012-07-10 07:01:45 -07:00
size_t idx1 = DICH_CHAIN1 ( op ) ;
if ( EINA_UNLIKELY ( idx1 > = klass - > chain_size ) )
2012-04-05 08:31:15 -07:00
return NULL ;
2012-07-10 07:01:45 -07:00
Dich_Chain1 * chain1 = & klass - > chain [ idx1 ] ;
if ( EINA_UNLIKELY ( ! chain1 - > funcs ) )
return NULL ;
return & chain1 - > funcs [ DICH_CHAIN_LAST ( op ) ] ;
2012-04-05 08:31:15 -07:00
}
static inline void
2012-07-10 07:01:45 -07:00
_dich_func_set ( Eo_Class * klass , Eo_Op op , eo_op_func_type func )
2012-04-05 08:31:15 -07:00
{
2012-07-10 07:01:45 -07:00
size_t idx1 = DICH_CHAIN1 ( op ) ;
2012-05-06 05:03:23 -07:00
Dich_Chain1 * chain1 = & klass - > chain [ idx1 ] ;
2012-07-10 07:01:45 -07:00
_dich_chain_alloc ( chain1 ) ;
2012-07-26 05:21:01 -07:00
if ( chain1 - > funcs [ DICH_CHAIN_LAST ( op ) ] . src = = klass )
{
const Eo_Class * op_kls = _eo_op_class_get ( op ) ;
const Eo_Op_Description * op_desc = _eo_op_id_desc_get ( op ) ;
2012-07-26 05:34:04 -07:00
ERR ( " Already set function for op %x (%s:%s). Overriding with func %p " ,
2012-07-26 05:21:01 -07:00
op , op_kls - > desc - > name , op_desc - > name , func ) ;
}
2012-05-06 05:03:23 -07:00
chain1 - > funcs [ DICH_CHAIN_LAST ( op ) ] . func = func ;
2012-05-07 23:56:57 -07:00
chain1 - > funcs [ DICH_CHAIN_LAST ( op ) ] . src = klass ;
2012-04-05 08:31:15 -07:00
}
static inline void
2012-05-07 23:56:57 -07:00
_dich_func_clean_all ( Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2012-05-06 05:03:23 -07:00
size_t i ;
2012-04-05 08:31:15 -07:00
Dich_Chain1 * chain1 = klass - > chain ;
2012-07-15 05:27:56 -07:00
for ( i = 0 ; i < klass - > chain_size ; i + + , chain1 + + )
2012-05-06 05:03:23 -07:00
{
if ( chain1 - > funcs )
free ( chain1 - > funcs ) ;
2012-04-05 08:31:15 -07:00
}
2012-05-06 05:03:23 -07:00
free ( klass - > chain ) ;
klass - > chain = NULL ;
2012-04-05 08:31:15 -07:00
}
/* END OF DICH */
2012-05-01 00:40:14 -07:00
static const Eo_Op_Description noop_desc =
2012-06-10 04:37:26 -07:00
EO_OP_DESCRIPTION ( EO_NOOP , " No operation. " ) ;
2012-04-18 00:58:34 -07:00
2012-07-10 07:01:45 -07:00
static const Eo_Class *
_eo_op_class_get ( Eo_Op op )
{
/* FIXME: Make it fast. */
Eo_Class * * itr = _eo_classes ;
2012-09-03 00:26:57 -07:00
int mid , max , min ;
min = 0 ;
max = _eo_classes_last_id - 1 ;
while ( min < = max )
2012-07-10 07:01:45 -07:00
{
2012-09-03 00:26:57 -07:00
mid = ( min + max ) / 2 ;
if ( itr [ mid ] - > base_id + itr [ mid ] - > desc - > ops . count < op )
min = mid + 1 ;
else if ( itr [ mid ] - > base_id > op )
max = mid - 1 ;
else
return itr [ mid ] ;
2012-07-10 07:01:45 -07:00
}
2012-09-03 00:26:57 -07:00
return NULL ;
2012-07-10 07:01:45 -07:00
}
2012-05-01 00:40:14 -07:00
static const Eo_Op_Description *
_eo_op_id_desc_get ( Eo_Op op )
2012-04-18 00:58:34 -07:00
{
2012-07-10 07:01:45 -07:00
const Eo_Class * klass ;
2012-04-18 00:58:34 -07:00
2012-05-01 00:40:14 -07:00
if ( op = = EO_NOOP )
2012-04-18 00:58:34 -07:00
return & noop_desc ;
2012-07-10 07:01:45 -07:00
klass = _eo_op_class_get ( op ) ;
if ( klass )
{
Eo_Op sub_id = op - klass - > base_id ;
if ( sub_id < klass - > desc - > ops . count )
return klass - > desc - > ops . descs + sub_id ;
}
2012-04-18 00:58:34 -07:00
return NULL ;
}
static const char *
2012-05-01 00:40:14 -07:00
_eo_op_id_name_get ( Eo_Op op )
2012-04-18 00:58:34 -07:00
{
2012-05-01 00:40:14 -07:00
const Eo_Op_Description * desc = _eo_op_id_desc_get ( op ) ;
2012-04-18 00:58:34 -07:00
return ( desc ) ? desc - > name : NULL ;
}
2012-05-06 05:03:13 -07:00
static inline void
2012-07-10 07:02:00 -07:00
_eo_kls_itr_init ( const Eo_Class * obj_klass , Eo_Kls_Itr * cur , Eo_Kls_Itr * prev_state )
2012-04-11 00:05:21 -07:00
{
2012-07-18 05:27:09 -07:00
memcpy ( prev_state , cur , sizeof ( * cur ) ) ;
cur - > kls = * obj_klass - > mro ;
2012-04-11 00:05:21 -07:00
}
2012-04-11 00:05:30 -07:00
static inline void
2012-05-15 07:16:54 -07:00
_eo_kls_itr_end ( Eo_Kls_Itr * cur , Eo_Kls_Itr * prev_state )
2012-04-11 00:05:30 -07:00
{
2012-07-18 05:27:09 -07:00
memcpy ( cur , prev_state , sizeof ( * cur ) ) ;
2012-04-11 00:05:30 -07:00
}
2012-05-01 00:40:14 -07:00
static inline const Eo_Class *
2012-05-15 07:16:54 -07:00
_eo_kls_itr_get ( Eo_Kls_Itr * cur )
2012-04-12 01:27:35 -07:00
{
2012-07-18 05:27:09 -07:00
return cur - > kls ;
}
static inline void
_eo_kls_itr_set ( Eo_Kls_Itr * cur , const Eo_Class * kls )
{
cur - > kls = kls ;
2012-04-12 01:27:35 -07:00
}
2012-05-01 00:40:14 -07:00
static inline const Eo_Class *
2012-07-18 05:27:09 -07:00
_eo_kls_itr_next ( const Eo_Class * orig_kls , Eo_Kls_Itr * cur , Eo_Kls_Itr * prev_state , Eo_Op op )
2012-04-11 00:05:30 -07:00
{
2012-07-18 05:27:09 -07:00
const Eo_Class * * kls_itr = NULL ;
2012-07-10 07:02:03 -07:00
memcpy ( prev_state , cur , sizeof ( * cur ) ) ;
2012-05-07 23:56:57 -07:00
2012-07-18 05:27:09 -07:00
/* Find the kls itr. */
kls_itr = orig_kls - > mro ;
while ( * kls_itr & & ( * kls_itr ! = cur - > kls ) )
kls_itr + + ;
2012-05-07 23:56:57 -07:00
2012-07-18 05:27:09 -07:00
if ( * kls_itr )
2012-04-11 00:05:33 -07:00
{
2012-07-18 05:27:09 -07:00
kls_itr + + ;
2012-07-31 00:15:33 -07:00
while ( * kls_itr )
2012-07-18 05:27:09 -07:00
{
const op_type_funcs * fsrc = _dich_func_get ( * kls_itr , op ) ;
2012-07-31 00:34:27 -07:00
if ( ! fsrc | | ! fsrc - > func )
2012-07-31 00:15:33 -07:00
{
kls_itr + + ;
continue ;
}
2012-07-18 05:27:09 -07:00
cur - > kls = fsrc - > src ;
return cur - > kls ;
}
2012-04-11 00:05:33 -07:00
}
2012-07-18 05:27:09 -07:00
2012-07-31 00:15:33 -07:00
cur - > kls = NULL ;
2012-07-18 05:27:09 -07:00
return NULL ;
2012-04-11 00:05:30 -07:00
}
2012-05-15 07:16:58 -07:00
static inline const op_type_funcs *
2012-07-10 07:02:00 -07:00
_eo_kls_itr_func_get ( Eo_Kls_Itr * mro_itr , Eo_Op op )
2012-05-15 07:16:58 -07:00
{
2012-07-10 07:02:00 -07:00
const Eo_Class * klass = _eo_kls_itr_get ( mro_itr ) ;
2012-05-15 07:16:58 -07:00
if ( klass )
{
2012-07-10 07:01:45 -07:00
const op_type_funcs * func = _dich_func_get ( klass , op ) ;
2012-05-15 07:16:58 -07:00
if ( func & & func - > func )
{
2012-07-18 05:27:09 -07:00
_eo_kls_itr_set ( mro_itr , func - > src ) ;
2012-05-15 07:16:58 -07:00
return func ;
}
}
2012-07-18 05:27:09 -07:00
_eo_kls_itr_set ( mro_itr , NULL ) ;
2012-05-15 07:16:58 -07:00
return NULL ;
}
2012-05-15 08:06:40 -07:00
# define _EO_OP_ERR_NO_OP_PRINT(op, klass) \
do \
{ \
2012-07-10 07:01:45 -07:00
const Eo_Class * op_klass = _eo_op_class_get ( op ) ; \
2012-05-15 08:06:40 -07:00
const char * _dom_name = ( op_klass ) ? op_klass - > desc - > name : NULL ; \
2012-07-26 06:15:28 -07:00
ERR ( " Can't find func for op %x (%s:%s) for class '%s'. Aborting. " , \
op , _dom_name , _eo_op_id_name_get ( op ) , \
2012-05-15 08:06:40 -07:00
( klass ) ? klass - > desc - > name : NULL ) ; \
} \
while ( 0 )
2012-05-15 07:16:58 -07:00
2012-04-05 08:31:15 -07:00
static Eina_Bool
2012-05-15 07:16:58 -07:00
_eo_op_internal ( Eo * obj , Eo_Op_Type op_type , Eo_Op op , va_list * p_list )
2012-04-05 08:31:15 -07:00
{
2012-06-05 05:05:08 -07:00
# ifndef NDEBUG
2012-05-01 00:40:14 -07:00
const Eo_Op_Description * op_desc = _eo_op_id_desc_get ( op ) ;
2012-04-24 01:04:14 -07:00
2012-05-15 07:16:58 -07:00
if ( op_desc )
2012-04-24 01:04:14 -07:00
{
2012-05-15 07:16:58 -07:00
if ( op_desc - > op_type = = EO_OP_TYPE_CLASS )
{
2012-06-07 04:32:21 -07:00
ERR ( " Tried calling a class op '%s' (%x) from a non-class context. " , ( op_desc ) ? op_desc - > name : NULL , op ) ;
2012-05-15 07:16:58 -07:00
return EINA_FALSE ;
}
2012-04-24 01:04:14 -07:00
}
2012-06-05 05:05:08 -07:00
# endif
2012-04-24 01:04:14 -07:00
2012-05-15 07:16:58 -07:00
{
const op_type_funcs * func =
2012-07-10 07:02:00 -07:00
_eo_kls_itr_func_get ( & obj - > mro_itr , op ) ;
2012-09-13 06:43:59 -07:00
if ( EINA_LIKELY ( func ! = NULL ) )
2012-04-05 08:31:15 -07:00
{
2012-09-13 06:39:02 -07:00
void * func_data = _eo_data_get ( obj , func - > src ) ;
func - > func ( obj , func_data , p_list ) ;
2012-07-10 07:02:00 -07:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
}
2012-04-12 03:14:58 -07:00
}
2012-04-12 03:23:46 -07:00
/* Try composite objects */
2012-04-12 03:14:58 -07:00
{
Eina_List * itr ;
2012-05-01 00:40:14 -07:00
Eo * emb_obj ;
2012-04-12 03:14:58 -07:00
EINA_LIST_FOREACH ( obj - > composite_objects , itr , emb_obj )
2012-04-05 08:31:15 -07:00
{
2012-07-18 05:27:09 -07:00
/* FIXME: Clean this up a bit. */
Eo_Kls_Itr prev_state ;
_eo_kls_itr_init ( emb_obj - > klass , & emb_obj - > mro_itr , & prev_state ) ;
2012-05-15 07:16:58 -07:00
if ( _eo_op_internal ( emb_obj , op_type , op , p_list ) )
2012-04-05 08:31:15 -07:00
{
2012-07-18 05:27:09 -07:00
_eo_kls_itr_end ( & emb_obj - > mro_itr , & prev_state ) ;
2012-07-10 07:02:00 -07:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
}
2012-07-18 05:27:09 -07:00
_eo_kls_itr_end ( & emb_obj - > mro_itr , & prev_state ) ;
2012-04-05 08:31:15 -07:00
}
}
2012-07-10 07:02:00 -07:00
return EINA_FALSE ;
2012-04-05 08:31:15 -07:00
}
2012-08-23 03:35:14 -07:00
static inline Eina_Bool
2012-10-09 04:34:16 -07:00
_eo_dov_internal ( Eo * obj , Eo_Op_Type op_type , va_list * p_list )
2012-04-05 08:31:15 -07:00
{
2012-06-13 04:38:56 -07:00
Eina_Bool prev_error ;
2012-04-05 08:31:15 -07:00
Eina_Bool ret = EINA_TRUE ;
2012-05-01 00:40:14 -07:00
Eo_Op op = EO_NOOP ;
2012-07-10 07:02:00 -07:00
Eo_Kls_Itr prev_state ;
2012-04-23 01:10:04 -07:00
2012-06-13 04:38:56 -07:00
prev_error = obj - > do_error ;
2012-05-06 05:03:26 -07:00
_eo_ref ( obj ) ;
2012-04-05 08:31:15 -07:00
2012-10-09 04:34:16 -07:00
op = va_arg ( * p_list , Eo_Op ) ;
2012-04-05 08:31:15 -07:00
while ( op )
{
2012-07-23 01:43:35 -07:00
_eo_kls_itr_init ( obj - > klass , & obj - > mro_itr , & prev_state ) ;
2012-10-09 04:34:16 -07:00
if ( ! _eo_op_internal ( obj , op_type , op , p_list ) )
2012-04-05 08:31:15 -07:00
{
2012-05-15 08:06:40 -07:00
_EO_OP_ERR_NO_OP_PRINT ( op , obj - > klass ) ;
2012-04-05 08:31:15 -07:00
ret = EINA_FALSE ;
2012-07-23 01:43:35 -07:00
_eo_kls_itr_end ( & obj - > mro_itr , & prev_state ) ;
2012-04-05 08:31:15 -07:00
break ;
}
2012-10-09 04:34:16 -07:00
op = va_arg ( * p_list , Eo_Op ) ;
2012-07-23 01:43:35 -07:00
_eo_kls_itr_end ( & obj - > mro_itr , & prev_state ) ;
2012-04-05 08:31:15 -07:00
}
2012-05-06 05:03:26 -07:00
_eo_unref ( obj ) ;
2012-06-13 04:38:56 -07:00
if ( obj - > do_error )
ret = EINA_FALSE ;
obj - > do_error = prev_error ;
2012-04-05 08:31:15 -07:00
return ret ;
}
2012-08-23 03:35:14 -07:00
EAPI Eina_Bool
eo_do_internal ( Eo * obj , Eo_Op_Type op_type , . . . )
{
Eina_Bool ret = EINA_TRUE ;
va_list p_list ;
2012-08-23 08:04:48 -07:00
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , EINA_FALSE ) ;
2012-08-23 03:35:14 -07:00
va_start ( p_list , op_type ) ;
2012-10-09 04:34:16 -07:00
ret = _eo_dov_internal ( obj , op_type , & p_list ) ;
2012-08-23 03:35:14 -07:00
va_end ( p_list ) ;
return ret ;
}
2012-04-05 08:31:15 -07:00
EAPI Eina_Bool
2012-05-15 07:16:58 -07:00
eo_do_super_internal ( Eo * obj , Eo_Op_Type op_type , Eo_Op op , . . . )
2012-04-05 08:31:15 -07:00
{
2012-05-15 07:16:58 -07:00
const Eo_Class * nklass ;
2012-04-11 00:05:21 -07:00
Eina_Bool ret = EINA_TRUE ;
2012-04-05 08:31:15 -07:00
va_list p_list ;
2012-07-10 07:02:00 -07:00
Eo_Kls_Itr prev_state ;
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , EINA_FALSE ) ;
2012-04-11 02:04:44 -07:00
2012-04-12 01:27:35 -07:00
/* Advance the kls itr. */
2012-07-18 05:27:09 -07:00
nklass = _eo_kls_itr_next ( obj - > klass , & obj - > mro_itr , & prev_state , op ) ;
2012-04-18 00:58:34 -07:00
va_start ( p_list , op ) ;
2012-05-15 07:16:58 -07:00
if ( ! _eo_op_internal ( obj , op_type , op , & p_list ) )
{
2012-05-15 08:06:40 -07:00
_EO_OP_ERR_NO_OP_PRINT ( op , nklass ) ;
2012-05-15 07:16:58 -07:00
ret = EINA_FALSE ;
}
va_end ( p_list ) ;
2012-06-20 08:56:17 -07:00
if ( obj - > do_error )
ret = EINA_FALSE ;
2012-07-10 07:02:00 -07:00
_eo_kls_itr_end ( & obj - > mro_itr , & prev_state ) ;
2012-05-15 07:16:58 -07:00
return ret ;
}
static Eina_Bool
_eo_class_op_internal ( Eo_Class * klass , Eo_Op op , va_list * p_list )
{
2012-06-05 05:05:08 -07:00
# ifndef NDEBUG
2012-05-15 07:16:58 -07:00
const Eo_Op_Description * op_desc = _eo_op_id_desc_get ( op ) ;
if ( op_desc )
{
if ( op_desc - > op_type ! = EO_OP_TYPE_CLASS )
{
2012-06-07 04:32:21 -07:00
ERR ( " Tried calling an instance op '%s' (%x) from a class context. " , ( op_desc ) ? op_desc - > name : NULL , op ) ;
2012-05-15 07:16:58 -07:00
return EINA_FALSE ;
}
}
2012-06-05 05:05:08 -07:00
# endif
2012-05-15 07:16:58 -07:00
{
const op_type_funcs * func =
2012-07-10 07:02:00 -07:00
_eo_kls_itr_func_get ( & klass - > mro_itr , op ) ;
2012-05-15 07:16:58 -07:00
if ( func )
{
( ( eo_op_func_type_class ) func - > func ) ( klass , p_list ) ;
2012-07-10 07:02:00 -07:00
return EINA_TRUE ;
2012-05-15 07:16:58 -07:00
}
}
2012-07-10 07:02:00 -07:00
return EINA_FALSE ;
2012-05-15 07:16:58 -07:00
}
EAPI Eina_Bool
eo_class_do_internal ( const Eo_Class * klass , . . . )
{
Eina_Bool ret = EINA_TRUE ;
Eo_Op op = EO_NOOP ;
2012-07-10 07:02:00 -07:00
Eo_Kls_Itr prev_state ;
2012-05-15 07:16:58 -07:00
va_list p_list ;
EO_MAGIC_RETURN_VAL ( klass , EO_CLASS_EINA_MAGIC , EINA_FALSE ) ;
va_start ( p_list , klass ) ;
op = va_arg ( p_list , Eo_Op ) ;
while ( op )
{
2012-07-23 01:43:35 -07:00
_eo_kls_itr_init ( klass , & ( ( Eo_Class * ) klass ) - > mro_itr , & prev_state ) ;
2012-05-15 07:16:58 -07:00
if ( ! _eo_class_op_internal ( ( Eo_Class * ) klass , op , & p_list ) )
{
2012-05-15 08:06:40 -07:00
_EO_OP_ERR_NO_OP_PRINT ( op , klass ) ;
2012-05-15 07:16:58 -07:00
ret = EINA_FALSE ;
2012-07-23 01:43:35 -07:00
_eo_kls_itr_end ( & ( ( Eo_Class * ) klass ) - > mro_itr , & prev_state ) ;
2012-05-15 07:16:58 -07:00
break ;
}
2012-07-23 01:43:35 -07:00
_eo_kls_itr_end ( & ( ( Eo_Class * ) klass ) - > mro_itr , & prev_state ) ;
2012-05-15 07:16:58 -07:00
op = va_arg ( p_list , Eo_Op ) ;
}
va_end ( p_list ) ;
return ret ;
}
EAPI Eina_Bool
eo_class_do_super_internal ( const Eo_Class * klass , Eo_Op op , . . . )
{
const Eo_Class * nklass ;
Eina_Bool ret = EINA_TRUE ;
va_list p_list ;
2012-07-10 07:02:00 -07:00
Eo_Kls_Itr prev_state ;
2012-05-15 07:16:58 -07:00
EO_MAGIC_RETURN_VAL ( klass , EO_CLASS_EINA_MAGIC , EINA_FALSE ) ;
/* Advance the kls itr. */
2012-07-18 05:27:09 -07:00
nklass = _eo_kls_itr_next ( klass , & ( ( Eo_Class * ) klass ) - > mro_itr , & prev_state , op ) ;
2012-05-15 07:16:58 -07:00
va_start ( p_list , op ) ;
if ( ! _eo_class_op_internal ( ( Eo_Class * ) klass , op , & p_list ) )
2012-04-11 00:05:21 -07:00
{
2012-05-15 08:06:40 -07:00
_EO_OP_ERR_NO_OP_PRINT ( op , nklass ) ;
2012-04-11 00:05:21 -07:00
ret = EINA_FALSE ;
}
2012-04-05 08:31:15 -07:00
va_end ( p_list ) ;
2012-04-11 02:04:44 -07:00
2012-07-10 07:02:00 -07:00
_eo_kls_itr_end ( & ( ( Eo_Class * ) klass ) - > mro_itr , & prev_state ) ;
2012-04-05 08:31:15 -07:00
return ret ;
}
2012-05-01 00:40:14 -07:00
EAPI const Eo_Class *
eo_class_get ( const Eo * obj )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , EINA_FALSE ) ;
2012-04-23 01:10:04 -07:00
2012-04-05 08:31:15 -07:00
return obj - > klass ;
}
EAPI const char *
2012-05-01 00:40:14 -07:00
eo_class_name_get ( const Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( klass , EO_CLASS_EINA_MAGIC , NULL ) ;
2012-04-23 01:10:04 -07:00
2012-04-05 08:31:15 -07:00
return klass - > desc - > name ;
}
static void
2012-05-01 00:40:14 -07:00
_eo_class_base_op_init ( Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
const Eo_Class_Description * desc = klass - > desc ;
2012-04-05 08:31:15 -07:00
2012-07-10 07:01:45 -07:00
klass - > base_id = _eo_ops_last_id ;
if ( desc & & desc - > ops . base_op_id )
* ( desc - > ops . base_op_id ) = klass - > base_id ;
_eo_ops_last_id + = desc - > ops . count + 1 ;
klass - > chain_size = DICH_CHAIN1 ( _eo_ops_last_id ) + 1 ;
klass - > chain = calloc ( klass - > chain_size , sizeof ( * klass - > chain ) ) ;
2012-04-05 08:31:15 -07:00
}
2012-06-14 03:29:39 -07:00
# ifndef NDEBUG
static Eina_Bool
_eo_class_mro_has ( const Eo_Class * klass , const Eo_Class * find )
{
const Eo_Class * * itr ;
for ( itr = klass - > mro ; * itr ; itr + + )
{
if ( * itr = = find )
{
return EINA_TRUE ;
}
}
return EINA_FALSE ;
}
# endif
2012-04-11 00:05:14 -07:00
static Eina_List *
2012-05-01 00:40:14 -07:00
_eo_class_mro_add ( Eina_List * mro , const Eo_Class * klass )
2012-04-11 00:05:14 -07:00
{
2012-04-19 01:52:15 -07:00
Eina_List * extn_pos = NULL ;
Eina_Bool check_consistency = ! mro ;
2012-04-11 00:05:14 -07:00
if ( ! klass )
return mro ;
mro = eina_list_append ( mro , klass ) ;
2012-06-13 04:39:02 -07:00
/* ONLY ADD MIXINS! */
2012-04-19 01:52:15 -07:00
/* Recursively add extenions. */
2012-04-11 00:05:14 -07:00
{
2012-06-13 04:39:02 -07:00
const Eo_Class * * extn_itr ;
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
2012-04-11 00:05:14 -07:00
{
2012-06-13 04:39:02 -07:00
const Eo_Class * extn = * extn_itr ;
if ( extn - > desc - > type ! = EO_CLASS_TYPE_MIXIN )
continue ;
mro = _eo_class_mro_add ( mro , extn ) ;
2012-04-23 01:09:40 -07:00
/* Not possible: if (!mro) return NULL; */
2012-04-19 01:52:15 -07:00
if ( check_consistency )
{
extn_pos = eina_list_append ( extn_pos , eina_list_last ( mro ) ) ;
}
}
}
/* Check if we can create a consistent mro. We only do it for the class
* we are working on ( i . e no parents ) . */
if ( check_consistency )
{
2012-06-13 04:39:02 -07:00
const Eo_Class * * extn_itr ;
2012-04-19 01:52:15 -07:00
Eina_List * itr = extn_pos ;
2012-06-13 04:39:02 -07:00
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
2012-04-19 01:52:15 -07:00
{
2012-06-13 04:39:02 -07:00
const Eo_Class * extn = * extn_itr ;
if ( extn - > desc - > type ! = EO_CLASS_TYPE_MIXIN )
continue ;
2012-04-19 01:52:15 -07:00
/* Get the first one after the extension. */
Eina_List * extn_list = eina_list_next ( eina_list_data_get ( itr ) ) ;
/* If we found the extension again. */
2012-06-13 04:39:02 -07:00
if ( eina_list_data_find_list ( extn_list , extn ) )
2012-04-19 01:52:15 -07:00
{
eina_list_free ( mro ) ;
2012-06-13 04:39:02 -07:00
ERR ( " Cannot create a consistent method resolution order for class '%s' because of '%s'. " , klass - > desc - > name , extn - > desc - > name ) ;
2012-04-19 01:52:15 -07:00
return NULL ;
}
itr = eina_list_next ( itr ) ;
2012-04-11 00:05:14 -07:00
}
}
2012-04-19 01:52:15 -07:00
2012-05-01 00:40:14 -07:00
mro = _eo_class_mro_add ( mro , klass - > parent ) ;
2012-04-11 00:05:14 -07:00
return mro ;
}
2012-04-19 01:52:15 -07:00
static Eina_Bool
2012-05-01 00:40:14 -07:00
_eo_class_mro_init ( Eo_Class * klass )
2012-04-11 00:05:14 -07:00
{
Eina_List * mro = NULL ;
DBG ( " Started creating MRO for class '%s' " , klass - > desc - > name ) ;
2012-05-01 00:40:14 -07:00
mro = _eo_class_mro_add ( mro , klass ) ;
2012-04-11 00:05:14 -07:00
2012-04-19 01:52:15 -07:00
if ( ! mro )
return EINA_FALSE ;
/* Remove duplicates and make them the right order. */
2012-04-11 00:05:14 -07:00
{
Eina_List * itr1 , * itr2 , * itr2n ;
itr1 = eina_list_last ( mro ) ;
while ( itr1 )
{
itr2 = eina_list_prev ( itr1 ) ;
while ( itr2 )
{
itr2n = eina_list_prev ( itr2 ) ;
if ( eina_list_data_get ( itr1 ) = = eina_list_data_get ( itr2 ) )
{
mro = eina_list_remove_list ( mro , itr2 ) ;
}
itr2 = itr2n ;
}
itr1 = eina_list_prev ( itr1 ) ;
}
}
/* Copy the mro and free the list. */
{
2012-05-01 00:40:14 -07:00
const Eo_Class * kls_itr ;
const Eo_Class * * mro_itr ;
2012-04-11 00:05:14 -07:00
klass - > mro = calloc ( sizeof ( * klass - > mro ) , eina_list_count ( mro ) + 1 ) ;
mro_itr = klass - > mro ;
EINA_LIST_FREE ( mro , kls_itr )
{
* ( mro_itr + + ) = kls_itr ;
DBG ( " Added '%s' to MRO " , kls_itr - > desc - > name ) ;
}
* ( mro_itr ) = NULL ;
}
DBG ( " Finished creating MRO for class '%s' " , klass - > desc - > name ) ;
2012-04-19 01:52:15 -07:00
return EINA_TRUE ;
2012-04-11 00:05:14 -07:00
}
2012-04-05 08:31:15 -07:00
static void
2012-05-01 00:40:14 -07:00
_eo_class_constructor ( Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
if ( klass - > constructed )
return ;
klass - > constructed = EINA_TRUE ;
2012-04-11 00:05:14 -07:00
if ( klass - > desc - > class_constructor )
klass - > desc - > class_constructor ( klass ) ;
2012-04-05 08:31:15 -07:00
}
EAPI void
2012-05-01 00:40:14 -07:00
eo_class_funcs_set ( Eo_Class * klass , const Eo_Op_Func_Description * func_descs )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN ( klass , EO_CLASS_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
2012-05-01 00:40:14 -07:00
const Eo_Op_Func_Description * itr ;
2012-04-05 08:31:15 -07:00
itr = func_descs ;
if ( itr )
{
2012-06-07 04:14:38 -07:00
for ( ; itr - > op_type ! = EO_OP_TYPE_INVALID ; itr + + )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
const Eo_Op_Description * op_desc = _eo_op_id_desc_get ( itr - > op ) ;
2012-04-24 01:04:14 -07:00
2012-06-07 04:32:17 -07:00
if ( EINA_UNLIKELY ( ! op_desc | | ( itr - > op = = EO_NOOP ) ) )
{
2012-10-23 02:56:39 -07:00
ERR ( " Setting implementation for non-existent op %x for class '%s'. Func index: %lu " , itr - > op , klass - > desc - > name , ( unsigned long ) ( itr - func_descs ) ) ;
2012-06-07 04:32:17 -07:00
}
else if ( EINA_LIKELY ( itr - > op_type = = op_desc - > op_type ) )
2012-04-24 01:04:14 -07:00
{
2012-07-10 07:01:45 -07:00
_dich_func_set ( klass , itr - > op , itr - > func ) ;
2012-04-24 01:04:14 -07:00
}
else
{
2012-10-23 02:56:39 -07:00
ERR ( " Set function's op type (%x) is different than the one in the op description (%d) for op '%s:%s'. Func index: %lu " ,
2012-06-07 04:32:17 -07:00
itr - > op_type ,
2012-06-07 04:14:35 -07:00
( op_desc ) ? op_desc - > op_type : EO_OP_TYPE_REGULAR ,
2012-06-07 04:32:17 -07:00
klass - > desc - > name ,
2012-07-26 06:15:28 -07:00
( op_desc ) ? op_desc - > name : NULL ,
2012-10-23 02:56:39 -07:00
( unsigned long ) ( itr - func_descs ) ) ;
2012-04-24 01:04:14 -07:00
}
2012-04-05 08:31:15 -07:00
}
}
}
2012-04-23 01:09:42 -07:00
static void
2012-05-01 00:40:14 -07:00
eo_class_free ( Eo_Class * klass )
2012-04-16 05:36:42 -07:00
{
if ( klass - > constructed )
{
if ( klass - > desc - > class_destructor )
klass - > desc - > class_destructor ( klass ) ;
2012-05-07 23:56:57 -07:00
_dich_func_clean_all ( klass ) ;
2012-04-16 05:36:42 -07:00
}
2012-06-13 04:39:02 -07:00
free ( klass - > extensions ) ;
2012-04-16 05:36:42 -07:00
2012-04-19 01:52:25 -07:00
if ( klass - > mro )
free ( klass - > mro ) ;
if ( klass - > extn_data_off )
free ( klass - > extn_data_off ) ;
2012-04-16 05:36:42 -07:00
free ( klass ) ;
}
2012-04-17 03:27:31 -07:00
/* DEVCHECK */
2012-04-17 01:05:09 -07:00
static Eina_Bool
2012-08-20 00:56:17 -07:00
_eo_class_check_op_descs ( const Eo_Class * klass )
2012-04-17 01:05:09 -07:00
{
2012-05-01 00:40:14 -07:00
const Eo_Class_Description * desc = klass - > desc ;
const Eo_Op_Description * itr ;
2012-04-17 01:05:09 -07:00
size_t i ;
2012-04-17 03:27:31 -07:00
if ( desc - > ops . count > 0 )
{
2012-08-20 00:56:17 -07:00
if ( ! desc - > ops . base_op_id )
2012-04-17 03:27:31 -07:00
{
ERR ( " Class '%s' has a non-zero ops count, but base_id is NULL. " ,
desc - > name ) ;
return EINA_FALSE ;
}
if ( ! desc - > ops . descs )
{
ERR ( " Class '%s' has a non-zero ops count, but there are no descs. " ,
desc - > name ) ;
return EINA_FALSE ;
}
}
2012-04-17 01:05:09 -07:00
itr = desc - > ops . descs ;
for ( i = 0 ; i < desc - > ops . count ; i + + , itr + + )
{
if ( itr - > sub_op ! = i )
{
2012-04-17 03:27:31 -07:00
if ( itr - > name )
{
2012-10-23 02:56:39 -07:00
ERR ( " Wrong order in Ops description for class '%s'. Expected %lx and got %lx " , desc - > name , ( unsigned long ) i , ( unsigned long ) itr - > sub_op ) ;
2012-04-17 03:27:31 -07:00
}
else
{
2012-10-23 02:56:39 -07:00
ERR ( " Found too few Ops description for class '%s'. Expected %lx descriptions, but found %lx. " , desc - > name , ( unsigned long ) desc - > ops . count , ( unsigned long ) i ) ;
2012-04-17 03:27:31 -07:00
}
2012-04-17 01:05:09 -07:00
return EINA_FALSE ;
}
}
if ( itr & & itr - > name )
{
2012-10-23 02:56:39 -07:00
ERR ( " Found extra Ops description for class '%s'. Expected %lu descriptions, but found more. " , desc - > name , ( unsigned long ) desc - > ops . count ) ;
2012-04-17 01:05:09 -07:00
return EINA_FALSE ;
}
return EINA_TRUE ;
}
2012-06-13 04:39:12 -07:00
/* Not really called, just used for the ptr... */
static void
_eo_class_isa_func ( Eo * obj EINA_UNUSED , void * class_data EINA_UNUSED , va_list * list EINA_UNUSED )
{
/* Do nonthing. */
}
2012-05-01 00:40:14 -07:00
EAPI const Eo_Class *
2012-08-20 00:56:17 -07:00
eo_class_new ( const Eo_Class_Description * desc , const Eo_Class * parent , . . . )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
Eo_Class * klass ;
2012-04-05 08:31:15 -07:00
va_list p_list ;
2012-05-01 00:40:14 -07:00
if ( parent & & ! EINA_MAGIC_CHECK ( parent , EO_CLASS_EINA_MAGIC ) )
2012-04-23 01:10:04 -07:00
{
2012-05-01 00:40:14 -07:00
EINA_MAGIC_FAIL ( parent , EO_CLASS_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
return NULL ;
}
2012-04-05 08:31:15 -07:00
va_start ( p_list , parent ) ;
2012-04-23 01:10:06 -07:00
EINA_SAFETY_ON_NULL_RETURN_VAL ( desc , NULL ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( desc - > name , NULL ) ;
2012-04-05 08:31:15 -07:00
2012-04-19 04:30:10 -07:00
/* Check restrictions on Interface types. */
2012-05-01 00:40:14 -07:00
if ( desc - > type = = EO_CLASS_TYPE_INTERFACE )
2012-04-19 04:30:10 -07:00
{
2012-04-23 01:10:06 -07:00
EINA_SAFETY_ON_FALSE_RETURN_VAL ( ! desc - > data_size , NULL ) ;
2012-04-19 04:30:10 -07:00
}
2012-05-01 00:40:14 -07:00
klass = calloc ( 1 , sizeof ( Eo_Class ) ) ;
2012-04-05 08:31:15 -07:00
klass - > parent = parent ;
/* Handle class extensions */
{
2012-06-13 04:39:02 -07:00
Eina_List * extn_list = NULL ;
const Eo_Class * extn = NULL ;
const Eo_Class * * extn_itr = NULL ;
2012-04-05 08:31:15 -07:00
2012-05-01 00:40:14 -07:00
extn = va_arg ( p_list , Eo_Class * ) ;
2012-04-05 08:31:15 -07:00
while ( extn )
{
switch ( extn - > desc - > type )
{
2012-05-01 00:40:14 -07:00
case EO_CLASS_TYPE_REGULAR :
case EO_CLASS_TYPE_REGULAR_NO_INSTANT :
2012-06-13 04:39:02 -07:00
case EO_CLASS_TYPE_INTERFACE :
2012-05-01 00:40:14 -07:00
case EO_CLASS_TYPE_MIXIN :
2012-06-13 04:39:02 -07:00
extn_list = eina_list_append ( extn_list , extn ) ;
2012-04-05 08:31:15 -07:00
break ;
}
2012-05-01 00:40:14 -07:00
extn = va_arg ( p_list , Eo_Class * ) ;
2012-04-05 08:31:15 -07:00
}
2012-06-13 04:39:02 -07:00
klass - > extensions = calloc ( sizeof ( * klass - > extensions ) ,
eina_list_count ( extn_list ) + 1 ) ;
extn_itr = klass - > extensions ;
EINA_LIST_FREE ( extn_list , extn )
{
* ( extn_itr + + ) = extn ;
}
2012-04-05 08:31:15 -07:00
}
klass - > desc = desc ;
2012-04-11 00:05:39 -07:00
2012-04-12 05:25:29 -07:00
/* Handle the inheritance */
2012-04-11 00:05:39 -07:00
if ( klass - > parent )
{
2012-04-12 05:25:29 -07:00
/* Verify the inheritance is allowed. */
switch ( klass - > desc - > type )
{
2012-05-01 00:40:14 -07:00
case EO_CLASS_TYPE_REGULAR :
case EO_CLASS_TYPE_REGULAR_NO_INSTANT :
if ( ( klass - > parent - > desc - > type ! = EO_CLASS_TYPE_REGULAR ) & &
( klass - > parent - > desc - > type ! = EO_CLASS_TYPE_REGULAR_NO_INSTANT ) )
2012-04-12 05:25:29 -07:00
{
ERR ( " Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s'). " , klass - > desc - > name , klass - > parent - > desc - > name ) ;
goto cleanup ;
}
break ;
2012-05-01 00:40:14 -07:00
case EO_CLASS_TYPE_INTERFACE :
case EO_CLASS_TYPE_MIXIN :
if ( ( klass - > parent - > desc - > type ! = EO_CLASS_TYPE_INTERFACE ) & &
( klass - > parent - > desc - > type ! = EO_CLASS_TYPE_MIXIN ) )
2012-04-12 05:25:29 -07:00
{
ERR ( " Non-regular classes ('%s') aren't allowed to inherit from regular classes ('%s'). " , klass - > desc - > name , klass - > parent - > desc - > name ) ;
goto cleanup ;
}
break ;
}
2012-04-12 05:25:34 -07:00
/* Update the current offset. */
2012-04-11 00:05:39 -07:00
/* FIXME: Make sure this alignment is enough. */
klass - > data_offset = klass - > parent - > data_offset +
2012-05-01 00:40:14 -07:00
EO_ALIGN_SIZE ( klass - > parent - > desc - > data_size ) ;
2012-04-11 00:05:39 -07:00
}
2012-08-20 00:56:17 -07:00
if ( ! _eo_class_check_op_descs ( klass ) )
2012-04-17 01:05:09 -07:00
{
goto cleanup ;
}
2012-05-01 00:40:14 -07:00
if ( ! _eo_class_mro_init ( klass ) )
2012-04-19 01:52:15 -07:00
{
goto cleanup ;
}
2012-04-19 01:52:25 -07:00
/* create MIXIN offset table. */
{
2012-05-01 00:40:14 -07:00
const Eo_Class * * mro_itr = klass - > mro ;
Eo_Extension_Data_Offset * extn_data_itr ;
2012-04-19 01:52:25 -07:00
size_t extn_num = 0 ;
size_t extn_data_off = klass - > data_offset +
2012-05-01 00:40:14 -07:00
EO_ALIGN_SIZE ( klass - > desc - > data_size ) ;
2012-04-19 01:52:25 -07:00
/* FIXME: Make faster... */
while ( * mro_itr )
{
2012-05-01 00:40:14 -07:00
if ( ( ( * mro_itr ) - > desc - > type = = EO_CLASS_TYPE_MIXIN ) & &
2012-04-19 01:52:25 -07:00
( ( * mro_itr ) - > desc - > data_size > 0 ) )
{
extn_num + + ;
}
mro_itr + + ;
}
klass - > extn_data_off = calloc ( extn_num + 1 ,
sizeof ( * klass - > extn_data_off ) ) ;
extn_data_itr = klass - > extn_data_off ;
mro_itr = klass - > mro ;
while ( * mro_itr )
{
2012-05-01 00:40:14 -07:00
if ( ( ( * mro_itr ) - > desc - > type = = EO_CLASS_TYPE_MIXIN ) & &
2012-04-19 01:52:25 -07:00
( ( * mro_itr ) - > desc - > data_size > 0 ) )
{
extn_data_itr - > klass = * mro_itr ;
extn_data_itr - > offset = extn_data_off ;
2012-05-01 00:40:14 -07:00
extn_data_off + = EO_ALIGN_SIZE ( extn_data_itr - > klass - > desc - > data_size ) ;
2012-04-19 01:52:25 -07:00
extn_data_itr + + ;
}
mro_itr + + ;
}
klass - > extn_data_size = extn_data_off ;
}
2012-05-01 00:40:14 -07:00
eina_lock_take ( & _eo_class_creation_lock ) ;
2012-06-03 01:42:12 -07:00
2012-08-20 00:56:17 -07:00
klass - > class_id = + + _eo_classes_last_id ;
2012-06-03 01:42:12 -07:00
2012-04-12 05:25:29 -07:00
{
/* FIXME: Handle errors. */
2012-06-03 01:42:12 -07:00
size_t arrsize = _eo_classes_last_id * sizeof ( * _eo_classes ) ;
2012-05-01 00:40:14 -07:00
Eo_Class * * tmp ;
2012-06-03 01:42:12 -07:00
tmp = realloc ( _eo_classes , arrsize ) ;
/* If it's the first allocation, memset. */
if ( ! _eo_classes )
memset ( tmp , 0 , arrsize ) ;
2012-05-01 00:40:14 -07:00
_eo_classes = tmp ;
_eo_classes [ klass - > class_id - 1 ] = klass ;
2012-04-12 05:25:29 -07:00
}
2012-05-01 00:40:14 -07:00
eina_lock_release ( & _eo_class_creation_lock ) ;
2012-04-12 05:25:29 -07:00
2012-05-01 00:40:14 -07:00
EINA_MAGIC_SET ( klass , EO_CLASS_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
2012-07-10 07:01:45 -07:00
_eo_class_base_op_init ( klass ) ;
2012-05-07 23:56:57 -07:00
/* Flatten the function array */
{
const Eo_Class * * mro_itr = klass - > mro ;
for ( ; * mro_itr ; mro_itr + + )
;
2012-05-21 08:18:52 -07:00
/* Skip ourselves. */
for ( mro_itr - - ; mro_itr > klass - > mro ; mro_itr - - )
2012-05-07 23:56:57 -07:00
{
_dich_copy_all ( klass , * mro_itr ) ;
}
}
2012-06-13 04:39:12 -07:00
/* Mark which classes we implement */
{
const Eo_Class * * extn_itr ;
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
{
const Eo_Class * extn = * extn_itr ;
/* Set it in the dich. */
2012-07-10 07:01:45 -07:00
_dich_func_set ( klass , extn - > base_id +
extn - > desc - > ops . count , _eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
}
2012-07-10 07:01:45 -07:00
_dich_func_set ( klass , klass - > base_id + klass - > desc - > ops . count ,
_eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
if ( klass - > parent )
{
_dich_func_set ( klass ,
2012-07-10 07:01:45 -07:00
klass - > parent - > base_id + klass - > parent - > desc - > ops . count ,
_eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
}
}
2012-05-01 00:40:14 -07:00
_eo_class_constructor ( klass ) ;
2012-04-05 08:31:15 -07:00
va_end ( p_list ) ;
return klass ;
2012-04-12 05:25:29 -07:00
cleanup :
2012-05-01 00:40:14 -07:00
eo_class_free ( klass ) ;
2012-04-12 05:25:29 -07:00
return NULL ;
2012-04-05 08:31:15 -07:00
}
2012-06-13 04:39:12 -07:00
EAPI Eina_Bool
eo_isa ( const Eo * obj , const Eo_Class * klass )
{
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , EINA_FALSE ) ;
EO_MAGIC_RETURN_VAL ( klass , EO_CLASS_EINA_MAGIC , EINA_FALSE ) ;
const op_type_funcs * func = _dich_func_get ( obj - > klass ,
2012-07-10 07:01:45 -07:00
klass - > base_id + klass - > desc - > ops . count ) ;
2012-06-13 04:39:12 -07:00
/* Currently implemented by reusing the LAST op id. Just marking it with
* _eo_class_isa_func . */
return ( func & & ( func - > func = = _eo_class_isa_func ) ) ;
}
2012-06-06 04:41:47 -07:00
EAPI Eina_Bool
eo_parent_set ( Eo * obj , const Eo * parent )
{
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , EINA_FALSE ) ;
if ( parent )
EO_MAGIC_RETURN_VAL ( parent , EO_EINA_MAGIC , EINA_FALSE ) ;
2012-06-07 00:17:42 -07:00
if ( obj - > parent = = parent )
return EINA_TRUE ;
2012-06-06 04:41:47 -07:00
_eo_ref ( obj ) ;
2012-06-07 03:54:15 -07:00
if ( eo_composite_is ( obj ) )
{
2012-06-10 08:02:49 -07:00
eo_composite_detach ( obj , obj - > parent ) ;
2012-06-07 03:54:15 -07:00
}
2012-06-06 04:41:47 -07:00
if ( obj - > parent )
{
obj - > parent - > children =
eina_inlist_remove ( obj - > parent - > children , EINA_INLIST_GET ( obj ) ) ;
2012-06-07 00:17:45 -07:00
eo_xunref ( obj , obj - > parent ) ;
2012-06-06 04:41:47 -07:00
}
obj - > parent = ( Eo * ) parent ;
if ( obj - > parent )
{
obj - > parent - > children =
eina_inlist_append ( obj - > parent - > children , EINA_INLIST_GET ( obj ) ) ;
2012-06-07 00:17:45 -07:00
eo_xref ( obj , obj - > parent ) ;
2012-06-06 04:41:47 -07:00
}
_eo_unref ( obj ) ;
return EINA_TRUE ;
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2012-08-23 03:35:14 -07:00
eo_add_internal ( const Eo_Class * klass , Eo * parent , . . . )
2012-04-05 08:31:15 -07:00
{
2012-06-13 04:38:56 -07:00
Eina_Bool do_err ;
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( klass , EO_CLASS_EINA_MAGIC , NULL ) ;
2012-04-23 01:10:04 -07:00
2012-05-01 00:40:14 -07:00
if ( parent ) EO_MAGIC_RETURN_VAL ( parent , EO_EINA_MAGIC , NULL ) ;
2012-04-23 01:10:04 -07:00
2012-05-01 00:40:14 -07:00
if ( EINA_UNLIKELY ( klass - > desc - > type ! = EO_CLASS_TYPE_REGULAR ) )
2012-04-05 08:31:15 -07:00
{
ERR ( " Class '%s' is not instantiate-able. Aborting. " , klass - > desc - > name ) ;
return NULL ;
}
2012-05-01 00:40:14 -07:00
Eo * obj = calloc ( 1 , EO_ALIGN_SIZE ( sizeof ( * obj ) ) +
( klass - > data_offset + EO_ALIGN_SIZE ( klass - > desc - > data_size ) ) +
2012-04-23 01:09:45 -07:00
klass - > extn_data_size ) ;
2012-06-06 04:41:47 -07:00
EINA_MAGIC_SET ( obj , EO_EINA_MAGIC ) ;
obj - > refcount + + ;
2012-04-05 08:31:15 -07:00
obj - > klass = klass ;
2012-06-06 04:41:47 -07:00
eo_parent_set ( obj , parent ) ;
2012-04-05 08:31:15 -07:00
2012-06-10 07:04:53 -07:00
_eo_condtor_reset ( obj ) ;
2012-04-15 01:57:17 -07:00
2012-05-06 05:03:26 -07:00
_eo_ref ( obj ) ;
2012-08-23 03:35:14 -07:00
/* Run the relevant do stuff. */
{
va_list p_list ;
va_start ( p_list , parent ) ;
2012-10-09 04:34:16 -07:00
do_err = ! _eo_dov_internal ( obj , EO_OP_TYPE_REGULAR , & p_list ) ;
2012-08-23 03:35:14 -07:00
va_end ( p_list ) ;
}
2012-04-15 01:57:17 -07:00
2012-06-13 04:38:56 -07:00
if ( EINA_UNLIKELY ( do_err ) )
2012-04-05 08:31:15 -07:00
{
2012-06-10 00:53:46 -07:00
ERR ( " Object of class '%s' - One of the object constructors have failed. " , klass - > desc - > name ) ;
2012-04-05 08:31:15 -07:00
goto fail ;
}
2012-06-10 07:04:53 -07:00
if ( ! obj - > condtor_done )
2012-04-05 08:31:15 -07:00
{
2012-06-26 20:58:39 -07:00
ERR ( " Object of class '%s' - Not all of the object constructors have been executed. " , klass - > desc - > name ) ;
2012-04-05 08:31:15 -07:00
goto fail ;
}
2012-08-23 03:35:14 -07:00
2012-05-06 05:03:26 -07:00
_eo_unref ( obj ) ;
2012-04-05 08:31:15 -07:00
return obj ;
fail :
2012-04-15 01:57:17 -07:00
/* Unref twice, once for the ref above, and once for the basic object ref. */
2012-05-06 05:03:26 -07:00
_eo_unref ( obj ) ;
_eo_unref ( obj ) ;
2012-04-05 08:31:15 -07:00
return NULL ;
}
2012-04-17 08:22:22 -07:00
typedef struct
{
EINA_INLIST ;
2012-05-01 00:40:14 -07:00
const Eo * ref_obj ;
2012-04-17 08:22:22 -07:00
const char * file ;
int line ;
2012-05-01 00:40:14 -07:00
} Eo_Xref_Node ;
2012-04-17 08:22:22 -07:00
2012-05-01 00:40:14 -07:00
EAPI Eo *
eo_xref_internal ( Eo * obj , const Eo * ref_obj , const char * file , int line )
2012-04-17 08:22:22 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , obj ) ;
2012-04-23 01:10:04 -07:00
2012-05-06 05:03:26 -07:00
_eo_ref ( obj ) ;
2012-04-17 08:22:22 -07:00
# ifndef NDEBUG
2012-05-01 00:40:14 -07:00
Eo_Xref_Node * xref = calloc ( 1 , sizeof ( * xref ) ) ;
2012-04-17 08:22:22 -07:00
xref - > ref_obj = ref_obj ;
xref - > file = file ;
xref - > line = line ;
obj - > xrefs = eina_inlist_prepend ( obj - > xrefs , EINA_INLIST_GET ( xref ) ) ;
# else
( void ) ref_obj ;
( void ) file ;
( void ) line ;
# endif
return obj ;
}
EAPI void
2012-05-01 00:40:14 -07:00
eo_xunref ( Eo * obj , const Eo * ref_obj )
2012-04-17 08:22:22 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN ( obj , EO_EINA_MAGIC ) ;
2012-04-17 08:22:22 -07:00
# ifndef NDEBUG
2012-05-01 00:40:14 -07:00
Eo_Xref_Node * xref = NULL ;
2012-04-17 08:22:22 -07:00
EINA_INLIST_FOREACH ( obj - > xrefs , xref )
{
if ( xref - > ref_obj = = ref_obj )
break ;
}
if ( xref )
{
obj - > xrefs = eina_inlist_remove ( obj - > xrefs , EINA_INLIST_GET ( xref ) ) ;
free ( xref ) ;
}
else
{
ERR ( " ref_obj (%p) does not reference obj (%p). Aborting unref. " , ref_obj , obj ) ;
return ;
}
# else
( void ) ref_obj ;
# endif
2012-05-06 05:03:26 -07:00
_eo_unref ( obj ) ;
}
static inline Eo *
_eo_ref ( Eo * obj )
{
obj - > refcount + + ;
return obj ;
2012-04-17 08:22:22 -07:00
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2012-05-14 00:35:19 -07:00
eo_ref ( const Eo * _obj )
2012-04-05 08:31:15 -07:00
{
2012-05-14 00:35:19 -07:00
Eo * obj = ( Eo * ) _obj ;
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , obj ) ;
2012-04-23 01:10:04 -07:00
2012-05-06 05:03:26 -07:00
return _eo_ref ( obj ) ;
2012-04-05 08:31:15 -07:00
}
2012-06-03 01:42:08 -07:00
static inline void
2012-05-01 00:40:14 -07:00
_eo_del_internal ( Eo * obj )
2012-04-23 01:10:12 -07:00
{
2012-06-13 04:38:56 -07:00
Eina_Bool do_err ;
2012-04-23 01:10:12 -07:00
/* We need that for the event callbacks that may ref/unref. */
obj - > refcount + + ;
2012-05-14 00:35:19 -07:00
eo_do ( obj , eo_event_callback_call ( EO_EV_DEL , NULL , NULL ) ) ;
2012-04-23 01:10:12 -07:00
2012-05-01 00:40:14 -07:00
const Eo_Class * klass = eo_class_get ( obj ) ;
2012-05-06 05:03:13 -07:00
2012-06-10 07:04:53 -07:00
_eo_condtor_reset ( obj ) ;
2012-06-13 04:38:56 -07:00
do_err = eo_do ( obj , eo_destructor ( ) ) ;
if ( EINA_UNLIKELY ( ! do_err ) )
2012-04-23 01:10:12 -07:00
{
2012-06-10 00:53:46 -07:00
ERR ( " Object of class '%s' - One of the object destructors have failed. " , klass - > desc - > name ) ;
2012-04-23 01:10:12 -07:00
}
2012-06-10 07:04:53 -07:00
if ( ! obj - > condtor_done )
2012-04-23 01:10:12 -07:00
{
2012-06-26 20:58:39 -07:00
ERR ( " Object of class '%s' - Not all of the object destructors have been executed. " , klass - > desc - > name ) ;
2012-04-23 01:10:12 -07:00
}
2012-05-01 00:40:14 -07:00
/*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */
2012-04-23 01:10:12 -07:00
{
2012-06-06 04:41:47 -07:00
Eina_List * itr , * itr_n ;
Eo * emb_obj ;
EINA_LIST_FOREACH_SAFE ( obj - > composite_objects , itr , itr_n , emb_obj )
{
2012-06-10 08:02:49 -07:00
eo_composite_detach ( emb_obj , obj ) ;
2012-06-06 04:41:47 -07:00
}
}
while ( obj - > children )
{
eo_parent_set ( EINA_INLIST_CONTAINER_GET ( obj - > children , Eo ) , NULL ) ;
2012-04-23 01:10:12 -07:00
}
2012-05-08 07:22:53 -07:00
2012-06-05 05:05:06 -07:00
obj - > del = EINA_TRUE ;
2012-05-08 07:22:53 -07:00
obj - > refcount - - ;
2012-04-23 01:10:12 -07:00
}
2012-05-21 04:45:32 -07:00
static inline void
_eo_free ( Eo * obj )
{
2012-06-05 05:05:06 -07:00
EINA_MAGIC_SET ( obj , EO_FREED_EINA_MAGIC ) ;
2012-05-21 04:45:32 -07:00
free ( obj ) ;
}
2012-05-06 05:03:26 -07:00
static inline void
_eo_unref ( Eo * obj )
2012-04-05 08:31:15 -07:00
{
2012-08-21 05:15:54 -07:00
- - ( obj - > refcount ) ;
if ( obj - > refcount = = 0 )
2012-04-05 08:31:15 -07:00
{
2012-06-10 00:53:43 -07:00
if ( obj - > del )
{
ERR ( " Object %p already deleted. " , obj ) ;
return ;
}
2012-05-01 00:40:14 -07:00
_eo_del_internal ( obj ) ;
2012-04-16 07:22:11 -07:00
2012-04-17 08:22:22 -07:00
# ifndef NDEBUG
2012-05-21 04:45:32 -07:00
/* If for some reason it's not empty, clear it. */
while ( obj - > xrefs )
{
2012-08-21 05:08:48 -07:00
ERR ( " obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack. " ) ;
2012-05-21 04:45:32 -07:00
Eina_Inlist * nitr = obj - > xrefs - > next ;
free ( EINA_INLIST_CONTAINER_GET ( obj - > xrefs , Eo_Xref_Node ) ) ;
obj - > xrefs = nitr ;
}
2012-04-17 08:22:22 -07:00
# endif
2012-06-06 04:41:53 -07:00
if ( ! obj - > manual_free )
_eo_free ( obj ) ;
else
_eo_ref ( obj ) ; /* If we manual free, we keep a phantom ref. */
2012-04-05 08:31:15 -07:00
}
2012-08-21 05:15:54 -07:00
else if ( obj - > refcount < 0 )
{
ERR ( " Obj:%p. Refcount (%d) < 0. Too many unrefs. " , obj , obj - > refcount ) ;
return ;
}
2012-04-05 08:31:15 -07:00
}
2012-05-06 05:03:26 -07:00
EAPI void
2012-05-14 00:35:19 -07:00
eo_unref ( const Eo * _obj )
2012-05-06 05:03:26 -07:00
{
2012-05-14 00:35:19 -07:00
Eo * obj = ( Eo * ) _obj ;
2012-05-06 05:03:26 -07:00
EO_MAGIC_RETURN ( obj , EO_EINA_MAGIC ) ;
_eo_unref ( obj ) ;
}
2012-06-07 00:17:45 -07:00
EAPI void
eo_del ( const Eo * obj )
{
eo_parent_set ( ( Eo * ) obj , NULL ) ;
eo_unref ( obj ) ;
}
2012-04-11 00:05:37 -07:00
EAPI int
2012-05-01 00:40:14 -07:00
eo_ref_get ( const Eo * obj )
2012-04-11 00:05:37 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , 0 ) ;
2012-04-23 01:10:04 -07:00
2012-04-11 00:05:37 -07:00
return obj - > refcount ;
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2012-05-07 23:56:50 -07:00
eo_parent_get ( const Eo * obj )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , NULL ) ;
2012-04-23 01:10:04 -07:00
2012-04-05 08:31:15 -07:00
return obj - > parent ;
}
EAPI void
2012-05-14 04:57:28 -07:00
eo_error_set_internal ( const Eo * obj , const char * file , int line )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
EO_MAGIC_RETURN ( obj , EO_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
2012-05-14 04:57:28 -07:00
ERR ( " Error with obj '%p' at %s:%d " , obj , file , line ) ;
2012-06-13 04:38:56 -07:00
( ( Eo * ) obj ) - > do_error = EINA_TRUE ;
2012-04-12 07:58:57 -07:00
}
2012-06-10 07:04:53 -07:00
void
_eo_condtor_done ( Eo * obj )
{
2012-06-10 07:04:58 -07:00
if ( obj - > condtor_done )
{
ERR ( " Object %p is already constructed at this point. " , obj ) ;
return ;
}
2012-06-10 07:04:53 -07:00
obj - > condtor_done = EINA_TRUE ;
}
static void
_eo_condtor_reset ( Eo * obj )
{
obj - > condtor_done = EINA_FALSE ;
}
2012-05-06 05:03:21 -07:00
static inline void *
_eo_data_get ( const Eo * obj , const Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2012-04-23 01:09:40 -07:00
if ( EINA_LIKELY ( klass - > desc - > data_size > 0 ) )
2012-04-19 01:52:25 -07:00
{
2012-05-01 00:40:14 -07:00
if ( EINA_UNLIKELY ( klass - > desc - > type = = EO_CLASS_TYPE_MIXIN ) )
2012-04-19 01:52:25 -07:00
{
2012-05-01 00:40:14 -07:00
Eo_Extension_Data_Offset * doff_itr =
eo_class_get ( obj ) - > extn_data_off ;
2012-04-19 01:52:25 -07:00
if ( ! doff_itr )
return NULL ;
while ( doff_itr - > klass )
{
if ( doff_itr - > klass = = klass )
2012-05-01 00:40:14 -07:00
return ( ( char * ) obj ) + EO_ALIGN_SIZE ( sizeof ( * obj ) ) +
2012-07-10 07:01:54 -07:00
doff_itr - > offset ;
2012-04-19 01:52:25 -07:00
doff_itr + + ;
}
}
else
{
2012-07-10 07:01:54 -07:00
return ( ( char * ) obj ) + EO_ALIGN_SIZE ( sizeof ( * obj ) ) +
klass - > data_offset ;
2012-04-19 01:52:25 -07:00
}
}
2012-05-06 05:03:21 -07:00
return NULL ;
}
EAPI void *
eo_data_get ( const Eo * obj , const Eo_Class * klass )
{
void * ret ;
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , NULL ) ;
2012-06-13 04:39:12 -07:00
EO_MAGIC_RETURN_VAL ( klass , EO_CLASS_EINA_MAGIC , NULL ) ;
2012-05-06 05:03:21 -07:00
# ifndef NDEBUG
2012-06-14 03:29:39 -07:00
if ( ! _eo_class_mro_has ( obj - > klass , klass ) )
2012-05-06 05:03:21 -07:00
{
ERR ( " Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter. " , klass - > desc - > name , obj - > klass - > desc - > name ) ;
return NULL ;
}
# endif
ret = _eo_data_get ( obj , klass ) ;
2012-05-21 07:48:32 -07:00
# ifndef NDEBUG
2012-05-06 05:03:21 -07:00
if ( ! ret & & ( klass - > desc - > data_size = = 0 ) )
2012-05-06 05:03:07 -07:00
{
ERR ( " Tried getting data of class '%s', but it has none.. " , klass - > desc - > name ) ;
}
2012-05-21 07:48:32 -07:00
# endif
2012-04-19 01:52:25 -07:00
2012-05-06 05:03:21 -07:00
return ret ;
2012-04-05 08:31:15 -07:00
}
EAPI Eina_Bool
2012-05-01 00:40:14 -07:00
eo_init ( void )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
const char * log_dom = " eo " ;
if ( _eo_init_count + + > 0 )
2012-04-05 08:31:15 -07:00
return EINA_TRUE ;
eina_init ( ) ;
2012-05-01 00:40:14 -07:00
_eo_classes = NULL ;
2012-08-20 00:56:17 -07:00
_eo_classes_last_id = EO_CLASS_IDS_FIRST - 1 ;
2012-07-10 07:01:45 -07:00
_eo_ops_last_id = EO_OP_IDS_FIRST ;
2012-05-01 00:40:14 -07:00
_eo_log_dom = eina_log_domain_register ( log_dom , EINA_COLOR_LIGHTBLUE ) ;
if ( _eo_log_dom < 0 )
2012-04-05 08:31:15 -07:00
{
2012-04-15 03:18:06 -07:00
EINA_LOG_ERR ( " Could not register log domain: %s " , log_dom ) ;
2012-04-05 08:31:15 -07:00
return EINA_FALSE ;
}
2012-05-01 00:40:14 -07:00
if ( ! eina_lock_new ( & _eo_class_creation_lock ) )
2012-04-23 01:09:54 -07:00
{
EINA_LOG_ERR ( " Could not init lock. " ) ;
return EINA_FALSE ;
}
2012-05-01 00:40:14 -07:00
eina_magic_string_static_set ( EO_EINA_MAGIC , EO_EINA_MAGIC_STR ) ;
2012-06-05 05:05:06 -07:00
eina_magic_string_static_set ( EO_FREED_EINA_MAGIC ,
EO_FREED_EINA_MAGIC_STR ) ;
2012-05-01 00:40:14 -07:00
eina_magic_string_static_set ( EO_CLASS_EINA_MAGIC ,
EO_CLASS_EINA_MAGIC_STR ) ;
2012-04-23 01:10:04 -07:00
2012-07-10 07:01:54 -07:00
# ifndef NDEBUG
/* Call it just for coverage purposes. Ugly I know, but I like it better than
* casting everywhere else . */
_eo_class_isa_func ( NULL , NULL , NULL ) ;
# endif
2012-04-05 08:31:15 -07:00
return EINA_TRUE ;
}
EAPI Eina_Bool
2012-05-01 00:40:14 -07:00
eo_shutdown ( void )
2012-04-05 08:31:15 -07:00
{
2012-05-06 05:03:23 -07:00
size_t i ;
2012-05-01 00:40:14 -07:00
Eo_Class * * cls_itr = _eo_classes ;
2012-04-05 08:31:15 -07:00
2012-05-01 00:40:14 -07:00
if ( - - _eo_init_count > 0 )
2012-04-05 08:31:15 -07:00
return EINA_TRUE ;
2012-05-01 00:40:14 -07:00
for ( i = 0 ; i < _eo_classes_last_id ; i + + , cls_itr + + )
2012-04-05 08:31:15 -07:00
{
if ( * cls_itr )
2012-05-01 00:40:14 -07:00
eo_class_free ( * cls_itr ) ;
2012-04-05 08:31:15 -07:00
}
2012-05-01 00:40:14 -07:00
if ( _eo_classes )
free ( _eo_classes ) ;
2012-04-05 08:31:15 -07:00
2012-05-01 00:40:14 -07:00
eina_lock_free ( & _eo_class_creation_lock ) ;
2012-04-23 01:09:54 -07:00
2012-05-01 00:40:14 -07:00
eina_log_domain_unregister ( _eo_log_dom ) ;
_eo_log_dom = - 1 ;
2012-04-05 08:31:15 -07:00
eina_shutdown ( ) ;
return EINA_TRUE ;
}
EAPI void
2012-06-10 08:02:44 -07:00
eo_composite_attach ( Eo * comp_obj , Eo * parent )
2012-04-05 08:31:15 -07:00
{
2012-06-10 07:56:20 -07:00
EO_MAGIC_RETURN ( comp_obj , EO_EINA_MAGIC ) ;
EO_MAGIC_RETURN ( parent , EO_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
2012-06-10 07:56:20 -07:00
comp_obj - > composite = EINA_TRUE ;
eo_parent_set ( comp_obj , parent ) ;
parent - > composite_objects = eina_list_prepend ( parent - > composite_objects , comp_obj ) ;
2012-04-05 08:31:15 -07:00
}
EAPI void
2012-06-10 08:02:44 -07:00
eo_composite_detach ( Eo * comp_obj , Eo * parent )
2012-04-05 08:31:15 -07:00
{
2012-06-10 07:56:20 -07:00
EO_MAGIC_RETURN ( comp_obj , EO_EINA_MAGIC ) ;
EO_MAGIC_RETURN ( parent , EO_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
2012-06-10 07:56:20 -07:00
comp_obj - > composite = EINA_FALSE ;
parent - > composite_objects = eina_list_remove ( parent - > composite_objects , comp_obj ) ;
eo_parent_set ( comp_obj , NULL ) ;
2012-04-05 08:31:15 -07:00
}
EAPI Eina_Bool
2012-06-10 07:56:20 -07:00
eo_composite_is ( const Eo * comp_obj )
2012-04-05 08:31:15 -07:00
{
2012-08-22 06:10:08 -07:00
EO_MAGIC_RETURN_VAL ( comp_obj , EO_EINA_MAGIC , EINA_FALSE ) ;
2012-04-23 01:10:04 -07:00
2012-06-10 07:56:20 -07:00
return comp_obj - > composite ;
2012-04-05 08:31:15 -07:00
}
2012-09-12 04:31:58 -07:00
EAPI Eina_Bool
eo_destructed_is ( const Eo * obj )
{
EO_MAGIC_RETURN_VAL ( obj , EO_EINA_MAGIC , EINA_FALSE ) ;
return obj - > del ;
}
2012-05-21 04:45:32 -07:00
EAPI void
eo_manual_free_set ( Eo * obj , Eina_Bool manual_free )
{
EO_MAGIC_RETURN ( obj , EO_EINA_MAGIC ) ;
obj - > manual_free = manual_free ;
}
EAPI void
eo_manual_free ( Eo * obj )
{
EO_MAGIC_RETURN ( obj , EO_EINA_MAGIC ) ;
if ( EINA_FALSE = = obj - > manual_free )
{
2012-06-06 04:41:56 -07:00
ERR ( " Tried to manually free the object %p while the option has not been set; see eo_manual_free_set for more information. " , obj ) ;
2012-05-21 04:45:32 -07:00
return ;
}
2012-06-06 04:41:53 -07:00
if ( ! obj - > del )
2012-05-21 04:45:32 -07:00
{
ERR ( " Tried deleting the object %p while still referenced(%d). " , obj , eo_ref_get ( obj ) ) ;
return ;
}
_eo_free ( obj ) ;
}