123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- #include <ft2build.h>
- #include FT_INTERNAL_OBJECT_H
- #include FT_INTERNAL_DEBUG_H
- #include FT_INTERNAL_OBJECTS_H
- #define FT_MAGIC_DEATH 0xDEADdead
- #define FT_MAGIC_CLASS 0x12345678
- #define FT_TYPE_HASH(x) (( (FT_UInt32)(x) >> 2 )^( (FT_UInt32)(x) >> 10 ))
- #define FT_OBJECT_CHECK(o) \
- ( FT_OBJECT(o) != NULL && \
- FT_OBJECT(o)->clazz != NULL && \
- FT_OBJECT(o)->ref_count >= 1 && \
- FT_OBJECT(o)->clazz->magic == FT_MAGIC_CLASS )
- #define FT_CLASS_CHECK(c) \
- ( FT_CLASS(c) != NULL && FT_CLASS(c)->magic == FT_MAGIC_CLASS )
- #define FT_ASSERT_IS_CLASS(c) FT_ASSERT( FT_CLASS_CHECK(c) )
- /*******************************************************************/
- /*******************************************************************/
- /***** *****/
- /***** *****/
- /***** M E T A - C L A S S *****/
- /***** *****/
- /***** *****/
- /*******************************************************************/
- /*******************************************************************/
- /* forward declaration */
- FT_BASE_DEF( FT_Error )
- ft_metaclass_init( FT_MetaClass meta,
- FT_Library library );
- /* forward declaration */
- FT_BASE_DEF( void )
- ft_metaclass_done( FT_MetaClass meta );
- /* class type for the meta-class itself */
- static const FT_TypeRec ft_meta_class_type =
- {
- "FT2.MetaClass",
- NULL,
- sizeof( FT_MetaClassRec ),
- (FT_Object_InitFunc) ft_metaclass_init,
- (FT_Object_DoneFunc) ft_metaclass_done,
- sizeof( FT_ClassRec ),
- (FT_Object_InitFunc) NULL,
- (FT_Object_DoneFunc) NULL
- };
- /* destroy a given class */
- static void
- ft_class_hnode_destroy( FT_ClassHNode node )
- {
- FT_Class clazz = node->clazz;
- FT_Memory memory = clazz->memory;
- if ( clazz->class_done )
- clazz->class_done( (FT_Object) clazz );
- FT_FREE( clazz );
- node->clazz = NULL;
- node->type = NULL;
- FT_FREE( node );
- }
- static FT_Int
- ft_type_equal( FT_Type type1,
- FT_Type type2 )
- {
- if ( type1 == type2 )
- goto Ok;
- if ( type1 == NULL || type2 == NULL )
- goto Fail;
- /* compare parent types */
- if ( type1->super != type2->super )
- {
- if ( type1->super == NULL ||
- type2->super == NULL ||
- !ft_type_equal( type1, type2 ) )
- goto Fail;
- }
- /* compare type names */
- if ( type1->name != type2->name )
- {
- if ( type1->name == NULL ||
- type2->name == NULL ||
- ft_strcmp( type1->name, type2->name ) != 0 )
- goto Fail;
- }
- /* compare the other type fields */
- if ( type1->class_size != type2->class_size ||
- type1->class_init != type2->class_init ||
- type1->class_done != type2->class_done ||
- type1->obj_size != type2->obj_size ||
- type1->obj_init != type2->obj_init ||
- type1->obj_done != type2->obj_done )
- goto Fail;
- Ok:
- return 1;
- Fail:
- return 0;
- }
- static FT_Int
- ft_class_hnode_equal( const FT_ClassHNode node1,
- const FT_ClassHNode node2 )
- {
- FT_Type type1 = node1->type;
- FT_Type type2 = node2->type;
- /* comparing the pointers should work in 99% of cases */
- return ( type1 == type2 ) ? 1 : ft_type_equal( type1, type2 );
- }
- FT_BASE_DEF( void )
- ft_metaclass_done( FT_MetaClass meta )
- {
- /* clear all classes */
- ft_hash_done( &meta->type_to_class,
- (FT_Hash_ForeachFunc) ft_class_hnode_destroy,
- NULL );
- meta->clazz.object.clazz = NULL;
- meta->clazz.object.ref_count = 0;
- meta->clazz.magic = FT_MAGIC_DEATH;
- }
- FT_BASE_DEF( FT_Error )
- ft_metaclass_init( FT_MetaClass meta,
- FT_Library library )
- {
- FT_ClassRec* clazz = (FT_ClassRec*) &meta->clazz;
- /* the meta-class is its OWN class !! */
- clazz->object.clazz = (FT_Class) clazz;
- clazz->object.ref_count = 1;
- clazz->magic = FT_MAGIC_CLASS;
- clazz->library = library;
- clazz->memory = library->memory;
- clazz->type = &ft_meta_class_type;
- clazz->info = NULL;
- clazz->class_done = (FT_Object_DoneFunc) ft_metaclass_done;
- clazz->obj_size = sizeof( FT_ClassRec );
- clazz->obj_init = NULL;
- clazz->obj_done = NULL;
- return ft_hash_init( &meta->type_to_class,
- (FT_Hash_EqualFunc) ft_class_hnode_equal,
- library->memory );
- }
- /* find or create the class corresponding to a given type */
- /* note that this function will retunr NULL in case of */
- /* memory overflow */
- /* */
- static FT_Class
- ft_metaclass_get_class( FT_MetaClass meta,
- FT_Type ctype )
- {
- FT_ClassHNodeRec keynode, *node, **pnode;
- FT_Memory memory;
- FT_ClassRec* clazz;
- FT_Class parent;
- FT_Error error;
- keynode.hnode.hash = FT_TYPE_HASH( ctype );
- keynode.type = ctype;
- pnode = (FT_ClassHNode*) ft_hash_lookup( &meta->type_to_class,
- (FT_HashNode) &keynode );
- node = *pnode;
- if ( node != NULL )
- {
- clazz = (FT_ClassRec*) node->clazz;
- goto Exit;
- }
- memory = FT_CLASS__MEMORY(meta);
- clazz = NULL;
- parent = NULL;
- if ( ctype->super != NULL )
- {
- FT_ASSERT( ctype->super->class_size <= ctype->class_size );
- FT_ASSERT( ctype->super->obj_size <= ctype->obj_size );
- parent = ft_metaclass_get_class( meta, ctype->super );
- }
- if ( !FT_NEW( node ) )
- {
- if ( !FT_ALLOC( clazz, ctype->class_size ) )
- {
- if ( parent )
- FT_MEM_COPY( (FT_ClassRec*)clazz, parent, parent->type->class_size );
- clazz->object.clazz = (FT_Class) meta;
- clazz->object.ref_count = 1;
- clazz->memory = memory;
- clazz->library = FT_CLASS__LIBRARY(meta);
- clazz->super = parent;
- clazz->type = ctype;
- clazz->info = NULL;
- clazz->magic = FT_MAGIC_CLASS;
- clazz->class_done = ctype->class_done;
- clazz->obj_size = ctype->obj_size;
- clazz->obj_init = ctype->obj_init;
- clazz->obj_done = ctype->obj_done;
- if ( parent )
- {
- if ( clazz->class_done == NULL )
- clazz->class_done = parent->class_done;
- if ( clazz->obj_init == NULL )
- clazz->obj_init = parent->obj_init;
- if ( clazz->obj_done == NULL )
- clazz->obj_done = parent->obj_done;
- }
- /* find class initializer, if any */
- {
- FT_Type ztype = ctype;
- FT_Object_InitFunc cinit = NULL;
- do
- {
- cinit = ztype->class_init;
- if ( cinit != NULL )
- break;
- ztype = ztype->super;
- }
- while ( ztype != NULL );
- /* then call it when needed */
- if ( cinit != NULL )
- error = cinit( (FT_Object) clazz, NULL );
- }
- }
- if (error)
- {
- if ( clazz )
- {
- /* we always call the class destructor when */
- /* an error was detected in the constructor !! */
- if ( clazz->class_done )
- clazz->class_done( (FT_Object) clazz );
- FT_FREE( clazz );
- }
- FT_FREE( node );
- }
- }
- Exit:
- return (FT_Class) clazz;
- }
- FT_BASE_DEF( FT_Int )
- ft_object_check( FT_Pointer obj )
- {
- return FT_OBJECT_CHECK(obj);
- }
- FT_BASE_DEF( FT_Int )
- ft_object_is_a( FT_Pointer obj,
- FT_Class clazz )
- {
- if ( FT_OBJECT_CHECK(obj) )
- {
- FT_Class c = FT_OBJECT__CLASS(obj);
- do
- {
- if ( c == clazz )
- return 1;
- c = c->super;
- }
- while ( c == NULL );
- return (clazz == NULL);
- }
- return 0;
- }
- FT_BASE_DEF( FT_Error )
- ft_object_create( FT_Object *pobject,
- FT_Class clazz,
- FT_Pointer init_data )
- {
- FT_Memory memory;
- FT_Error error;
- FT_Object obj;
- FT_ASSERT_IS_CLASS(clazz);
- memory = FT_CLASS__MEMORY(clazz);
- if ( !FT_ALLOC( obj, clazz->obj_size ) )
- {
- obj->clazz = clazz;
- obj->ref_count = 1;
- if ( clazz->obj_init )
- {
- error = clazz->obj_init( obj, init_data );
- if ( error )
- {
- /* IMPORTANT: call the destructor when an error */
- /* was detected in the constructor !! */
- if ( clazz->obj_done )
- clazz->obj_done( obj );
- FT_FREE( obj );
- }
- }
- }
- *pobject = obj;
- return error;
- }
- FT_BASE_DEF( FT_Class )
- ft_class_find_by_type( FT_Type type,
- FT_Library library )
- {
- FT_MetaClass meta = &library->meta_class;
- return ft_metaclass_get_class( meta, type );
- }
- FT_BASE_DEF( FT_Error )
- ft_object_create_from_type( FT_Object *pobject,
- FT_Type type,
- FT_Pointer init_data,
- FT_Library library )
- {
- FT_Class clazz;
- FT_Error error;
- clazz = ft_class_find_by_type( type, library );
- if ( clazz )
- error = ft_object_create( pobject, clazz, init_data );
- else
- {
- *pobject = NULL;
- error = FT_Err_Out_Of_Memory;
- }
- return error;
- }
|