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"
2013-04-18 04:19:02 -07:00
# include "eo_ptr_indirection.h"
2012-05-01 00:40:14 -07:00
# include "eo_private.h"
2012-04-05 08:31:15 -07:00
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 */
2013-10-10 01:26:02 -07:00
EAPI Eina_Spinlock _eo_class_creation_lock ;
2012-05-01 00:40:14 -07:00
int _eo_log_dom = - 1 ;
2012-04-05 08:31:15 -07:00
2013-04-18 04:19:02 -07:00
static _Eo_Class * * _eo_classes ;
2013-09-27 02:50:06 -07:00
static Eo_Id _eo_classes_last_id ;
2012-05-01 00:40:14 -07:00
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
2013-04-10 19:58:53 -07:00
static size_t _eo_sz = 0 ;
2013-06-17 14:33:19 -07:00
static size_t _eo_class_sz = 0 ;
2013-04-10 19:58:53 -07:00
2013-09-26 14:31:39 -07:00
static void _eo_condtor_reset ( _Eo_Object * obj ) ;
static inline void * _eo_data_scope_get ( const _Eo_Object * obj , const _Eo_Class * klass ) ;
static inline void * _eo_data_xref_internal ( const char * file , int line , _Eo_Object * obj , const _Eo_Class * klass , const _Eo_Object * ref_obj ) ;
static inline void _eo_data_xunref_internal ( _Eo_Object * obj , void * data , const _Eo_Object * ref_obj ) ;
2013-04-18 04:19:02 -07:00
static const _Eo_Class * _eo_op_class_get ( Eo_Op op ) ;
2012-07-26 05:21:01 -07:00
static const Eo_Op_Description * _eo_op_id_desc_get ( Eo_Op op ) ;
2014-01-03 07:01:27 -08:00
static const char * _eo_op_id_name_get ( Eo_Op op , int version ) ;
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)
2013-08-09 06:58:55 -07:00
# define DICH_CHAIN1(x) ((x) >> DICH_CHAIN_LAST_BITS)
# define DICH_CHAIN_LAST(x) ((x) & ((1 << DICH_CHAIN_LAST_BITS) - 1))
2012-04-05 08:31:15 -07:00
2014-03-11 08:50:44 -07:00
/* We are substracting the mask here instead of "AND"ing because it's a hot path,
* it should be a valid class at this point , and this lets the compiler do 1
* substraction at compile time . */
# define _UNMASK_ID(id) ((id) - MASK_CLASS_TAG)
2012-05-06 05:03:23 -07:00
# define ID_CLASS_GET(id) ({ \
2014-03-11 08:50:44 -07:00
( _Eo_Class * ) ( ( ( _UNMASK_ID ( id ) < = _eo_classes_last_id ) & & ( _UNMASK_ID ( id ) > 0 ) ) ? \
( _eo_classes [ _UNMASK_ID ( id ) - 1 ] ) : NULL ) ; \
2012-05-06 05:03:23 -07:00
} )
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
2013-04-18 04:19:02 -07:00
_dich_copy_all ( _Eo_Class * dst , const _Eo_Class * src )
2012-05-07 23:56:57 -07:00
{
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 *
2013-04-18 04:19:02 -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
2013-04-18 04:19:02 -07:00
_dich_func_set ( _Eo_Class * klass , Eo_Op op , eo_op_func_type func )
2012-04-05 08:31:15 -07:00
{
2014-01-03 07:02:00 -08:00
op_type_funcs * fsrc ;
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 ) ;
2014-01-03 07:02:00 -08:00
fsrc = & chain1 - > funcs [ DICH_CHAIN_LAST ( op ) ] ;
if ( fsrc - > src = = klass )
2012-07-26 05:21:01 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * op_kls = _eo_op_class_get ( op ) ;
2014-01-03 07:02:00 -08:00
const char * op_name = _eo_op_id_name_get ( op , op_kls - > desc - > version ) ;
2014-01-08 02:10:48 -08:00
ERR ( " Already set function for op %d (%s:'%s'). Overriding %p with %p. " ,
2014-01-03 07:02:00 -08:00
op , op_kls - > desc - > name , op_name , fsrc - > func , func ) ;
2012-07-26 05:21:01 -07:00
}
2014-01-03 07:02:00 -08:00
fsrc - > func = func ;
fsrc - > src = klass ;
2012-04-05 08:31:15 -07:00
}
static inline void
2013-04-18 04:19:02 -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
2013-09-26 14:32:43 -07:00
static inline Eina_Bool
2013-12-26 14:46:50 -08:00
_eo_is_a_class ( const Eo * eo_id )
2013-09-26 14:32:43 -07:00
{
2013-09-27 03:13:14 -07:00
Eo_Id oid ;
2013-09-26 14:32:43 -07:00
# ifdef HAVE_EO_ID
2013-12-26 14:46:50 -08:00
oid = ( Eo_Id ) eo_id ;
2013-09-26 14:32:43 -07:00
# else
2013-12-26 14:46:50 -08:00
/* fortunately EO_OBJ_POINTER_RETURN* will handle NULL eo_id */
if ( ! eo_id ) return EINA_FALSE ;
oid = ( ( Eo_Base * ) eo_id ) - > id ;
2013-09-26 14:32:43 -07:00
# endif
2013-09-27 03:13:14 -07:00
return ( ( ( oid > > REF_TAG_SHIFT ) & 0x1 ) = = 0x0 ) ;
2013-09-26 14:32:43 -07:00
}
2013-04-18 04:19:02 -07:00
static inline _Eo_Class *
2013-09-27 08:38:15 -07:00
_eo_class_pointer_get ( const Eo_Class * klass_id )
2013-04-18 04:19:02 -07:00
{
# ifdef HAVE_EO_ID
2013-09-27 02:50:06 -07:00
return ID_CLASS_GET ( ( Eo_Id ) klass_id ) ;
2013-04-18 04:19:02 -07:00
# else
2013-09-27 03:13:14 -07:00
return ( _Eo_Class * ) klass_id ;
2013-04-18 04:19:02 -07:00
# endif
}
static const _Eo_Class *
2012-07-10 07:01:45 -07:00
_eo_op_class_get ( Eo_Op op )
{
/* FIXME: Make it fast. */
2013-04-18 04:19:02 -07:00
_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
{
2013-04-18 04:19:02 -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 ;
}
2014-01-03 07:00:24 -08:00
static const Eo2_Op_Description *
_eo2_op_id_desc_get ( Eo_Op op )
{
unsigned int i ;
const _Eo_Class * klass ;
const Eo2_Op_Description * op_descs ;
if ( op = = EO_NOOP )
return NULL ;
klass = _eo_op_class_get ( op ) ;
DBG ( " klass %p %s " , klass , klass - > desc - > name ) ;
if ( klass )
{
op_descs = klass - > desc - > ops . descs2 ;
for ( i = 0 ; i < klass - > desc - > ops . count ; i + + )
{
if ( op_descs [ i ] . op = = op )
return & op_descs [ i ] ;
}
}
return NULL ;
}
2012-04-18 00:58:34 -07:00
static const char *
2014-01-03 07:01:27 -08:00
_eo_op_id_name_get ( Eo_Op op , int version )
2012-04-18 00:58:34 -07:00
{
2014-01-03 07:01:27 -08:00
if ( version = = EO2_VERSION )
{
const Eo2_Op_Description * desc = _eo2_op_id_desc_get ( op ) ;
return ( desc ) ? desc - > doc : NULL ;
}
else
{
const Eo_Op_Description * desc = _eo_op_id_desc_get ( op ) ;
return ( desc ) ? desc - > name : NULL ;
}
2012-04-18 00:58:34 -07:00
}
2013-11-11 05:06:51 -08:00
static inline const op_type_funcs *
_eo2_kls_itr_next ( const _Eo_Class * orig_kls , const _Eo_Class * cur_klass , Eo_Op op )
2012-04-11 00:05:30 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * * kls_itr = NULL ;
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 ;
2013-03-13 09:04:04 -07:00
while ( * kls_itr & & ( * kls_itr ! = cur_klass ) )
2012-07-18 05:27:09 -07:00
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 ;
}
2013-11-11 05:06:51 -08:00
return fsrc ;
2012-07-18 05:27:09 -07:00
}
2012-04-11 00:05:33 -07:00
}
2012-07-18 05:27:09 -07:00
return NULL ;
2012-04-11 00:05:30 -07:00
}
2013-11-11 05:06:51 -08:00
static inline const _Eo_Class *
_eo_kls_itr_next ( const _Eo_Class * orig_kls , const _Eo_Class * cur_klass , Eo_Op op )
{
const op_type_funcs * fsrc ;
fsrc = _eo2_kls_itr_next ( orig_kls , cur_klass , op ) ;
return ( fsrc ) ? fsrc - > src : NULL ;
}
2012-05-15 07:16:58 -07:00
static inline const op_type_funcs *
2013-04-18 04:19:02 -07:00
_eo_kls_itr_func_get ( const _Eo_Class * cur_klass , Eo_Op op )
2012-05-15 07:16:58 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * klass = cur_klass ;
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 )
{
return func ;
}
}
return NULL ;
}
2013-07-18 00:10:07 -07:00
/************************************ EO2 ************************************/
2013-08-01 02:49:27 -07:00
EAPI Eo2_Hook_Call eo2_hook_call_pre = NULL ;
EAPI Eo2_Hook_Call eo2_hook_call_post = NULL ;
2013-12-30 06:24:15 -08:00
// FIXME: Thread Local Storage
2013-12-25 06:16:34 -08:00
# define EO2_INVALID_DATA (void *) -1
2013-12-30 06:24:15 -08:00
# define EO2_CALL_STACK_DEPTH 30
2013-10-02 05:57:45 -07:00
2013-12-25 06:16:34 -08:00
typedef struct _Eo2_Stack_Frame
{
2013-10-02 02:47:10 -07:00
const Eo * eo_id ;
2013-11-11 02:34:35 -08:00
union {
_Eo_Object * obj ;
const _Eo_Class * kls ;
} o ;
2013-10-02 01:44:33 -07:00
const _Eo_Class * cur_klass ;
2013-07-24 15:10:26 -07:00
void * obj_data ;
2013-12-25 06:16:34 -08:00
} Eo2_Stack_Frame ;
typedef struct _Eo2_Call_Stack {
2013-10-02 05:57:45 -07:00
Eo2_Stack_Frame * stack ;
2013-12-25 06:16:34 -08:00
Eo2_Stack_Frame * frame_ptr ;
2013-12-30 06:24:15 -08:00
Eo2_Stack_Frame * last_frame ;
Eo2_Stack_Frame * shrink_frame ;
2013-12-25 06:16:34 -08:00
} Eo2_Call_Stack ;
2013-12-30 06:24:15 -08:00
static Eo2_Call_Stack eo2_call_stack = { NULL , NULL , NULL , NULL } ;
2013-10-02 05:57:45 -07:00
static Eina_Bool
_eo2_call_stack_init ( )
{
eo2_call_stack . stack = calloc ( EO2_CALL_STACK_DEPTH , sizeof ( Eo2_Stack_Frame ) ) ;
if ( ! eo2_call_stack . stack )
return EINA_FALSE ;
// first frame is never used
2013-12-30 06:24:15 -08:00
eo2_call_stack . frame_ptr = eo2_call_stack . stack ;
eo2_call_stack . last_frame = & eo2_call_stack . stack [ EO2_CALL_STACK_DEPTH - 1 ] ;
eo2_call_stack . shrink_frame = eo2_call_stack . stack ;
2013-10-02 05:57:45 -07:00
return EINA_TRUE ;
}
static void
_eo2_call_stack_free ( )
{
if ( eo2_call_stack . stack )
free ( eo2_call_stack . stack ) ;
}
2013-12-25 06:16:34 -08:00
2013-12-30 06:24:15 -08:00
static inline void
_eo2_call_stack_resize ( Eina_Bool grow )
{
size_t sz , next_sz ;
int frame_offset ;
frame_offset = eo2_call_stack . frame_ptr - eo2_call_stack . stack ;
sz = eo2_call_stack . last_frame - eo2_call_stack . stack + 1 ;
if ( grow )
next_sz = sz < < 1 ;
else
next_sz = sz > > 1 ;
DBG ( " resize from %lu to %lu " , sz , next_sz ) ;
eo2_call_stack . stack = realloc ( eo2_call_stack . stack , next_sz * sizeof ( Eo2_Stack_Frame ) ) ;
if ( ! eo2_call_stack . stack )
{
CRI ( " unable to resize call stack, abort. " ) ;
abort ( ) ;
}
eo2_call_stack . frame_ptr = & eo2_call_stack . stack [ frame_offset ] ;
eo2_call_stack . last_frame = & eo2_call_stack . stack [ next_sz - 1 ] ;
if ( grow )
frame_offset = ( sz > > 1 ) ;
if ( next_sz = = EO2_CALL_STACK_DEPTH )
frame_offset = 0 ;
else
frame_offset = ( next_sz > > 1 ) ;
eo2_call_stack . shrink_frame = & eo2_call_stack . stack [ frame_offset ] ;
}
2013-10-02 02:47:10 -07:00
static inline Eina_Bool
2013-11-11 02:34:35 -08:00
_eo2_do_internal ( const Eo * eo_id , const Eo_Class * cur_klass_id ,
2013-12-30 11:31:40 -08:00
Eina_Bool is_super , Eo2_Stack_Frame * fptr , Eo2_Stack_Frame * pfptr )
2013-07-08 08:31:36 -07:00
{
2013-12-30 08:53:54 -08:00
Eina_Bool is_klass = _eo_is_a_class ( eo_id ) ;
2013-11-11 02:34:35 -08:00
/* If we are already in the same object context, we inherit info from it. */
2013-10-02 05:57:45 -07:00
if ( pfptr )
2013-10-02 01:44:33 -07:00
{
2013-10-02 05:57:45 -07:00
memcpy ( fptr , pfptr , sizeof ( Eo2_Stack_Frame ) ) ;
2013-12-30 08:53:54 -08:00
if ( ! is_klass )
_eo_ref ( fptr - > o . obj ) ;
2013-07-24 15:10:26 -07:00
}
2013-12-25 06:16:34 -08:00
else
2013-07-24 15:10:26 -07:00
{
2013-10-02 05:57:45 -07:00
fptr - > eo_id = eo_id ;
2013-11-11 02:34:35 -08:00
fptr - > obj_data = EO2_INVALID_DATA ;
2013-12-30 08:53:54 -08:00
if ( is_klass )
{
EO_CLASS_POINTER_RETURN_VAL ( eo_id , _klass , EINA_FALSE ) ;
fptr - > o . kls = _klass ;
}
else
{
EO_OBJ_POINTER_RETURN_VAL ( eo_id , _obj , EINA_FALSE ) ;
fptr - > o . obj = _obj ;
_eo_ref ( _obj ) ;
}
2013-07-24 15:10:26 -07:00
}
2013-12-25 06:16:34 -08:00
2013-11-11 02:47:13 -08:00
if ( is_super )
2013-10-02 01:44:33 -07:00
{
EO_CLASS_POINTER_RETURN_VAL ( cur_klass_id , cur_klass , EINA_FALSE ) ;
2013-11-11 02:34:35 -08:00
if ( fptr - > cur_klass = = cur_klass )
2013-12-30 11:31:40 -08:00
fptr - > obj_data = EO2_INVALID_DATA ;
2013-11-11 02:34:35 -08:00
fptr - > cur_klass = cur_klass ;
2013-10-02 01:44:33 -07:00
}
else
2013-10-02 02:47:10 -07:00
{
2013-11-11 02:34:35 -08:00
fptr - > cur_klass = NULL ;
2013-07-30 06:02:35 -07:00
}
2013-10-02 02:47:10 -07:00
return EINA_TRUE ;
}
EAPI Eina_Bool
2013-11-11 02:51:47 -08:00
_eo2_do_start ( const Eo * eo_id , const Eo_Class * cur_klass_id , Eina_Bool is_super , const char * file EINA_UNUSED , const char * func EINA_UNUSED , int line EINA_UNUSED )
2013-10-02 02:47:10 -07:00
{
2013-10-02 05:57:45 -07:00
Eo2_Stack_Frame * fptr , * pfptr ;
2013-12-25 06:16:34 -08:00
2013-12-30 06:24:15 -08:00
if ( eo2_call_stack . frame_ptr = = eo2_call_stack . last_frame )
_eo2_call_stack_resize ( EINA_TRUE ) ;
2013-07-24 15:10:26 -07:00
fptr = eo2_call_stack . frame_ptr ;
2013-12-25 06:16:34 -08:00
2013-11-08 04:18:05 -08:00
pfptr = ( ( eo_id ) & & ( fptr - > eo_id = = eo_id ) ? fptr : NULL ) ;
2013-11-11 02:34:35 -08:00
fptr + + ;
2013-11-11 02:47:13 -08:00
if ( ! _eo2_do_internal ( eo_id , cur_klass_id , is_super , fptr , pfptr ) )
2013-12-30 06:24:15 -08:00
return EINA_FALSE ;
2013-11-11 02:34:35 -08:00
2013-10-02 05:57:45 -07:00
eo2_call_stack . frame_ptr + + ;
2013-07-30 06:02:35 -07:00
return EINA_TRUE ;
}
2013-10-02 02:47:10 -07:00
EAPI void
2013-11-11 02:51:47 -08:00
_eo2_do_end ( const Eo * * eo_id EINA_UNUSED )
2013-07-30 06:02:35 -07:00
{
Eo2_Stack_Frame * fptr ;
fptr = eo2_call_stack . frame_ptr ;
2013-12-30 11:23:22 -08:00
if ( ! _eo_is_a_class ( fptr - > eo_id ) & & fptr - > o . obj )
2013-11-11 02:34:35 -08:00
_eo_unref ( fptr - > o . obj ) ;
2013-07-30 06:02:35 -07:00
2013-07-24 15:10:26 -07:00
fptr - > obj_data = EO2_INVALID_DATA ;
2013-12-30 06:24:15 -08:00
if ( fptr = = eo2_call_stack . stack )
{
CRI ( " call stack underflow, abort. " ) ;
abort ( ) ;
}
eo2_call_stack . frame_ptr - - ;
if ( fptr = = eo2_call_stack . shrink_frame )
_eo2_call_stack_resize ( EINA_FALSE ) ;
2013-07-11 05:15:39 -07:00
}
2013-07-10 00:24:59 -07:00
EAPI Eina_Bool
2014-01-03 06:54:18 -08:00
_eo2_call_resolve ( const char * func_name , const Eo_Op op , Eo2_Op_Call_Data * call , const char * file , int line )
2013-07-09 05:21:11 -07:00
{
2013-07-24 15:10:26 -07:00
Eo2_Stack_Frame * fptr ;
2013-07-10 00:24:59 -07:00
const _Eo_Class * klass ;
const op_type_funcs * func ;
2013-11-11 02:34:35 -08:00
Eina_Bool is_obj ;
2013-07-24 15:10:26 -07:00
fptr = eo2_call_stack . frame_ptr ;
2013-11-11 02:34:35 -08:00
is_obj = ! _eo_is_a_class ( fptr - > eo_id ) ;
klass = ( is_obj ) ? fptr - > o . obj - > klass : fptr - > o . kls ;
/* If we have a current class, we need to itr to the next. */
if ( fptr - > cur_klass )
{
2013-11-11 05:06:51 -08:00
func = _eo2_kls_itr_next ( klass , fptr - > cur_klass , op ) ;
2013-11-11 02:34:35 -08:00
2013-11-11 05:06:51 -08:00
if ( ! func )
2013-12-30 11:31:40 -08:00
goto end ;
2013-11-11 05:06:51 -08:00
klass = func - > src ;
}
else
{
func = _dich_func_get ( klass , op ) ;
2013-11-11 02:34:35 -08:00
}
2013-07-09 05:21:11 -07:00
2013-12-26 15:18:45 -08:00
if ( EINA_UNLIKELY ( func = = NULL ) )
2013-07-30 06:02:35 -07:00
{
2014-01-08 02:10:48 -08:00
ERR ( " in %s:%d: you called func '%s' (%d) which is unknown in class '%s'. " ,
2014-01-03 06:54:18 -08:00
file , line , func_name , op , klass - > desc - > name ) ;
2013-12-26 15:18:45 -08:00
return EINA_FALSE ;
2013-07-30 06:02:35 -07:00
}
2013-07-10 00:24:59 -07:00
2013-11-08 07:30:25 -08:00
if ( EINA_LIKELY ( func - > func & & func - > src ) )
2013-07-08 08:31:36 -07:00
{
2013-07-10 00:24:59 -07:00
call - > func = func - > func ;
2013-11-07 14:38:36 -08:00
call - > klass = _eo_class_id_get ( klass ) ;
2013-12-25 06:16:34 -08:00
2013-11-11 02:34:35 -08:00
if ( is_obj )
2013-12-25 06:16:34 -08:00
{
2013-11-07 14:38:36 -08:00
call - > obj = ( Eo * ) fptr - > eo_id ;
2013-11-11 02:34:35 -08:00
if ( func - > src = = fptr - > o . obj - > klass )
2013-07-30 06:02:35 -07:00
{
if ( fptr - > obj_data = = EO2_INVALID_DATA )
2013-11-11 02:34:35 -08:00
fptr - > obj_data = _eo_data_scope_get ( fptr - > o . obj , func - > src ) ;
2013-12-25 06:16:34 -08:00
2013-07-30 06:02:35 -07:00
call - > data = fptr - > obj_data ;
}
else
2013-11-11 02:34:35 -08:00
call - > data = _eo_data_scope_get ( fptr - > o . obj , func - > src ) ;
2013-12-25 06:16:34 -08:00
}
else
2013-11-07 14:38:36 -08:00
{
call - > obj = call - > klass ;
call - > data = NULL ;
}
2013-12-25 06:16:34 -08:00
2013-07-10 00:24:59 -07:00
return EINA_TRUE ;
2013-07-08 08:31:36 -07:00
}
2013-12-26 15:18:45 -08:00
if ( func - > src ! = NULL )
{
2014-01-08 02:10:48 -08:00
ERR ( " in %s:%d: you called a pure virtual func '%s' (%d). " ,
2014-01-03 06:54:18 -08:00
file , line , func_name , op ) ;
2013-12-26 15:18:45 -08:00
return EINA_FALSE ;
}
2013-11-11 02:34:35 -08:00
end :
2013-07-08 08:31:36 -07:00
/* Try composite objects */
2013-11-11 02:34:35 -08:00
if ( is_obj )
2013-10-03 05:30:31 -07:00
{
Eina_List * itr ;
Eo * emb_eo_id ;
2013-11-11 02:34:35 -08:00
EINA_LIST_FOREACH ( fptr - > o . obj - > composite_objects , itr , emb_eo_id )
2013-10-03 05:30:31 -07:00
{
/* should never return */
EO_OBJ_POINTER_RETURN_VAL ( emb_eo_id , emb_obj , EINA_FALSE ) ;
func = _dich_func_get ( emb_obj - > klass , op ) ;
if ( func = = NULL )
continue ;
2013-11-11 02:34:35 -08:00
if ( EINA_LIKELY ( func - > func & & func - > src ) )
2013-10-03 05:30:31 -07:00
{
call - > obj = _eo_id_get ( emb_obj ) ;
call - > klass = _eo_class_id_get ( emb_obj - > klass ) ;
call - > func = func - > func ;
call - > data = _eo_data_scope_get ( emb_obj , func - > src ) ;
return EINA_TRUE ;
}
}
}
2013-11-11 02:34:35 -08:00
{
const _Eo_Class * main_klass ;
main_klass = ( is_obj ) ? fptr - > o . obj - > klass : fptr - > o . kls ;
/* If it's a do_super call. */
if ( fptr - > cur_klass )
{
2014-01-08 02:10:48 -08:00
ERR ( " in %s:%d: func '%s' (%d) could not be resolved for class '%s' for super of '%s'. " ,
2014-01-03 06:54:18 -08:00
file , line , func_name , op , main_klass - > desc - > name ,
2013-12-30 11:31:40 -08:00
fptr - > cur_klass - > desc - > name ) ;
2013-11-11 02:34:35 -08:00
}
else
{
2014-01-08 02:10:48 -08:00
ERR ( " in %s:%d: func '%s' (%d) could not be resolved for class '%s'. " ,
2014-01-03 06:54:18 -08:00
file , line , func_name , op , main_klass - > desc - > name ) ;
2013-11-11 02:34:35 -08:00
}
}
2013-10-03 05:30:31 -07:00
2013-07-10 00:24:59 -07:00
return EINA_FALSE ;
2013-07-08 08:31:36 -07:00
}
2013-12-25 05:51:52 -08:00
2013-12-25 07:14:55 -08:00
static inline const Eo2_Op_Description *
2013-10-03 05:30:31 -07:00
_eo2_api_desc_get ( const void * api_func , const _Eo_Class * klass , const _Eo_Class * * extns )
2013-12-25 05:51:52 -08:00
{
2013-12-25 06:04:26 -08:00
int imin , imax , imid ;
2013-08-14 04:48:54 -07:00
const _Eo_Class * cur_klass ;
const _Eo_Class * * kls_itr = NULL ;
2013-10-03 05:30:31 -07:00
const Eo2_Op_Description * op_desc ;
const Eo2_Op_Description * op_descs ;
2013-12-25 05:51:52 -08:00
2013-11-07 15:42:42 -08:00
if ( klass )
2013-12-25 05:51:52 -08:00
{
2013-11-07 15:42:42 -08:00
for ( kls_itr = klass - > mro ; * kls_itr ; kls_itr + + )
2013-07-25 23:39:34 -07:00
{
2013-11-07 15:42:42 -08:00
cur_klass = * kls_itr ;
imin = 0 ;
imax = cur_klass - > desc - > ops . count - 1 ;
op_descs = cur_klass - > desc - > ops . descs2 ;
2013-07-25 23:39:34 -07:00
2013-11-07 15:42:42 -08:00
while ( imax > = imin )
{
imid = ( imax + imin ) / 2 ;
op_desc = op_descs + imid ;
if ( op_desc - > api_func > api_func )
imin = imid + 1 ;
else if ( op_desc - > api_func < api_func )
imax = imid - 1 ;
else
return op_desc ;
}
2013-07-25 23:39:34 -07:00
2013-11-07 15:42:42 -08:00
}
2013-10-03 05:30:31 -07:00
}
if ( extns )
{
for ( kls_itr = extns ; * kls_itr ; kls_itr + + )
{
cur_klass = * kls_itr ;
2013-11-08 03:08:17 -08:00
op_desc = _eo2_api_desc_get ( api_func , cur_klass , NULL ) ;
if ( op_desc ) return op_desc ;
2013-10-03 05:30:31 -07:00
}
2013-12-25 05:51:52 -08:00
}
2013-12-25 07:14:55 -08:00
return NULL ;
}
EAPI Eo_Op
2014-01-03 06:54:18 -08:00
_eo2_api_op_id_get ( const void * api_func , const char * file , int line )
2013-12-25 07:14:55 -08:00
{
2013-12-30 11:31:40 -08:00
const Eo2_Op_Description * desc ;
const _Eo_Class * klass ;
2013-07-25 17:34:16 -07:00
2013-11-07 14:38:36 -08:00
Eina_Bool class_ref = _eo_is_a_class ( eo2_call_stack . frame_ptr - > eo_id ) ;
if ( class_ref )
2013-12-30 11:31:40 -08:00
klass = eo2_call_stack . frame_ptr - > o . kls ;
2013-07-31 14:37:06 -07:00
else
2013-12-30 11:31:40 -08:00
klass = eo2_call_stack . frame_ptr - > o . obj - > klass ;
2013-07-25 17:34:16 -07:00
2013-10-03 05:30:31 -07:00
desc = _eo2_api_desc_get ( api_func , klass , klass - > extensions ) ;
2013-12-25 07:14:55 -08:00
2013-07-25 17:34:16 -07:00
if ( desc = = NULL )
2013-07-31 14:37:06 -07:00
{
2014-01-08 02:10:48 -08:00
ERR ( " in %s:%d: unable to resolve %s api func %p. " ,
2014-01-03 06:54:18 -08:00
file , line , ( class_ref ? " class " : " regular " ) , api_func ) ;
2013-07-31 14:37:06 -07:00
return EO_NOOP ;
}
2013-12-25 07:14:55 -08:00
2013-12-30 11:31:40 -08:00
return desc - > op ;
2013-12-25 05:51:52 -08:00
}
static int
2013-07-18 00:10:07 -07:00
eo2_api_funcs_cmp ( const void * p1 , const void * p2 )
2013-12-25 05:51:52 -08:00
{
const Eo2_Op_Description * op1 , * op2 ;
op1 = ( Eo2_Op_Description * ) p1 ;
op2 = ( Eo2_Op_Description * ) p2 ;
if ( op1 - > api_func > op2 - > api_func ) return - 1 ;
else if ( op1 - > api_func < op2 - > api_func ) return 1 ;
else return 0 ;
}
EAPI void
2013-07-29 13:13:13 -07:00
_eo2_class_funcs_set ( _Eo_Class * klass )
2013-12-25 05:51:52 -08:00
{
2013-07-24 15:08:37 -07:00
int op_id ;
2014-01-08 02:13:34 -08:00
const void * last_api_func ;
2013-12-30 11:31:40 -08:00
const Eo2_Op_Description * api_desc ;
2013-12-25 05:51:52 -08:00
Eo2_Op_Description * op_desc ;
2013-12-25 06:12:06 -08:00
Eo2_Op_Description * op_descs ;
2013-12-25 05:51:52 -08:00
2014-01-08 02:13:34 -08:00
op_id = klass - > base_id ;
2013-12-25 06:12:06 -08:00
op_descs = klass - > desc - > ops . descs2 ;
2013-12-25 05:51:52 -08:00
2013-07-24 15:08:37 -07:00
qsort ( ( void * ) op_descs , klass - > desc - > ops . count , sizeof ( Eo2_Op_Description ) , eo2_api_funcs_cmp ) ;
2013-12-25 05:51:52 -08:00
2014-01-08 02:13:34 -08:00
DBG ( " Set functions for class '%s':%p " , klass - > desc - > name , klass ) ;
2013-11-07 15:51:00 -08:00
if ( ! op_descs ) return ;
2014-01-08 02:13:34 -08:00
last_api_func = NULL ;
2013-12-25 06:12:06 -08:00
for ( op_desc = op_descs ; op_desc - > op_type ! = EO_OP_TYPE_INVALID ; op_desc + + )
2013-12-25 05:51:52 -08:00
{
2013-07-24 15:08:37 -07:00
if ( op_desc - > api_func = = NULL )
2014-01-08 02:13:34 -08:00
{
ERR ( " Ignore %d NULL->%p '%s'. Can't set implementation for NULL API. " ,
op_desc - > op , op_desc - > func , op_desc - > doc ) ;
continue ;
}
2013-07-24 15:08:37 -07:00
2013-12-25 05:51:52 -08:00
if ( op_desc - > op = = EO_NOOP )
{
2014-01-08 02:13:34 -08:00
if ( op_desc - > api_func = = last_api_func )
{
ERR ( " API already defined %d %p->%p '%s'. Expect undefined behaviour. " ,
op_desc - > op , op_desc - > api_func , op_desc - > func , op_desc - > doc ) ;
}
2013-07-24 15:08:37 -07:00
op_desc - > op = op_id ;
op_id + + ;
}
else if ( op_desc - > op = = EO2_OP_OVERRIDE )
{
2013-10-03 05:30:31 -07:00
api_desc = _eo2_api_desc_get ( op_desc - > api_func , klass - > parent , klass - > extensions ) ;
2013-12-25 07:14:55 -08:00
if ( api_desc = = NULL )
2014-01-08 02:13:34 -08:00
{
ERR ( " Ignore override %p->%p. Can't find api func description in class hierarchy. " ,
op_desc - > api_func , op_desc - > func ) ;
continue ;
}
2013-12-25 07:14:55 -08:00
op_desc - > op = api_desc - > op ;
op_desc - > doc = api_desc - > doc ;
2013-12-25 05:51:52 -08:00
}
2013-07-24 15:08:37 -07:00
2014-01-08 02:13:34 -08:00
DBG ( " %4d %p->%p '%s' " , op_desc - > op , op_desc - > api_func , op_desc - > func , op_desc - > doc ) ;
2013-12-25 05:51:52 -08:00
_dich_func_set ( klass , op_desc - > op , op_desc - > func ) ;
2014-01-08 02:13:34 -08:00
last_api_func = op_desc - > api_func ;
2013-12-25 05:51:52 -08:00
}
}
2013-08-01 00:47:21 -07:00
EAPI Eo *
2013-11-08 07:20:38 -08:00
_eo2_add_internal_start ( const char * file , int line , const Eo_Class * klass_id , Eo * parent_id )
2013-08-01 00:47:21 -07:00
{
2013-12-26 15:00:11 -08:00
_Eo_Object * obj ;
2013-12-26 11:42:18 -08:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass , NULL ) ;
2013-08-01 00:47:21 -07:00
if ( parent_id )
{
EO_OBJ_POINTER_RETURN_VAL ( parent_id , parent , NULL ) ;
}
if ( EINA_UNLIKELY ( klass - > desc - > type ! = EO_CLASS_TYPE_REGULAR ) )
{
ERR ( " in %s:%d: Class '%s' is not instantiate-able. Aborting. " , file , line , klass - > desc - > name ) ;
return NULL ;
}
2013-12-26 15:00:11 -08:00
eina_spinlock_take ( & klass - > objects . trash_lock ) ;
obj = eina_trash_pop ( & klass - > objects . trash ) ;
if ( obj )
{
memset ( obj , 0 , klass - > obj_size ) ;
klass - > objects . trash_count - - ;
}
else
{
obj = calloc ( 1 , klass - > obj_size ) ;
}
eina_spinlock_release ( & klass - > objects . trash_lock ) ;
2013-08-01 00:47:21 -07:00
obj - > refcount + + ;
obj - > klass = klass ;
# ifndef HAVE_EO_ID
2013-12-26 15:00:11 -08:00
EINA_MAGIC_SET ( ( Eo_Base * ) obj , EO_EINA_MAGIC ) ;
2013-08-01 00:47:21 -07:00
# endif
2013-12-26 14:46:50 -08:00
Eo_Id eo_id = _eo_id_allocate ( obj ) ;
obj - > header . id = eo_id ;
2013-08-01 00:47:21 -07:00
_eo_condtor_reset ( obj ) ;
2013-12-26 15:00:11 -08:00
_eo_ref ( obj ) ;
eo2_do ( _eo_id_get ( obj ) , eo2_parent_set ( parent_id ) ) ;
2013-12-26 12:11:48 -08:00
2013-12-26 15:00:11 -08:00
return _eo_id_get ( obj ) ;
2013-08-01 00:47:21 -07:00
}
EAPI Eo *
2013-11-08 07:20:38 -08:00
_eo2_add_internal_end ( const char * file , int line , const Eo * eo_id )
2013-08-01 00:47:21 -07:00
{
Eo2_Stack_Frame * fptr ;
fptr = eo2_call_stack . frame_ptr ;
2013-12-26 14:46:50 -08:00
if ( ( fptr = = NULL ) | | ( fptr - > eo_id ! = eo_id ) )
2013-08-01 00:47:21 -07:00
{
ERR ( " in %s:%d - Something very wrong happend to the call stack. " , file , line ) ;
return NULL ;
}
2013-11-11 02:34:35 -08:00
if ( ! fptr - > o . obj - > condtor_done | | fptr - > o . obj - > do_error )
2013-08-01 00:47:21 -07:00
{
2013-11-11 02:34:35 -08:00
const _Eo_Class * klass = ( fptr - > cur_klass ) ?
fptr - > cur_klass : fptr - > o . obj - > klass ;
2013-08-01 00:47:21 -07:00
ERR ( " in %s:%d: Object of class '%s' - Not all of the object constructors have been executed. " ,
2013-11-11 02:34:35 -08:00
file , line , klass - > desc - > name ) ;
2013-11-08 07:20:38 -08:00
/* Unref twice, once for the ref in _eo2_add_internal_start, and once for the basic object ref. */
2013-11-11 02:34:35 -08:00
_eo_unref ( fptr - > o . obj ) ;
_eo_unref ( fptr - > o . obj ) ;
2013-08-01 00:47:21 -07:00
return NULL ;
}
2013-11-11 02:34:35 -08:00
_eo_unref ( fptr - > o . obj ) ;
2013-12-26 15:00:11 -08:00
return ( Eo * ) eo_id ;
2013-08-01 00:47:21 -07:00
}
2013-07-18 00:10:07 -07:00
/*****************************************************************************/
2013-04-17 07:08:12 -07:00
# define _EO_OP_ERR_NO_OP_PRINT(file, line, op, klass) \
2012-05-15 08:06:40 -07:00
do \
{ \
2013-04-18 04:19:02 -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 ; \
2013-06-03 04:30:19 -07:00
ERR ( " in %s:%d: Can't execute function %s:%s (op 0x%x) for class '%s'. Aborting. " , \
2014-01-03 07:01:27 -08:00
file , line , _dom_name , _eo_op_id_name_get ( op , op_klass - > desc - > version ) , op , \
2012-05-15 08:06:40 -07:00
( klass ) ? klass - > desc - > name : NULL ) ; \
} \
while ( 0 )
2012-05-15 07:16:58 -07:00
2013-07-02 20:53:25 -07:00
static inline Eina_Bool
2013-09-27 04:09:14 -07:00
_eo_op_internal ( const char * file , int line , Eo_Base * eo_ptr , const _Eo_Class * cur_klass ,
2013-04-17 07:08:12 -07:00
Eo_Op_Type op_type , Eo_Op op , va_list * p_list )
2012-04-05 08:31:15 -07:00
{
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
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
2013-09-26 15:02:30 -07:00
if ( op_desc & & ( op_type ! = op_desc - > op_type ) )
2012-04-24 01:04:14 -07:00
{
2013-09-26 15:02:30 -07:00
if ( op_type = = EO_OP_TYPE_REGULAR )
2012-05-15 07:16:58 -07:00
{
2013-04-17 07:08:12 -07:00
ERR ( " in %s:%d: Tried calling a class op '%s' (0x%x) from a non-class context. " ,
2013-09-26 15:02:30 -07:00
file , line , op_desc - > name , op ) ;
}
else
{
ERR ( " in %s:%d: Tried calling an instance op '%s' (0x%x) from a class context. " ,
file , line , op_desc - > name , op ) ;
2012-05-15 07:16:58 -07:00
}
2013-09-26 15:02:30 -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
{
2013-03-13 09:04:04 -07:00
const op_type_funcs * func = _eo_kls_itr_func_get ( cur_klass , op ) ;
2012-09-13 06:43:59 -07:00
if ( EINA_LIKELY ( func ! = NULL ) )
2012-04-05 08:31:15 -07:00
{
2013-09-25 10:10:03 -07:00
void * func_data = NULL ;
Eo * calling_obj ;
2013-09-26 15:02:30 -07:00
if ( op_type = = EO_OP_TYPE_REGULAR )
{
2013-09-27 04:09:14 -07:00
func_data = _eo_data_scope_get ( ( _Eo_Object * ) eo_ptr , func - > src ) ;
2013-09-27 04:27:00 -07:00
calling_obj = _eo_id_get ( ( _Eo_Object * ) eo_ptr ) ;
2013-09-26 15:02:30 -07:00
}
else
{
2013-09-25 10:10:03 -07:00
calling_obj = _eo_class_id_get ( cur_klass ) ;
2013-09-26 15:02:30 -07:00
}
2013-09-25 10:10:03 -07:00
func - > func ( calling_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 */
2013-09-26 15:02:30 -07:00
if ( op_type = = EO_OP_TYPE_REGULAR )
2012-04-12 03:14:58 -07:00
{
2014-03-05 14:57:39 -08:00
const _Eo_Object * * comp_itr = ( ( _Eo_Object * ) eo_ptr ) - > composites ;
if ( ! comp_itr ) return EINA_FALSE ;
for ( unsigned int i = 0 ; i < ( ( _Eo_Object * ) eo_ptr ) - > klass - > composites_count ; i + + , comp_itr + + )
if ( * comp_itr )
{
if ( _eo_op_internal ( file , line , ( Eo_Base * ) ( * comp_itr ) , ( * comp_itr ) - > klass , op_type , op , p_list ) )
{
return EINA_TRUE ;
}
}
2012-04-05 08:31:15 -07:00
}
2014-03-05 14:57:39 -08: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
2013-09-27 09:21:08 -07:00
_eo_dov_internal ( const char * file , int line , Eo_Base * obj , const _Eo_Class * klass , Eo_Op_Type op_type , va_list * p_list )
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-04-23 01:10:04 -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 )
{
2013-09-27 09:21:08 -07:00
if ( ! _eo_op_internal ( file , line , obj , klass , op_type , op , p_list ) )
2012-04-05 08:31:15 -07:00
{
2013-09-27 09:21:08 -07:00
_EO_OP_ERR_NO_OP_PRINT ( file , line , op , klass ) ;
2012-04-05 08:31:15 -07:00
ret = EINA_FALSE ;
break ;
}
2012-10-09 04:34:16 -07:00
op = va_arg ( * p_list , Eo_Op ) ;
2012-04-05 08:31:15 -07:00
}
2013-09-27 09:21:08 -07:00
return ret ;
}
static inline Eina_Bool
_eo_obj_dov_internal ( const char * file , int line , _Eo_Object * obj , va_list * p_list )
{
Eina_Bool prev_error ;
Eina_Bool ret = EINA_TRUE ;
prev_error = obj - > do_error ;
_eo_ref ( obj ) ;
ret = _eo_dov_internal ( file , line , ( Eo_Base * ) obj , obj - > klass , EO_OP_TYPE_REGULAR , p_list ) ;
2012-06-13 04:38:56 -07:00
if ( obj - > do_error )
2013-09-26 15:02:30 -07:00
ret = EINA_FALSE ;
2012-06-13 04:38:56 -07:00
obj - > do_error = prev_error ;
2013-04-12 09:17:30 -07:00
_eo_unref ( obj ) ;
2012-04-05 08:31:15 -07:00
return ret ;
}
2013-09-26 15:02:30 -07:00
static inline Eina_Bool
_eo_class_dov_internal ( const char * file , int line , _Eo_Class * klass , va_list * p_list )
2012-08-23 03:35:14 -07:00
{
2013-09-27 09:21:08 -07:00
return _eo_dov_internal ( file , line , ( Eo_Base * ) klass , klass , EO_OP_TYPE_CLASS , p_list ) ;
2013-09-26 15:02:30 -07:00
}
2012-08-23 03:35:14 -07:00
2013-09-26 15:02:30 -07:00
EAPI Eina_Bool
2013-12-26 14:46:50 -08:00
eo_do_internal ( const char * file , int line , const Eo * eo_id , . . . )
2013-09-26 15:02:30 -07:00
{
Eina_Bool ret = EINA_TRUE ;
va_list p_list ;
2013-12-26 14:46:50 -08:00
Eina_Bool class_ref = _eo_is_a_class ( eo_id ) ;
2012-08-23 03:35:14 -07:00
2013-09-26 15:40:09 -07:00
if ( class_ref )
2013-09-26 15:02:30 -07:00
{
2013-12-26 14:46:50 -08:00
EO_CLASS_POINTER_RETURN_VAL ( eo_id , klass , EINA_FALSE ) ;
2013-09-30 06:07:20 -07:00
2013-12-26 14:46:50 -08:00
va_start ( p_list , eo_id ) ;
2013-09-26 15:40:09 -07:00
ret = _eo_class_dov_internal ( file , line , klass , & p_list ) ;
2013-09-30 06:07:20 -07:00
va_end ( p_list ) ;
2013-09-26 15:02:30 -07:00
}
else
{
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , EINA_FALSE ) ;
2013-09-30 06:07:20 -07:00
2013-12-26 14:46:50 -08:00
va_start ( p_list , eo_id ) ;
2013-09-26 15:40:09 -07:00
ret = _eo_obj_dov_internal ( file , line , obj , & p_list ) ;
2013-09-30 06:07:20 -07:00
va_end ( p_list ) ;
2013-09-26 15:02:30 -07:00
}
2012-08-23 03:35:14 -07:00
return ret ;
}
2013-02-12 02:20:15 -08:00
EAPI Eina_Bool
2013-12-26 14:46:50 -08:00
eo_vdo_internal ( const char * file , int line , const Eo * eo_id , va_list * ops )
2013-02-12 02:20:15 -08:00
{
2013-12-26 14:46:50 -08:00
Eina_Bool class_ref = _eo_is_a_class ( eo_id ) ;
2013-02-12 02:20:15 -08:00
2013-09-26 15:40:09 -07:00
if ( class_ref )
2013-09-26 15:11:19 -07:00
{
2013-12-26 14:46:50 -08:00
EO_CLASS_POINTER_RETURN_VAL ( eo_id , klass , EINA_FALSE ) ;
2013-09-26 15:40:09 -07:00
return _eo_class_dov_internal ( file , line , klass , ops ) ;
2013-09-26 15:11:19 -07:00
}
else
{
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , EINA_FALSE ) ;
2013-09-26 15:40:09 -07:00
return _eo_obj_dov_internal ( file , line , obj , ops ) ;
2013-09-26 15:11:19 -07:00
}
2013-02-12 02:20:15 -08:00
}
2012-04-05 08:31:15 -07:00
EAPI Eina_Bool
2013-12-26 14:46:50 -08:00
eo_do_super_internal ( const char * file , int line , const Eo * eo_id , const Eo_Class * cur_klass_id , Eo_Op op , . . . )
2012-04-05 08:31:15 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * nklass ;
2013-09-26 15:38:15 -07:00
Eina_Bool op_ret = EINA_TRUE ;
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 ;
2013-04-18 04:19:02 -07:00
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( cur_klass_id , cur_klass , EINA_FALSE ) ;
2012-04-11 02:04:44 -07:00
2013-12-26 14:46:50 -08:00
if ( _eo_is_a_class ( eo_id ) )
2012-05-15 07:16:58 -07:00
{
2013-12-26 14:46:50 -08:00
EO_CLASS_POINTER_RETURN_VAL ( eo_id , klass , EINA_FALSE ) ;
2013-09-30 06:10:21 -07:00
va_start ( p_list , op ) ;
2013-09-26 15:38:15 -07:00
nklass = _eo_kls_itr_next ( klass , cur_klass , op ) ;
2013-09-27 04:09:14 -07:00
op_ret = _eo_op_internal ( file , line , ( Eo_Base * ) klass , nklass , EO_OP_TYPE_CLASS , op , & p_list ) ;
2013-09-30 06:10:21 -07:00
va_end ( p_list ) ;
2012-05-15 07:16:58 -07:00
}
2013-09-26 15:38:15 -07:00
else
2012-04-11 00:05:21 -07:00
{
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , EINA_FALSE ) ;
2013-09-30 06:10:21 -07:00
va_start ( p_list , op ) ;
2013-09-26 15:38:15 -07:00
nklass = _eo_kls_itr_next ( obj - > klass , cur_klass , op ) ;
2013-09-27 04:09:14 -07:00
op_ret = _eo_op_internal ( file , line , ( Eo_Base * ) obj , nklass , EO_OP_TYPE_REGULAR , op , & p_list ) ;
2013-09-26 15:38:15 -07:00
if ( obj - > do_error )
ret = EINA_FALSE ;
2013-09-30 06:10:21 -07:00
va_end ( p_list ) ;
2012-04-11 00:05:21 -07:00
}
2012-04-11 02:04:44 -07:00
2013-09-26 15:38:15 -07:00
if ( ! op_ret )
_EO_OP_ERR_NO_OP_PRINT ( file , line , op , nklass ) ;
return ( ret & op_ret ) ;
2012-04-05 08:31:15 -07:00
}
2013-09-27 08:38:15 -07:00
EAPI const Eo_Class *
2013-12-26 14:46:50 -08:00
eo_class_get ( const Eo * eo_id )
2012-04-05 08:31:15 -07:00
{
2013-12-26 14:46:50 -08:00
if ( _eo_is_a_class ( eo_id ) )
2013-09-26 15:13:31 -07:00
{
2013-12-26 14:46:50 -08:00
EO_CLASS_POINTER_RETURN_VAL ( eo_id , _klass , NULL ) ;
2013-12-26 15:33:49 -08:00
if ( _klass - > desc - > version = = EO2_VERSION )
return eo2_class_class_get ( ) ;
else
return eo_class_class_get ( ) ;
2013-09-26 15:13:31 -07:00
}
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , NULL ) ;
2012-04-23 01:10:04 -07:00
2013-04-18 04:19:02 -07:00
if ( obj - > klass )
return _eo_class_id_get ( obj - > klass ) ;
return NULL ;
2012-04-05 08:31:15 -07:00
}
EAPI const char *
2013-12-26 14:46:50 -08:00
eo_class_name_get ( const Eo_Class * eo_id )
2012-04-05 08:31:15 -07:00
{
2013-09-26 15:13:00 -07:00
const _Eo_Class * klass ;
2013-12-26 14:46:50 -08:00
if ( _eo_is_a_class ( eo_id ) )
2013-09-26 15:13:00 -07:00
{
2013-12-26 14:46:50 -08:00
EO_CLASS_POINTER_RETURN_VAL ( eo_id , _klass , NULL ) ;
2013-09-26 15:13:00 -07:00
klass = _klass ;
}
else
{
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , NULL ) ;
2013-09-26 15:13:00 -07:00
klass = obj - > klass ;
}
2012-04-23 01:10:04 -07:00
2012-04-05 08:31:15 -07:00
return klass - > desc - > name ;
}
static void
2013-04-18 04:19:02 -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 ;
2013-09-30 06:32:47 -07:00
if ( desc - > ops . base_op_id )
2012-07-10 07:01:45 -07:00
* ( 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
}
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-06-14 03:29:39 -07:00
static Eina_Bool
2013-04-18 04:19:02 -07:00
_eo_class_mro_has ( const _Eo_Class * klass , const _Eo_Class * find )
2012-06-14 03:29:39 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * * itr ;
2012-06-14 03:29:39 -07:00
for ( itr = klass - > mro ; * itr ; itr + + )
{
if ( * itr = = find )
{
return EINA_TRUE ;
}
}
return EINA_FALSE ;
}
# endif
2013-06-17 14:38:04 -07:00
static Eina_List *
_eo_class_list_remove_duplicates ( Eina_List * list )
{
Eina_List * itr1 , * itr2 , * itr2n ;
itr1 = eina_list_last ( list ) ;
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 ) )
{
list = eina_list_remove_list ( list , itr2 ) ;
}
itr2 = itr2n ;
}
itr1 = eina_list_prev ( itr1 ) ;
}
return list ;
}
2012-04-11 00:05:14 -07:00
static Eina_List *
2013-04-18 04:19:02 -07:00
_eo_class_mro_add ( Eina_List * mro , const _Eo_Class * klass )
2012-04-11 00:05:14 -07:00
{
if ( ! klass )
2013-06-17 14:41:02 -07:00
return mro ;
2012-04-11 00:05:14 -07:00
mro = eina_list_append ( mro , klass ) ;
2013-06-17 14:41:02 -07:00
/* Recursively add MIXINS extensions. */
2012-04-11 00:05:14 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * * extn_itr ;
2012-06-13 04:39:02 -07:00
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
2012-04-11 00:05:14 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * extn = * extn_itr ;
2013-06-17 14:41:02 -07:00
if ( extn - > desc - > type = = EO_CLASS_TYPE_MIXIN )
mro = _eo_class_mro_add ( mro , extn ) ;
2012-04-19 01:52:15 -07:00
}
}
2013-06-17 14:41:02 -07:00
mro = _eo_class_mro_add ( mro , klass - > parent ) ;
return mro ;
}
static Eina_List *
_eo_class_mro_init ( const Eo_Class_Description * desc , const _Eo_Class * parent , Eina_List * extensions )
{
Eina_List * mro = NULL ;
Eina_List * extn_itr = NULL ;
Eina_List * extn_pos = NULL ;
const _Eo_Class * extn = NULL ;
/* Add MIXINS extensions. */
EINA_LIST_FOREACH ( extensions , extn_itr , extn )
2012-04-19 01:52:15 -07:00
{
2013-06-17 14:41:02 -07:00
if ( extn - > desc - > type ! = EO_CLASS_TYPE_MIXIN )
continue ;
2012-04-19 01:52:15 -07:00
2013-06-17 14:41:02 -07:00
mro = _eo_class_mro_add ( mro , extn ) ;
extn_pos = eina_list_append ( extn_pos , eina_list_last ( mro ) ) ;
}
/* Check if we can create a consistent mro */
{
2012-04-19 01:52:15 -07:00
Eina_List * itr = extn_pos ;
2013-06-17 14:41:02 -07:00
EINA_LIST_FOREACH ( extensions , extn_itr , extn )
2012-04-19 01:52:15 -07:00
{
2012-06-13 04:39:02 -07:00
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 ) ;
2013-06-17 14:41:02 -07:00
eina_list_free ( extn_pos ) ;
ERR ( " Cannot create a consistent method resolution order for class '%s' because of '%s'. " , 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-12-14 12:03:25 -08:00
eina_list_free ( extn_pos ) ;
2012-04-19 01:52:15 -07:00
2013-06-17 14:41:02 -07:00
mro = _eo_class_mro_add ( mro , parent ) ;
2013-06-17 14:38:04 -07:00
mro = _eo_class_list_remove_duplicates ( mro ) ;
2013-06-17 14:41:02 -07:00
/* Will be replaced with the actual class pointer */
mro = eina_list_prepend ( mro , NULL ) ;
2012-04-11 00:05:14 -07:00
2013-06-17 14:41:02 -07:00
return mro ;
2012-04-11 00:05:14 -07:00
}
2012-04-05 08:31:15 -07:00
static void
2013-04-18 04:19:02 -07:00
_eo_class_constructor ( _Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
if ( klass - > constructed )
2013-07-29 14:52:46 -07:00
return ;
2012-04-05 08:31:15 -07:00
klass - > constructed = EINA_TRUE ;
2013-07-29 13:13:13 -07:00
if ( klass - > desc - > version = = EO2_VERSION )
_eo2_class_funcs_set ( klass ) ;
2012-04-11 00:05:14 -07:00
if ( klass - > desc - > class_constructor )
2013-07-29 14:52:46 -07:00
klass - > desc - > class_constructor ( _eo_class_id_get ( klass ) ) ;
2012-04-05 08:31:15 -07:00
}
EAPI void
2013-09-27 08:38:15 -07:00
eo_class_funcs_set ( Eo_Class * klass_id , const Eo_Op_Func_Description * func_descs )
2012-04-05 08:31:15 -07:00
{
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN ( klass_id , klass ) ;
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 ) ) )
{
2013-04-09 05:41:44 -07:00
ERR ( " Setting implementation for non-existent op 0x%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
{
2013-04-09 05:41:44 -07:00
ERR ( " Set function's op type (0x%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
2013-04-18 04:19:02 -07:00
eo_class_free ( _Eo_Class * klass )
2012-04-16 05:36:42 -07:00
{
2013-09-11 00:08:06 -07:00
void * data ;
2013-09-10 19:23:50 -07:00
2012-04-16 05:36:42 -07:00
if ( klass - > constructed )
{
if ( klass - > desc - > class_destructor )
2013-04-18 04:19:02 -07:00
klass - > desc - > class_destructor ( _eo_class_id_get ( klass ) ) ;
2012-04-16 05:36:42 -07:00
2012-05-07 23:56:57 -07:00
_dich_func_clean_all ( klass ) ;
2012-04-16 05:36:42 -07:00
}
2013-09-11 00:08:06 -07:00
EINA_TRASH_CLEAN ( & klass - > objects . trash , data )
2013-09-27 03:13:14 -07:00
free ( data ) ;
2013-09-10 19:23:50 -07:00
2013-09-11 00:08:06 -07:00
EINA_TRASH_CLEAN ( & klass - > iterators . trash , data )
2013-09-27 03:13:14 -07:00
free ( data ) ;
2013-09-11 00:08:06 -07:00
2013-10-10 01:26:02 -07:00
eina_spinlock_free ( & klass - > objects . trash_lock ) ;
eina_spinlock_free ( & klass - > iterators . trash_lock ) ;
2013-09-10 19:23:50 -07:00
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
2013-06-17 14:41:45 -07:00
_eo_class_check_op_descs ( const Eo_Class_Description * desc )
2012-04-17 01:05:09 -07:00
{
2012-05-01 00:40:14 -07:00
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 )
{
2013-04-09 05:41:44 -07:00
ERR ( " Wrong order in Ops description for class '%s'. Expected 0x%lx and got 0x%lx " , desc - > name , ( unsigned long ) i , ( unsigned long ) itr - > sub_op ) ;
2012-04-17 03:27:31 -07:00
}
else
{
2013-04-09 05:41:44 -07:00
ERR ( " Found too few Ops description for class '%s'. Expected 0x%lx descriptions, but found 0x%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
2013-12-26 14:46:50 -08:00
_eo_class_isa_func ( Eo * eo_id EINA_UNUSED , void * class_data EINA_UNUSED , va_list * list EINA_UNUSED )
2012-06-13 04:39:12 -07:00
{
/* Do nonthing. */
}
2013-09-27 08:38:15 -07:00
EAPI const Eo_Class *
eo_class_new ( const Eo_Class_Description * desc , const Eo_Class * parent_id , . . . )
2012-04-05 08:31:15 -07:00
{
2013-04-18 04:19:02 -07:00
_Eo_Class * klass ;
2012-04-05 08:31:15 -07:00
va_list p_list ;
2013-06-17 14:48:22 -07:00
size_t extn_sz , mro_sz , mixins_sz ;
2013-06-17 14:47:15 -07:00
Eina_List * extn_list , * mro , * mixins ;
2012-04-05 08:31:15 -07:00
2014-02-19 01:13:47 -08:00
EINA_SAFETY_ON_NULL_RETURN_VAL ( desc , NULL ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( desc - > name , NULL ) ;
2013-07-24 15:11:00 -07:00
if ( desc - > version = = EO2_VERSION )
{
// FIXME: eo2
/* if (!_eo2_class_check_op_descs(desc)) */
/* return NULL; */
}
else
2013-12-25 06:12:06 -08:00
{
if ( ! _eo_class_check_op_descs ( desc ) )
return NULL ;
}
2014-02-19 01:13:47 -08:00
2013-04-18 04:19:02 -07:00
_Eo_Class * parent = _eo_class_pointer_get ( parent_id ) ;
2013-09-26 08:06:46 -07:00
# ifndef HAVE_EO_ID
2013-09-27 04:01:30 -07:00
if ( parent & & ! EINA_MAGIC_CHECK ( ( Eo_Base * ) parent , EO_CLASS_EINA_MAGIC ) )
2012-04-23 01:10:04 -07:00
{
2013-09-27 04:01:30 -07:00
EINA_MAGIC_FAIL ( ( Eo_Base * ) parent , EO_CLASS_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
return NULL ;
}
2013-09-26 08:06:46 -07:00
# endif
2012-04-23 01:10:04 -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
}
2013-06-17 14:41:45 -07:00
/* Check parent */
if ( parent )
{
/* Verify the inheritance is allowed. */
switch ( desc - > type )
{
case EO_CLASS_TYPE_REGULAR :
case EO_CLASS_TYPE_REGULAR_NO_INSTANT :
if ( ( parent - > desc - > type ! = EO_CLASS_TYPE_REGULAR ) & &
( parent - > desc - > type ! = EO_CLASS_TYPE_REGULAR_NO_INSTANT ) )
{
ERR ( " Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s'). " ,
desc - > name , parent - > desc - > name ) ;
return NULL ;
}
break ;
case EO_CLASS_TYPE_INTERFACE :
case EO_CLASS_TYPE_MIXIN :
if ( ( parent - > desc - > type ! = EO_CLASS_TYPE_INTERFACE ) & &
( parent - > desc - > type ! = EO_CLASS_TYPE_MIXIN ) )
{
ERR ( " Non-regular classes ('%s') aren't allowed to inherit from regular classes ('%s'). " ,
desc - > name , parent - > desc - > name ) ;
return NULL ;
}
break ;
}
}
2013-06-17 14:35:48 -07:00
/* Build class extensions list */
2012-04-05 08:31:15 -07:00
{
2013-06-17 14:35:48 -07:00
DBG ( " Started building extensions list for class '%s' " , desc - > name ) ;
extn_list = NULL ;
2013-04-18 04:19:02 -07:00
const _Eo_Class * extn = NULL ;
2013-09-27 02:50:06 -07:00
const Eo_Id * extn_id = NULL ;
2013-06-17 14:35:48 -07:00
va_start ( p_list , parent_id ) ;
2012-04-05 08:31:15 -07:00
2013-09-27 02:50:06 -07:00
extn_id = va_arg ( p_list , Eo_Id * ) ;
2013-04-18 04:19:02 -07:00
while ( extn_id )
2012-04-05 08:31:15 -07:00
{
2013-09-27 08:38:15 -07:00
extn = _eo_class_pointer_get ( ( Eo_Class * ) extn_id ) ;
2012-04-05 08:31:15 -07:00
switch ( extn - > desc - > type )
{
2012-05-01 00:40:14 -07:00
case EO_CLASS_TYPE_REGULAR_NO_INSTANT :
2014-02-18 07:02:56 -08:00
case EO_CLASS_TYPE_REGULAR :
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 ;
}
2013-09-27 02:50:06 -07:00
extn_id = va_arg ( p_list , Eo_Id * ) ;
2012-04-05 08:31:15 -07:00
}
2012-06-13 04:39:02 -07:00
2013-06-17 14:35:48 -07:00
va_end ( p_list ) ;
2013-06-17 14:38:04 -07:00
extn_list = _eo_class_list_remove_duplicates ( extn_list ) ;
2013-06-17 14:35:48 -07:00
extn_sz = sizeof ( _Eo_Class * ) * ( eina_list_count ( extn_list ) + 1 ) ;
DBG ( " Finished building extensions list for class '%s' " , desc - > name ) ;
}
2013-06-17 14:41:02 -07:00
/* Prepare mro list */
{
DBG ( " Started building MRO list for class '%s' " , desc - > name ) ;
mro = _eo_class_mro_init ( desc , parent , extn_list ) ;
if ( ! mro )
{
eina_list_free ( extn_list ) ;
return NULL ;
}
mro_sz = sizeof ( _Eo_Class * ) * ( eina_list_count ( mro ) + 1 ) ;
DBG ( " Finished building MRO list for class '%s' " , desc - > name ) ;
}
2013-06-17 14:48:22 -07:00
/* Prepare mixins list */
{
Eina_List * itr ;
const _Eo_Class * kls_itr ;
DBG ( " Started building Mixins list for class '%s' " , desc - > name ) ;
mixins = NULL ;
EINA_LIST_FOREACH ( mro , itr , kls_itr )
{
if ( ( kls_itr ) & & ( kls_itr - > desc - > type = = EO_CLASS_TYPE_MIXIN ) & &
( kls_itr - > desc - > data_size > 0 ) )
mixins = eina_list_append ( mixins , kls_itr ) ;
}
mixins_sz = sizeof ( Eo_Extension_Data_Offset ) * ( eina_list_count ( mixins ) + 1 ) ;
if ( ( desc - > type = = EO_CLASS_TYPE_MIXIN ) & & ( desc - > data_size > 0 ) )
mixins_sz + = sizeof ( Eo_Extension_Data_Offset ) ;
DBG ( " Finished building Mixins list for class '%s' " , desc - > name ) ;
}
klass = calloc ( 1 , _eo_class_sz + extn_sz + mro_sz + mixins_sz ) ;
2013-09-27 03:13:14 -07:00
# ifndef HAVE_EO_ID
2013-09-27 04:01:30 -07:00
EINA_MAGIC_SET ( ( Eo_Base * ) klass , EO_CLASS_EINA_MAGIC ) ;
2013-09-26 08:06:46 -07:00
# endif
2013-10-10 01:26:02 -07:00
eina_spinlock_new ( & klass - > objects . trash_lock ) ;
eina_spinlock_new ( & klass - > iterators . trash_lock ) ;
2013-06-17 14:35:48 -07:00
klass - > parent = parent ;
klass - > desc = desc ;
klass - > extensions = ( const _Eo_Class * * ) ( ( char * ) klass + _eo_class_sz ) ;
2013-06-17 14:41:02 -07:00
klass - > mro = ( const _Eo_Class * * ) ( ( char * ) klass - > extensions + extn_sz ) ;
2013-06-17 14:48:22 -07:00
klass - > extn_data_off = ( Eo_Extension_Data_Offset * ) ( ( char * ) klass - > mro + mro_sz ) ;
2013-06-17 14:41:45 -07:00
if ( klass - > parent )
{
/* FIXME: Make sure this alignment is enough. */
klass - > data_offset = klass - > parent - > data_offset +
EO_ALIGN_SIZE ( klass - > parent - > desc - > data_size ) ;
}
2013-06-17 14:41:02 -07:00
mro = eina_list_remove ( mro , NULL ) ;
mro = eina_list_prepend ( mro , klass ) ;
2013-06-17 14:48:22 -07:00
if ( ( desc - > type = = EO_CLASS_TYPE_MIXIN ) & & ( desc - > data_size > 0 ) )
mixins = eina_list_prepend ( mixins , klass ) ;
2012-06-13 04:39:02 -07:00
2013-06-17 14:35:48 -07:00
/* Copy the extensions and free the list */
{
const _Eo_Class * extn = NULL ;
const _Eo_Class * * extn_itr = klass - > extensions ;
2012-06-13 04:39:02 -07:00
EINA_LIST_FREE ( extn_list , extn )
{
* ( extn_itr + + ) = extn ;
2014-03-05 14:57:39 -08:00
if ( extn - > desc - > type = = EO_CLASS_TYPE_REGULAR )
klass - > composites_count + = 1 ;
2013-06-17 14:35:48 -07:00
DBG ( " Added '%s' extension " , extn - > desc - > name ) ;
2012-06-13 04:39:02 -07:00
}
2013-06-17 14:35:48 -07:00
* ( extn_itr ) = NULL ;
2012-04-05 08:31:15 -07:00
}
2013-06-17 14:48:22 -07:00
/* Copy the mro and free the list. */
2013-06-17 14:41:02 -07:00
{
2013-06-17 14:48:22 -07:00
const _Eo_Class * kls_itr = NULL ;
2013-06-17 14:41:02 -07:00
const _Eo_Class * * 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 ;
}
2014-03-05 13:44:21 -08:00
size_t extn_data_off = klass - > data_offset ;
if ( klass - > desc - > type ! = EO_CLASS_TYPE_MIXIN )
extn_data_off + = EO_ALIGN_SIZE ( klass - > desc - > data_size ) ;
2013-06-17 14:32:50 -07:00
2013-06-17 14:48:22 -07:00
/* Feed the mixins data offsets and free the mixins list. */
2012-04-19 01:52:25 -07:00
{
2013-06-17 14:48:22 -07:00
const _Eo_Class * kls_itr = NULL ;
Eo_Extension_Data_Offset * extn_data_itr = klass - > extn_data_off ;
2013-06-17 14:47:15 -07:00
EINA_LIST_FREE ( mixins , kls_itr )
2012-04-19 01:52:25 -07:00
{
2013-06-17 14:47:15 -07:00
extn_data_itr - > klass = kls_itr ;
extn_data_itr - > offset = extn_data_off ;
2012-04-19 01:52:25 -07:00
2013-06-17 14:47:15 -07:00
extn_data_off + = EO_ALIGN_SIZE ( extn_data_itr - > klass - > desc - > data_size ) ;
extn_data_itr + + ;
2012-04-19 01:52:25 -07:00
2013-06-17 14:47:15 -07:00
DBG ( " Added '%s' to Data Offset info " , kls_itr - > desc - > name ) ;
}
extn_data_itr - > klass = 0 ;
extn_data_itr - > offset = 0 ;
2012-04-19 01:52:25 -07:00
}
2013-06-17 14:32:50 -07:00
klass - > obj_size = _eo_sz + extn_data_off ;
2014-03-05 14:57:39 -08:00
if ( klass - > composites_count > 0 )
klass - > obj_size + = ( klass - > composites_count * sizeof ( _Eo_Object * ) ) ;
2013-06-17 15:08:58 -07:00
if ( getenv ( " EO_DEBUG " ) )
2012-04-12 05:25:29 -07:00
{
2013-06-17 15:08:58 -07:00
fprintf ( stderr , " Eo class '%s' will take %u bytes per object. \n " ,
desc - > name , klass - > obj_size ) ;
2012-04-12 05:25:29 -07:00
}
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 */
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * * mro_itr = klass - > mro ;
2012-05-07 23:56:57 -07:00
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 */
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * * extn_itr ;
2012-06-13 04:39:12 -07:00
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * extn = * extn_itr ;
2012-06-13 04:39:12 -07:00
/* 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
}
}
2013-10-10 01:26:02 -07:00
eina_spinlock_take ( & _eo_class_creation_lock ) ;
2014-03-11 08:50:44 -07:00
klass - > header . id = + + _eo_classes_last_id | MASK_CLASS_TAG ;
2013-03-12 03:16:43 -07:00
{
2013-06-17 15:08:58 -07:00
/* FIXME: Handle errors. */
size_t arrsize = _eo_classes_last_id * sizeof ( * _eo_classes ) ;
_Eo_Class * * tmp ;
tmp = realloc ( _eo_classes , arrsize ) ;
/* If it's the first allocation, memset. */
if ( ! _eo_classes )
memset ( tmp , 0 , arrsize ) ;
_eo_classes = tmp ;
2013-09-27 02:59:41 -07:00
_eo_classes [ klass - > header . id - 1 ] = klass ;
2013-03-12 03:16:43 -07:00
}
2013-10-10 01:26:02 -07:00
eina_spinlock_release ( & _eo_class_creation_lock ) ;
2013-06-17 15:08:58 -07:00
_eo_class_constructor ( klass ) ;
2012-04-05 08:31:15 -07:00
2014-02-19 01:13:47 -08:00
DBG ( " Finished building class '%s' " , klass - > desc - > name ) ;
2013-04-18 04:19:02 -07:00
return _eo_class_id_get ( klass ) ;
2012-04-05 08:31:15 -07:00
}
2012-06-13 04:39:12 -07:00
EAPI Eina_Bool
2013-12-26 14:46:50 -08:00
eo_isa ( const Eo * eo_id , const Eo_Class * klass_id )
2012-06-13 04:39:12 -07:00
{
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , EINA_FALSE ) ;
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass , EINA_FALSE ) ;
2012-06-13 04:39:12 -07:00
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 ) ) ;
}
2013-09-24 21:32:13 -07:00
// A little bit hacky, but does the job
2013-09-11 00:08:06 -07:00
static void
2013-09-26 14:31:39 -07:00
_eo_parent_internal_set ( _Eo_Object * obj , . . . )
2013-09-11 00:08:06 -07:00
{
2013-09-24 21:32:13 -07:00
va_list p_list ;
2013-09-11 00:08:06 -07:00
2013-09-24 21:32:13 -07:00
va_start ( p_list , obj ) ;
2013-09-27 04:09:14 -07:00
_eo_op_internal ( __FILE__ , __LINE__ , ( Eo_Base * ) obj , obj - > klass ,
2013-09-24 21:32:13 -07:00
EO_OP_TYPE_REGULAR , EO_BASE_ID ( EO_BASE_SUB_ID_PARENT_SET ) ,
& p_list ) ;
va_end ( p_list ) ;
2013-09-11 00:08:06 -07:00
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2013-09-27 08:38:15 -07:00
eo_add_internal ( const char * file , int line , const Eo_Class * klass_id , Eo * parent_id , . . . )
2012-04-05 08:31:15 -07:00
{
2012-06-13 04:38:56 -07:00
Eina_Bool do_err ;
2013-09-26 14:31:39 -07:00
_Eo_Object * obj ;
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass , NULL ) ;
2012-04-23 01:10:04 -07:00
2013-04-18 04:19:02 -07:00
if ( parent_id )
{
EO_OBJ_POINTER_RETURN_VAL ( parent_id , parent , 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
{
2013-04-17 07:08:12 -07:00
ERR ( " in %s:%d: Class '%s' is not instantiate-able. Aborting. " , file , line , klass - > desc - > name ) ;
2012-04-05 08:31:15 -07:00
return NULL ;
}
2013-10-10 01:26:02 -07:00
eina_spinlock_take ( & klass - > objects . trash_lock ) ;
2013-09-11 00:08:06 -07:00
obj = eina_trash_pop ( & klass - > objects . trash ) ;
2013-09-10 19:23:50 -07:00
if ( obj )
{
memset ( obj , 0 , klass - > obj_size ) ;
2013-09-11 00:08:06 -07:00
klass - > objects . trash_count - - ;
2013-09-10 19:23:50 -07:00
}
else
{
obj = calloc ( 1 , klass - > obj_size ) ;
}
2013-10-10 01:26:02 -07:00
eina_spinlock_release ( & klass - > objects . trash_lock ) ;
2013-09-10 19:23:50 -07:00
2012-06-06 04:41:47 -07:00
obj - > refcount + + ;
2012-04-05 08:31:15 -07:00
obj - > klass = klass ;
2014-03-05 14:57:39 -08:00
if ( klass - > composites_count = = 0 )
obj - > composites = NULL ;
else
obj - > composites = ( const _Eo_Object * * )
( ( char * ) obj + klass - > obj_size - ( klass - > composites_count * sizeof ( _Eo_Object * ) ) ) ;
2012-04-05 08:31:15 -07:00
2013-04-18 04:19:02 -07:00
# ifndef HAVE_EO_ID
2013-09-27 04:01:30 -07:00
EINA_MAGIC_SET ( ( Eo_Base * ) obj , EO_EINA_MAGIC ) ;
2013-04-18 04:19:02 -07:00
# endif
Eo_Id obj_id = _eo_id_allocate ( obj ) ;
2013-09-27 02:59:41 -07:00
obj - > header . id = obj_id ;
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
2013-09-24 21:32:13 -07:00
_eo_parent_internal_set ( obj , parent_id ) ;
2013-07-30 06:12:03 -07:00
/* Run the relevant do stuff. */
2012-08-23 03:35:14 -07:00
{
va_list p_list ;
2013-04-18 04:19:02 -07:00
va_start ( p_list , parent_id ) ;
2013-09-26 15:02:30 -07:00
do_err = ! _eo_obj_dov_internal ( file , line , obj , & 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
{
2013-04-17 07:08:12 -07:00
ERR ( " in %s:%d, Object of class '%s' - One of the object constructors have failed. " ,
file , line , 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
{
2013-04-17 07:08:12 -07:00
ERR ( " in %s:%d: Object of class '%s' - Not all of the object constructors have been executed. " ,
file , line , 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
2013-09-27 04:27:00 -07:00
return _eo_id_get ( obj ) ;
2012-04-05 08:31:15 -07:00
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-05-01 00:40:14 -07:00
EAPI Eo *
2013-04-18 04:19:02 -07:00
eo_xref_internal ( const char * file , int line , Eo * obj_id , const Eo * ref_obj_id )
2012-04-17 08:22:22 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , obj_id ) ;
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
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-05-01 00:40:14 -07:00
Eo_Xref_Node * xref = calloc ( 1 , sizeof ( * xref ) ) ;
2013-04-18 04:19:02 -07:00
xref - > ref_obj = ref_obj_id ;
2012-04-17 08:22:22 -07:00
xref - > file = file ;
xref - > line = line ;
obj - > xrefs = eina_inlist_prepend ( obj - > xrefs , EINA_INLIST_GET ( xref ) ) ;
# else
2013-04-18 04:19:02 -07:00
( void ) ref_obj_id ;
2012-04-17 08:22:22 -07:00
( void ) file ;
( void ) line ;
# endif
2013-04-18 04:19:02 -07:00
return obj_id ;
2012-04-17 08:22:22 -07:00
}
EAPI void
2013-04-18 04:19:02 -07:00
eo_xunref ( Eo * obj_id , const Eo * ref_obj_id )
2012-04-17 08:22:22 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
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 )
{
2013-03-19 23:56:15 -07:00
if ( xref - > ref_obj = = ref_obj_id )
2013-04-02 17:31:17 -07:00
break ;
2012-04-17 08:22:22 -07:00
}
if ( xref )
{
obj - > xrefs = eina_inlist_remove ( obj - > xrefs , EINA_INLIST_GET ( xref ) ) ;
free ( xref ) ;
}
else
{
2013-03-19 23:56:15 -07:00
ERR ( " ref_obj (%p) does not reference obj (%p). Aborting unref. " , ref_obj_id , obj_id ) ;
2012-04-17 08:22:22 -07:00
return ;
}
# else
2013-04-18 04:19:02 -07:00
( void ) ref_obj_id ;
2012-04-17 08:22:22 -07:00
# endif
2012-05-06 05:03:26 -07:00
_eo_unref ( obj ) ;
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2013-04-18 04:19:02 -07:00
eo_ref ( const Eo * obj_id )
2012-04-05 08:31:15 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , ( Eo * ) obj_id ) ;
2012-04-23 01:10:04 -07:00
2013-04-18 04:19:02 -07:00
_eo_ref ( obj ) ;
return ( Eo * ) obj_id ;
2012-04-05 08:31:15 -07:00
}
2012-05-06 05:03:26 -07:00
EAPI void
2013-04-18 04:19:02 -07:00
eo_unref ( const Eo * obj_id )
2012-05-06 05:03:26 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2012-05-06 05:03:26 -07:00
_eo_unref ( obj ) ;
}
2012-06-07 00:17:45 -07:00
EAPI void
eo_del ( const Eo * obj )
{
2013-12-26 12:11:48 -08:00
EO_OBJ_POINTER_RETURN ( obj , _obj ) ;
if ( _obj - > klass - > desc - > version = = EO2_VERSION )
eo2_do ( ( Eo * ) obj , eo2_parent_set ( NULL ) ) ;
else
eo_do ( ( Eo * ) obj , eo_parent_set ( NULL ) ) ;
2012-06-07 00:17:45 -07:00
eo_unref ( obj ) ;
}
2012-04-11 00:05:37 -07:00
EAPI int
2013-04-18 04:19:02 -07:00
eo_ref_get ( const Eo * obj_id )
2012-04-11 00:05:37 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , 0 ) ;
2012-04-23 01:10:04 -07:00
2012-04-11 00:05:37 -07:00
return obj - > refcount ;
}
2012-04-05 08:31:15 -07:00
EAPI void
2013-04-18 04:19:02 -07:00
eo_error_set_internal ( const Eo * obj_id , const char * file , int line )
2012-04-05 08:31:15 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2012-04-23 01:10:04 -07:00
2014-01-08 02:10:48 -08:00
ERR ( " Error with obj '%p' at %s:%d. " , obj , file , line ) ;
2012-05-14 04:57:28 -07:00
2013-04-18 04:19:02 -07:00
obj - > do_error = EINA_TRUE ;
2012-04-12 07:58:57 -07:00
}
2012-06-10 07:04:53 -07:00
void
2013-04-18 04:19:02 -07:00
_eo_condtor_done ( Eo * obj_id )
2012-06-10 07:04:53 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , 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 ;
}
2012-05-06 05:03:21 -07:00
static inline void *
2013-09-26 14:31:39 -07:00
_eo_data_scope_get ( const _Eo_Object * obj , const _Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2013-08-09 06:58:55 -07:00
if ( EINA_LIKELY ( ( klass - > desc - > data_size > 0 ) & & ( klass - > desc - > type ! = EO_CLASS_TYPE_MIXIN ) ) )
return ( ( char * ) obj ) + _eo_sz + klass - > data_offset ;
if ( EINA_UNLIKELY ( klass - > desc - > data_size = = 0 ) )
return NULL ;
else
2012-04-19 01:52:25 -07:00
{
2013-08-09 06:58:55 -07:00
Eo_Extension_Data_Offset * doff_itr = obj - > klass - > extn_data_off ;
2012-04-19 01:52:25 -07:00
2013-08-09 06:58:55 -07:00
if ( ! doff_itr )
return NULL ;
2012-04-19 01:52:25 -07:00
2013-08-09 06:58:55 -07:00
while ( doff_itr - > klass )
2012-04-19 01:52:25 -07:00
{
2013-08-09 06:58:55 -07:00
if ( doff_itr - > klass = = klass )
return ( ( char * ) obj ) + _eo_sz + doff_itr - > offset ;
doff_itr + + ;
2012-04-19 01:52:25 -07:00
}
}
2012-05-06 05:03:21 -07:00
return NULL ;
}
2013-03-19 23:56:15 -07:00
static inline void *
2013-09-26 14:31:39 -07:00
_eo_data_xref_internal ( const char * file , int line , _Eo_Object * obj , const _Eo_Class * klass , const _Eo_Object * ref_obj )
2013-03-19 23:56:15 -07:00
{
2013-05-01 11:45:57 -07:00
void * data = NULL ;
2013-03-19 23:56:15 -07:00
if ( klass ! = NULL )
{
data = _eo_data_scope_get ( obj , klass ) ;
if ( data = = NULL ) return NULL ;
}
( obj - > datarefcount ) + + ;
# ifdef EO_DEBUG
Eo_Xref_Node * xref = calloc ( 1 , sizeof ( * xref ) ) ;
2013-09-27 03:13:14 -07:00
xref - > ref_obj = _eo_id_get ( ref_obj ) ;
2013-03-19 23:56:15 -07:00
xref - > file = file ;
xref - > line = line ;
obj - > data_xrefs = eina_inlist_prepend ( obj - > data_xrefs , EINA_INLIST_GET ( xref ) ) ;
# else
( void ) ref_obj ;
( void ) file ;
( void ) line ;
# endif
return data ;
}
static inline void
2013-09-26 14:31:39 -07:00
_eo_data_xunref_internal ( _Eo_Object * obj , void * data , const _Eo_Object * ref_obj )
2013-03-19 23:56:15 -07:00
{
# ifdef EO_DEBUG
const _Eo_Class * klass = obj - > klass ;
2013-09-23 02:07:07 -07:00
Eina_Bool in_range = ( ( ( char * ) data > = ( ( ( char * ) obj ) + _eo_sz ) ) & &
( ( char * ) data < ( ( ( char * ) obj ) + klass - > obj_size ) ) ) ;
2013-03-19 23:56:15 -07:00
if ( ! in_range )
{
2013-09-27 02:59:41 -07:00
ERR ( " Data %p is not in the data range of the object %p (%s). " , data , ( Eo * ) obj - > headr . id , obj - > klass - > desc - > name ) ;
2013-03-19 23:56:15 -07:00
}
# else
( void ) data ;
# endif
if ( obj - > datarefcount = = 0 )
{
2013-09-27 04:27:00 -07:00
ERR ( " Data for object %lx (%s) is already not referenced. " , ( unsigned long ) _eo_id_get ( obj ) , obj - > klass - > desc - > name ) ;
2013-03-19 23:56:15 -07:00
}
else
{
( obj - > datarefcount ) - - ;
}
# ifdef EO_DEBUG
Eo_Xref_Node * xref = NULL ;
EINA_INLIST_FOREACH ( obj - > data_xrefs , xref )
{
2013-09-27 03:13:14 -07:00
if ( xref - > ref_obj = = _eo_id_get ( ref_obj ) )
2013-03-19 23:56:15 -07:00
break ;
}
if ( xref )
{
obj - > data_xrefs = eina_inlist_remove ( obj - > data_xrefs , EINA_INLIST_GET ( xref ) ) ;
free ( xref ) ;
}
else
{
2013-09-27 03:13:14 -07:00
ERR ( " ref_obj (0x%lx) does not reference data (%p) of obj (0x%lx). " , ( unsigned long ) _eo_id_get ( ref_obj ) , data , ( unsigned long ) _eo_id_get ( obj ) ) ;
2013-03-19 23:56:15 -07:00
}
# else
( void ) ref_obj ;
# endif
}
2012-05-06 05:03:21 -07:00
EAPI void *
2013-09-27 08:38:15 -07:00
eo_data_get ( const Eo * obj_id , const Eo_Class * klass_id )
2013-03-19 23:56:15 -07:00
{
return eo_data_scope_get ( obj_id , klass_id ) ;
}
EAPI void *
2013-09-27 08:38:15 -07:00
eo_data_scope_get ( const Eo * obj_id , const Eo_Class * klass_id )
2012-05-06 05:03:21 -07:00
{
void * ret ;
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , NULL ) ;
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass , NULL ) ;
2012-05-06 05:03:21 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
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
2013-03-19 23:56:15 -07:00
ret = _eo_data_scope_get ( obj , klass ) ;
2012-05-06 05:03:21 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-05-06 05:03:21 -07:00
if ( ! ret & & ( klass - > desc - > data_size = = 0 ) )
2012-05-06 05:03:07 -07:00
{
2014-01-08 02:10:48 -08:00
ERR ( " Tried getting data of class '%s', but it has none. " , klass - > desc - > name ) ;
2012-05-06 05:03:07 -07:00
}
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
}
2013-03-19 23:56:15 -07:00
EAPI void *
2013-09-27 08:38:15 -07:00
eo_data_xref_internal ( const char * file , int line , const Eo * obj_id , const Eo_Class * klass_id , const Eo * ref_obj_id )
2013-03-19 23:56:15 -07:00
{
void * ret ;
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , NULL ) ;
EO_OBJ_POINTER_RETURN_VAL ( ref_obj_id , ref_obj , NULL ) ;
_Eo_Class * klass = NULL ;
if ( klass_id )
{
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass2 , NULL ) ;
klass = klass2 ;
2013-03-19 23:56:15 -07:00
# ifdef EO_DEBUG
if ( ! _eo_class_mro_has ( obj - > klass , klass ) )
{
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_xref_internal ( file , line , obj , klass , ref_obj ) ;
# ifdef EO_DEBUG
if ( klass & & ! ret & & ( klass - > desc - > data_size = = 0 ) )
{
2014-01-08 02:10:48 -08:00
ERR ( " Tried getting data of class '%s', but it has none. " , klass - > desc - > name ) ;
2013-03-19 23:56:15 -07:00
}
# endif
return ret ;
}
EAPI void
eo_data_xunref_internal ( const Eo * obj_id , void * data , const Eo * ref_obj_id )
{
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
EO_OBJ_POINTER_RETURN ( ref_obj_id , ref_obj ) ;
_eo_data_xunref_internal ( obj , data , ref_obj ) ;
}
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 )
2013-04-02 17:31:17 -07:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
eina_init ( ) ;
2013-09-26 14:31:39 -07:00
_eo_sz = EO_ALIGN_SIZE ( sizeof ( _Eo_Object ) ) ;
_eo_class_sz = EO_ALIGN_SIZE ( sizeof ( _Eo_Class ) ) ;
2013-04-10 19:58:53 -07:00
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
{
2014-01-08 02:10:48 -08:00
EINA_LOG_ERR ( " Could not register log domain: %s. " , log_dom ) ;
2012-04-05 08:31:15 -07:00
return EINA_FALSE ;
}
2013-10-10 01:26:02 -07:00
if ( ! eina_spinlock_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 ,
2013-04-02 17:31:17 -07:00
EO_FREED_EINA_MAGIC_STR ) ;
2012-05-01 00:40:14 -07:00
eina_magic_string_static_set ( EO_CLASS_EINA_MAGIC ,
2013-04-02 17:31:17 -07:00
EO_CLASS_EINA_MAGIC_STR ) ;
2012-04-23 01:10:04 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-07-10 07:01:54 -07:00
/* 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
2013-03-27 05:42:55 -07:00
eina_log_timing ( _eo_log_dom ,
2013-04-02 17:31:17 -07:00
EINA_LOG_STATE_STOP ,
EINA_LOG_STATE_INIT ) ;
2013-03-27 05:42:55 -07:00
2013-10-12 14:51:59 -07:00
/* bootstrap EO_CLASS_CLASS */
( void ) eo_class_class_get ( ) ;
2013-10-02 05:57:45 -07:00
if ( ! _eo2_call_stack_init ( ) )
{
EINA_LOG_ERR ( " Could not init eo2 call stack. " ) ;
return EINA_FALSE ;
}
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 ;
2013-04-18 04:19:02 -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 )
2013-04-02 17:31:17 -07:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
2013-03-27 05:42:55 -07:00
eina_log_timing ( _eo_log_dom ,
2013-04-02 17:31:17 -07:00
EINA_LOG_STATE_START ,
EINA_LOG_STATE_SHUTDOWN ) ;
2013-03-27 05:42:55 -07:00
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 )
2013-04-02 17:31:17 -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 )
2013-04-02 17:31:17 -07:00
free ( _eo_classes ) ;
2012-04-05 08:31:15 -07:00
2013-10-10 01:26:02 -07:00
eina_spinlock_free ( & _eo_class_creation_lock ) ;
2012-04-23 01:09:54 -07:00
2013-10-02 05:57:45 -07:00
_eo2_call_stack_free ( ) ;
2013-04-18 04:19:02 -07:00
_eo_free_ids_tables ( ) ;
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 ;
}
2014-02-18 06:33:24 -08:00
EAPI Eina_Bool
2013-04-18 04:19:02 -07:00
eo_composite_attach ( Eo * comp_obj_id , Eo * parent_id )
2012-04-05 08:31:15 -07:00
{
2014-03-05 14:57:39 -08:00
const _Eo_Object * * comp_itr ;
const _Eo_Object * * comp_dst ;
2014-02-18 06:33:24 -08:00
EO_OBJ_POINTER_RETURN_VAL ( comp_obj_id , comp_obj , EINA_FALSE ) ;
EO_OBJ_POINTER_RETURN_VAL ( parent_id , parent , EINA_FALSE ) ;
2014-03-05 14:57:39 -08:00
if ( ! parent - > composites ) return EINA_FALSE ;
if ( comp_obj - > klass - > desc - > type ! = EO_CLASS_TYPE_REGULAR ) return EINA_FALSE ;
2014-02-27 06:02:45 -08:00
if ( ! eo_isa ( parent_id , _eo_class_id_get ( comp_obj - > klass ) ) ) return EINA_FALSE ;
2014-02-18 06:33:24 -08:00
2014-03-05 14:57:39 -08:00
comp_dst = NULL ;
comp_itr = parent - > composites ;
for ( unsigned int i = 0 ; i < parent - > klass - > composites_count ; i + + , comp_itr + + )
2014-02-18 06:33:24 -08:00
{
2014-03-05 14:57:39 -08:00
if ( * comp_itr )
2014-02-18 06:33:24 -08:00
{
2014-03-05 14:57:39 -08:00
if ( ( * comp_itr ) - > klass = = comp_obj - > klass )
2014-02-18 06:33:24 -08:00
return EINA_FALSE ;
}
2014-03-05 14:57:39 -08:00
else if ( ! comp_dst )
comp_dst = comp_itr ;
2014-02-18 06:33:24 -08:00
}
2012-04-23 01:10:04 -07:00
2014-03-05 14:57:39 -08:00
if ( ! comp_dst )
return EINA_FALSE ;
2014-02-27 06:02:45 -08:00
2014-03-05 14:57:39 -08:00
comp_obj - > composite = EINA_TRUE ;
* comp_dst = comp_obj ;
2013-10-03 05:17:03 -07:00
if ( comp_obj - > klass - > desc - > version = = EO2_VERSION )
eo2_do ( comp_obj_id , eo2_parent_set ( parent_id ) ) ;
else
eo_do ( comp_obj_id , eo_parent_set ( parent_id ) ) ;
2014-02-18 06:33:24 -08:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
}
2014-03-05 14:57:39 -08:00
EAPI Eina_Bool
2013-04-18 04:19:02 -07:00
eo_composite_detach ( Eo * comp_obj_id , Eo * parent_id )
2012-04-05 08:31:15 -07:00
{
2014-03-05 14:57:39 -08:00
const _Eo_Object * * comp_itr ;
EO_OBJ_POINTER_RETURN_VAL ( comp_obj_id , comp_obj , EINA_FALSE ) ;
EO_OBJ_POINTER_RETURN_VAL ( parent_id , parent , EINA_FALSE ) ;
if ( ! parent - > composites ) return EINA_FALSE ;
comp_itr = parent - > composites ;
for ( unsigned int i = 0 ; i < parent - > klass - > composites_count ; i + + , comp_itr + + )
{
if ( * comp_itr = = comp_obj )
{
comp_obj - > composite = EINA_FALSE ;
* comp_itr = NULL ;
2013-10-03 05:17:03 -07:00
if ( comp_obj - > klass - > desc - > version = = EO2_VERSION )
eo2_do ( comp_obj_id , eo2_parent_set ( NULL ) ) ;
else
eo_do ( comp_obj_id , eo_parent_set ( NULL ) ) ;
2014-03-05 14:57:39 -08:00
return EINA_TRUE ;
}
}
2012-04-23 01:10:04 -07:00
2014-03-05 14:57:39 -08:00
return EINA_FALSE ;
2012-04-05 08:31:15 -07:00
}
EAPI Eina_Bool
2013-04-18 04:19:02 -07:00
eo_composite_is ( const Eo * comp_obj_id )
2012-04-05 08:31:15 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( comp_obj_id , comp_obj , 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
2013-04-18 04:19:02 -07:00
eo_destructed_is ( const Eo * obj_id )
2012-09-12 04:31:58 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , EINA_FALSE ) ;
2012-09-12 04:31:58 -07:00
return obj - > del ;
}
2012-05-21 04:45:32 -07:00
EAPI void
2013-04-18 04:19:02 -07:00
eo_manual_free_set ( Eo * obj_id , Eina_Bool manual_free )
2012-05-21 04:45:32 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2012-05-21 04:45:32 -07:00
obj - > manual_free = manual_free ;
}
2013-11-26 04:10:53 -08:00
EAPI Eina_Bool
2013-04-18 04:19:02 -07:00
eo_manual_free ( Eo * obj_id )
2012-05-21 04:45:32 -07:00
{
2013-11-26 05:08:55 -08:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , EINA_FALSE ) ;
2012-05-21 04:45:32 -07:00
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 ) ;
2013-11-26 04:10:53 -08:00
return EINA_FALSE ;
2012-05-21 04:45:32 -07:00
}
2012-06-06 04:41:53 -07:00
if ( ! obj - > del )
2012-05-21 04:45:32 -07:00
{
2013-04-18 04:19:02 -07:00
ERR ( " Tried deleting the object %p while still referenced(%d). " , obj_id , obj - > refcount ) ;
2013-11-26 04:10:53 -08:00
return EINA_FALSE ;
2012-05-21 04:45:32 -07:00
}
_eo_free ( obj ) ;
2013-11-26 04:10:53 -08:00
return EINA_TRUE ;
2012-05-21 04:45:32 -07:00
}
2013-01-28 22:36:23 -08:00