1*37da2899SCharles.Forsyth #include <ft2build.h> 2*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECT_H 3*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 4*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H 5*37da2899SCharles.Forsyth 6*37da2899SCharles.Forsyth #define FT_MAGIC_DEATH 0xDEADdead 7*37da2899SCharles.Forsyth #define FT_MAGIC_CLASS 0x12345678 8*37da2899SCharles.Forsyth 9*37da2899SCharles.Forsyth #define FT_TYPE_HASH(x) (( (FT_UInt32)(x) >> 2 )^( (FT_UInt32)(x) >> 10 )) 10*37da2899SCharles.Forsyth 11*37da2899SCharles.Forsyth #define FT_OBJECT_CHECK(o) \ 12*37da2899SCharles.Forsyth ( FT_OBJECT(o) != NULL && \ 13*37da2899SCharles.Forsyth FT_OBJECT(o)->clazz != NULL && \ 14*37da2899SCharles.Forsyth FT_OBJECT(o)->ref_count >= 1 && \ 15*37da2899SCharles.Forsyth FT_OBJECT(o)->clazz->magic == FT_MAGIC_CLASS ) 16*37da2899SCharles.Forsyth 17*37da2899SCharles.Forsyth #define FT_CLASS_CHECK(c) \ 18*37da2899SCharles.Forsyth ( FT_CLASS(c) != NULL && FT_CLASS(c)->magic == FT_MAGIC_CLASS ) 19*37da2899SCharles.Forsyth 20*37da2899SCharles.Forsyth #define FT_ASSERT_IS_CLASS(c) FT_ASSERT( FT_CLASS_CHECK(c) ) 21*37da2899SCharles.Forsyth 22*37da2899SCharles.Forsyth /*******************************************************************/ 23*37da2899SCharles.Forsyth /*******************************************************************/ 24*37da2899SCharles.Forsyth /***** *****/ 25*37da2899SCharles.Forsyth /***** *****/ 26*37da2899SCharles.Forsyth /***** M E T A - C L A S S *****/ 27*37da2899SCharles.Forsyth /***** *****/ 28*37da2899SCharles.Forsyth /***** *****/ 29*37da2899SCharles.Forsyth /*******************************************************************/ 30*37da2899SCharles.Forsyth /*******************************************************************/ 31*37da2899SCharles.Forsyth 32*37da2899SCharles.Forsyth /* forward declaration */ 33*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) 34*37da2899SCharles.Forsyth ft_metaclass_init( FT_MetaClass meta, 35*37da2899SCharles.Forsyth FT_Library library ); 36*37da2899SCharles.Forsyth 37*37da2899SCharles.Forsyth /* forward declaration */ 38*37da2899SCharles.Forsyth FT_BASE_DEF( void ) 39*37da2899SCharles.Forsyth ft_metaclass_done( FT_MetaClass meta ); 40*37da2899SCharles.Forsyth 41*37da2899SCharles.Forsyth 42*37da2899SCharles.Forsyth /* class type for the meta-class itself */ 43*37da2899SCharles.Forsyth static const FT_TypeRec ft_meta_class_type = 44*37da2899SCharles.Forsyth { 45*37da2899SCharles.Forsyth "FT2.MetaClass", 46*37da2899SCharles.Forsyth NULL, 47*37da2899SCharles.Forsyth 48*37da2899SCharles.Forsyth sizeof( FT_MetaClassRec ), 49*37da2899SCharles.Forsyth (FT_Object_InitFunc) ft_metaclass_init, 50*37da2899SCharles.Forsyth (FT_Object_DoneFunc) ft_metaclass_done, 51*37da2899SCharles.Forsyth 52*37da2899SCharles.Forsyth sizeof( FT_ClassRec ), 53*37da2899SCharles.Forsyth (FT_Object_InitFunc) NULL, 54*37da2899SCharles.Forsyth (FT_Object_DoneFunc) NULL 55*37da2899SCharles.Forsyth }; 56*37da2899SCharles.Forsyth 57*37da2899SCharles.Forsyth 58*37da2899SCharles.Forsyth 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth /* destroy a given class */ 61*37da2899SCharles.Forsyth static void ft_class_hnode_destroy(FT_ClassHNode node)62*37da2899SCharles.Forsyth ft_class_hnode_destroy( FT_ClassHNode node ) 63*37da2899SCharles.Forsyth { 64*37da2899SCharles.Forsyth FT_Class clazz = node->clazz; 65*37da2899SCharles.Forsyth FT_Memory memory = clazz->memory; 66*37da2899SCharles.Forsyth 67*37da2899SCharles.Forsyth if ( clazz->class_done ) 68*37da2899SCharles.Forsyth clazz->class_done( (FT_Object) clazz ); 69*37da2899SCharles.Forsyth 70*37da2899SCharles.Forsyth FT_FREE( clazz ); 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth node->clazz = NULL; 73*37da2899SCharles.Forsyth node->type = NULL; 74*37da2899SCharles.Forsyth 75*37da2899SCharles.Forsyth FT_FREE( node ); 76*37da2899SCharles.Forsyth } 77*37da2899SCharles.Forsyth 78*37da2899SCharles.Forsyth 79*37da2899SCharles.Forsyth static FT_Int ft_type_equal(FT_Type type1,FT_Type type2)80*37da2899SCharles.Forsyth ft_type_equal( FT_Type type1, 81*37da2899SCharles.Forsyth FT_Type type2 ) 82*37da2899SCharles.Forsyth { 83*37da2899SCharles.Forsyth if ( type1 == type2 ) 84*37da2899SCharles.Forsyth goto Ok; 85*37da2899SCharles.Forsyth 86*37da2899SCharles.Forsyth if ( type1 == NULL || type2 == NULL ) 87*37da2899SCharles.Forsyth goto Fail; 88*37da2899SCharles.Forsyth 89*37da2899SCharles.Forsyth /* compare parent types */ 90*37da2899SCharles.Forsyth if ( type1->super != type2->super ) 91*37da2899SCharles.Forsyth { 92*37da2899SCharles.Forsyth if ( type1->super == NULL || 93*37da2899SCharles.Forsyth type2->super == NULL || 94*37da2899SCharles.Forsyth !ft_type_equal( type1, type2 ) ) 95*37da2899SCharles.Forsyth goto Fail; 96*37da2899SCharles.Forsyth } 97*37da2899SCharles.Forsyth 98*37da2899SCharles.Forsyth /* compare type names */ 99*37da2899SCharles.Forsyth if ( type1->name != type2->name ) 100*37da2899SCharles.Forsyth { 101*37da2899SCharles.Forsyth if ( type1->name == NULL || 102*37da2899SCharles.Forsyth type2->name == NULL || 103*37da2899SCharles.Forsyth ft_strcmp( type1->name, type2->name ) != 0 ) 104*37da2899SCharles.Forsyth goto Fail; 105*37da2899SCharles.Forsyth } 106*37da2899SCharles.Forsyth 107*37da2899SCharles.Forsyth /* compare the other type fields */ 108*37da2899SCharles.Forsyth if ( type1->class_size != type2->class_size || 109*37da2899SCharles.Forsyth type1->class_init != type2->class_init || 110*37da2899SCharles.Forsyth type1->class_done != type2->class_done || 111*37da2899SCharles.Forsyth type1->obj_size != type2->obj_size || 112*37da2899SCharles.Forsyth type1->obj_init != type2->obj_init || 113*37da2899SCharles.Forsyth type1->obj_done != type2->obj_done ) 114*37da2899SCharles.Forsyth goto Fail; 115*37da2899SCharles.Forsyth 116*37da2899SCharles.Forsyth Ok: 117*37da2899SCharles.Forsyth return 1; 118*37da2899SCharles.Forsyth 119*37da2899SCharles.Forsyth Fail: 120*37da2899SCharles.Forsyth return 0; 121*37da2899SCharles.Forsyth } 122*37da2899SCharles.Forsyth 123*37da2899SCharles.Forsyth 124*37da2899SCharles.Forsyth static FT_Int ft_class_hnode_equal(const FT_ClassHNode node1,const FT_ClassHNode node2)125*37da2899SCharles.Forsyth ft_class_hnode_equal( const FT_ClassHNode node1, 126*37da2899SCharles.Forsyth const FT_ClassHNode node2 ) 127*37da2899SCharles.Forsyth { 128*37da2899SCharles.Forsyth FT_Type type1 = node1->type; 129*37da2899SCharles.Forsyth FT_Type type2 = node2->type; 130*37da2899SCharles.Forsyth 131*37da2899SCharles.Forsyth /* comparing the pointers should work in 99% of cases */ 132*37da2899SCharles.Forsyth return ( type1 == type2 ) ? 1 : ft_type_equal( type1, type2 ); 133*37da2899SCharles.Forsyth } 134*37da2899SCharles.Forsyth 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth FT_BASE_DEF( void ) ft_metaclass_done(FT_MetaClass meta)137*37da2899SCharles.Forsyth ft_metaclass_done( FT_MetaClass meta ) 138*37da2899SCharles.Forsyth { 139*37da2899SCharles.Forsyth /* clear all classes */ 140*37da2899SCharles.Forsyth ft_hash_done( &meta->type_to_class, 141*37da2899SCharles.Forsyth (FT_Hash_ForeachFunc) ft_class_hnode_destroy, 142*37da2899SCharles.Forsyth NULL ); 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsyth meta->clazz.object.clazz = NULL; 145*37da2899SCharles.Forsyth meta->clazz.object.ref_count = 0; 146*37da2899SCharles.Forsyth meta->clazz.magic = FT_MAGIC_DEATH; 147*37da2899SCharles.Forsyth } 148*37da2899SCharles.Forsyth 149*37da2899SCharles.Forsyth 150*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) ft_metaclass_init(FT_MetaClass meta,FT_Library library)151*37da2899SCharles.Forsyth ft_metaclass_init( FT_MetaClass meta, 152*37da2899SCharles.Forsyth FT_Library library ) 153*37da2899SCharles.Forsyth { 154*37da2899SCharles.Forsyth FT_ClassRec* clazz = (FT_ClassRec*) &meta->clazz; 155*37da2899SCharles.Forsyth 156*37da2899SCharles.Forsyth /* the meta-class is its OWN class !! */ 157*37da2899SCharles.Forsyth clazz->object.clazz = (FT_Class) clazz; 158*37da2899SCharles.Forsyth clazz->object.ref_count = 1; 159*37da2899SCharles.Forsyth clazz->magic = FT_MAGIC_CLASS; 160*37da2899SCharles.Forsyth clazz->library = library; 161*37da2899SCharles.Forsyth clazz->memory = library->memory; 162*37da2899SCharles.Forsyth clazz->type = &ft_meta_class_type; 163*37da2899SCharles.Forsyth clazz->info = NULL; 164*37da2899SCharles.Forsyth 165*37da2899SCharles.Forsyth clazz->class_done = (FT_Object_DoneFunc) ft_metaclass_done; 166*37da2899SCharles.Forsyth 167*37da2899SCharles.Forsyth clazz->obj_size = sizeof( FT_ClassRec ); 168*37da2899SCharles.Forsyth clazz->obj_init = NULL; 169*37da2899SCharles.Forsyth clazz->obj_done = NULL; 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth return ft_hash_init( &meta->type_to_class, 172*37da2899SCharles.Forsyth (FT_Hash_EqualFunc) ft_class_hnode_equal, 173*37da2899SCharles.Forsyth library->memory ); 174*37da2899SCharles.Forsyth } 175*37da2899SCharles.Forsyth 176*37da2899SCharles.Forsyth 177*37da2899SCharles.Forsyth /* find or create the class corresponding to a given type */ 178*37da2899SCharles.Forsyth /* note that this function will retunr NULL in case of */ 179*37da2899SCharles.Forsyth /* memory overflow */ 180*37da2899SCharles.Forsyth /* */ 181*37da2899SCharles.Forsyth static FT_Class ft_metaclass_get_class(FT_MetaClass meta,FT_Type ctype)182*37da2899SCharles.Forsyth ft_metaclass_get_class( FT_MetaClass meta, 183*37da2899SCharles.Forsyth FT_Type ctype ) 184*37da2899SCharles.Forsyth { 185*37da2899SCharles.Forsyth FT_ClassHNodeRec keynode, *node, **pnode; 186*37da2899SCharles.Forsyth FT_Memory memory; 187*37da2899SCharles.Forsyth FT_ClassRec* clazz; 188*37da2899SCharles.Forsyth FT_Class parent; 189*37da2899SCharles.Forsyth FT_Error error; 190*37da2899SCharles.Forsyth 191*37da2899SCharles.Forsyth keynode.hnode.hash = FT_TYPE_HASH( ctype ); 192*37da2899SCharles.Forsyth keynode.type = ctype; 193*37da2899SCharles.Forsyth 194*37da2899SCharles.Forsyth pnode = (FT_ClassHNode*) ft_hash_lookup( &meta->type_to_class, 195*37da2899SCharles.Forsyth (FT_HashNode) &keynode ); 196*37da2899SCharles.Forsyth node = *pnode; 197*37da2899SCharles.Forsyth if ( node != NULL ) 198*37da2899SCharles.Forsyth { 199*37da2899SCharles.Forsyth clazz = (FT_ClassRec*) node->clazz; 200*37da2899SCharles.Forsyth goto Exit; 201*37da2899SCharles.Forsyth } 202*37da2899SCharles.Forsyth 203*37da2899SCharles.Forsyth memory = FT_CLASS__MEMORY(meta); 204*37da2899SCharles.Forsyth clazz = NULL; 205*37da2899SCharles.Forsyth parent = NULL; 206*37da2899SCharles.Forsyth if ( ctype->super != NULL ) 207*37da2899SCharles.Forsyth { 208*37da2899SCharles.Forsyth FT_ASSERT( ctype->super->class_size <= ctype->class_size ); 209*37da2899SCharles.Forsyth FT_ASSERT( ctype->super->obj_size <= ctype->obj_size ); 210*37da2899SCharles.Forsyth 211*37da2899SCharles.Forsyth parent = ft_metaclass_get_class( meta, ctype->super ); 212*37da2899SCharles.Forsyth } 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth if ( !FT_NEW( node ) ) 215*37da2899SCharles.Forsyth { 216*37da2899SCharles.Forsyth if ( !FT_ALLOC( clazz, ctype->class_size ) ) 217*37da2899SCharles.Forsyth { 218*37da2899SCharles.Forsyth if ( parent ) 219*37da2899SCharles.Forsyth FT_MEM_COPY( (FT_ClassRec*)clazz, parent, parent->type->class_size ); 220*37da2899SCharles.Forsyth 221*37da2899SCharles.Forsyth clazz->object.clazz = (FT_Class) meta; 222*37da2899SCharles.Forsyth clazz->object.ref_count = 1; 223*37da2899SCharles.Forsyth 224*37da2899SCharles.Forsyth clazz->memory = memory; 225*37da2899SCharles.Forsyth clazz->library = FT_CLASS__LIBRARY(meta); 226*37da2899SCharles.Forsyth clazz->super = parent; 227*37da2899SCharles.Forsyth clazz->type = ctype; 228*37da2899SCharles.Forsyth clazz->info = NULL; 229*37da2899SCharles.Forsyth clazz->magic = FT_MAGIC_CLASS; 230*37da2899SCharles.Forsyth 231*37da2899SCharles.Forsyth clazz->class_done = ctype->class_done; 232*37da2899SCharles.Forsyth clazz->obj_size = ctype->obj_size; 233*37da2899SCharles.Forsyth clazz->obj_init = ctype->obj_init; 234*37da2899SCharles.Forsyth clazz->obj_done = ctype->obj_done; 235*37da2899SCharles.Forsyth 236*37da2899SCharles.Forsyth if ( parent ) 237*37da2899SCharles.Forsyth { 238*37da2899SCharles.Forsyth if ( clazz->class_done == NULL ) 239*37da2899SCharles.Forsyth clazz->class_done = parent->class_done; 240*37da2899SCharles.Forsyth 241*37da2899SCharles.Forsyth if ( clazz->obj_init == NULL ) 242*37da2899SCharles.Forsyth clazz->obj_init = parent->obj_init; 243*37da2899SCharles.Forsyth 244*37da2899SCharles.Forsyth if ( clazz->obj_done == NULL ) 245*37da2899SCharles.Forsyth clazz->obj_done = parent->obj_done; 246*37da2899SCharles.Forsyth } 247*37da2899SCharles.Forsyth 248*37da2899SCharles.Forsyth /* find class initializer, if any */ 249*37da2899SCharles.Forsyth { 250*37da2899SCharles.Forsyth FT_Type ztype = ctype; 251*37da2899SCharles.Forsyth FT_Object_InitFunc cinit = NULL; 252*37da2899SCharles.Forsyth 253*37da2899SCharles.Forsyth do 254*37da2899SCharles.Forsyth { 255*37da2899SCharles.Forsyth cinit = ztype->class_init; 256*37da2899SCharles.Forsyth if ( cinit != NULL ) 257*37da2899SCharles.Forsyth break; 258*37da2899SCharles.Forsyth 259*37da2899SCharles.Forsyth ztype = ztype->super; 260*37da2899SCharles.Forsyth } 261*37da2899SCharles.Forsyth while ( ztype != NULL ); 262*37da2899SCharles.Forsyth 263*37da2899SCharles.Forsyth /* then call it when needed */ 264*37da2899SCharles.Forsyth if ( cinit != NULL ) 265*37da2899SCharles.Forsyth error = cinit( (FT_Object) clazz, NULL ); 266*37da2899SCharles.Forsyth } 267*37da2899SCharles.Forsyth } 268*37da2899SCharles.Forsyth 269*37da2899SCharles.Forsyth if (error) 270*37da2899SCharles.Forsyth { 271*37da2899SCharles.Forsyth if ( clazz ) 272*37da2899SCharles.Forsyth { 273*37da2899SCharles.Forsyth /* we always call the class destructor when */ 274*37da2899SCharles.Forsyth /* an error was detected in the constructor !! */ 275*37da2899SCharles.Forsyth if ( clazz->class_done ) 276*37da2899SCharles.Forsyth clazz->class_done( (FT_Object) clazz ); 277*37da2899SCharles.Forsyth 278*37da2899SCharles.Forsyth FT_FREE( clazz ); 279*37da2899SCharles.Forsyth } 280*37da2899SCharles.Forsyth FT_FREE( node ); 281*37da2899SCharles.Forsyth } 282*37da2899SCharles.Forsyth } 283*37da2899SCharles.Forsyth 284*37da2899SCharles.Forsyth Exit: 285*37da2899SCharles.Forsyth return (FT_Class) clazz; 286*37da2899SCharles.Forsyth } 287*37da2899SCharles.Forsyth 288*37da2899SCharles.Forsyth 289*37da2899SCharles.Forsyth 290*37da2899SCharles.Forsyth 291*37da2899SCharles.Forsyth 292*37da2899SCharles.Forsyth 293*37da2899SCharles.Forsyth 294*37da2899SCharles.Forsyth 295*37da2899SCharles.Forsyth 296*37da2899SCharles.Forsyth 297*37da2899SCharles.Forsyth 298*37da2899SCharles.Forsyth 299*37da2899SCharles.Forsyth 300*37da2899SCharles.Forsyth 301*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Int ) ft_object_check(FT_Pointer obj)302*37da2899SCharles.Forsyth ft_object_check( FT_Pointer obj ) 303*37da2899SCharles.Forsyth { 304*37da2899SCharles.Forsyth return FT_OBJECT_CHECK(obj); 305*37da2899SCharles.Forsyth } 306*37da2899SCharles.Forsyth 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Int ) ft_object_is_a(FT_Pointer obj,FT_Class clazz)309*37da2899SCharles.Forsyth ft_object_is_a( FT_Pointer obj, 310*37da2899SCharles.Forsyth FT_Class clazz ) 311*37da2899SCharles.Forsyth { 312*37da2899SCharles.Forsyth if ( FT_OBJECT_CHECK(obj) ) 313*37da2899SCharles.Forsyth { 314*37da2899SCharles.Forsyth FT_Class c = FT_OBJECT__CLASS(obj); 315*37da2899SCharles.Forsyth 316*37da2899SCharles.Forsyth do 317*37da2899SCharles.Forsyth { 318*37da2899SCharles.Forsyth if ( c == clazz ) 319*37da2899SCharles.Forsyth return 1; 320*37da2899SCharles.Forsyth 321*37da2899SCharles.Forsyth c = c->super; 322*37da2899SCharles.Forsyth } 323*37da2899SCharles.Forsyth while ( c == NULL ); 324*37da2899SCharles.Forsyth 325*37da2899SCharles.Forsyth return (clazz == NULL); 326*37da2899SCharles.Forsyth } 327*37da2899SCharles.Forsyth return 0; 328*37da2899SCharles.Forsyth } 329*37da2899SCharles.Forsyth 330*37da2899SCharles.Forsyth 331*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) ft_object_create(FT_Object * pobject,FT_Class clazz,FT_Pointer init_data)332*37da2899SCharles.Forsyth ft_object_create( FT_Object *pobject, 333*37da2899SCharles.Forsyth FT_Class clazz, 334*37da2899SCharles.Forsyth FT_Pointer init_data ) 335*37da2899SCharles.Forsyth { 336*37da2899SCharles.Forsyth FT_Memory memory; 337*37da2899SCharles.Forsyth FT_Error error; 338*37da2899SCharles.Forsyth FT_Object obj; 339*37da2899SCharles.Forsyth 340*37da2899SCharles.Forsyth FT_ASSERT_IS_CLASS(clazz); 341*37da2899SCharles.Forsyth 342*37da2899SCharles.Forsyth memory = FT_CLASS__MEMORY(clazz); 343*37da2899SCharles.Forsyth if ( !FT_ALLOC( obj, clazz->obj_size ) ) 344*37da2899SCharles.Forsyth { 345*37da2899SCharles.Forsyth obj->clazz = clazz; 346*37da2899SCharles.Forsyth obj->ref_count = 1; 347*37da2899SCharles.Forsyth 348*37da2899SCharles.Forsyth if ( clazz->obj_init ) 349*37da2899SCharles.Forsyth { 350*37da2899SCharles.Forsyth error = clazz->obj_init( obj, init_data ); 351*37da2899SCharles.Forsyth if ( error ) 352*37da2899SCharles.Forsyth { 353*37da2899SCharles.Forsyth /* IMPORTANT: call the destructor when an error */ 354*37da2899SCharles.Forsyth /* was detected in the constructor !! */ 355*37da2899SCharles.Forsyth if ( clazz->obj_done ) 356*37da2899SCharles.Forsyth clazz->obj_done( obj ); 357*37da2899SCharles.Forsyth 358*37da2899SCharles.Forsyth FT_FREE( obj ); 359*37da2899SCharles.Forsyth } 360*37da2899SCharles.Forsyth } 361*37da2899SCharles.Forsyth } 362*37da2899SCharles.Forsyth *pobject = obj; 363*37da2899SCharles.Forsyth return error; 364*37da2899SCharles.Forsyth } 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth 367*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Class ) ft_class_find_by_type(FT_Type type,FT_Library library)368*37da2899SCharles.Forsyth ft_class_find_by_type( FT_Type type, 369*37da2899SCharles.Forsyth FT_Library library ) 370*37da2899SCharles.Forsyth { 371*37da2899SCharles.Forsyth FT_MetaClass meta = &library->meta_class; 372*37da2899SCharles.Forsyth 373*37da2899SCharles.Forsyth return ft_metaclass_get_class( meta, type ); 374*37da2899SCharles.Forsyth } 375*37da2899SCharles.Forsyth 376*37da2899SCharles.Forsyth 377*37da2899SCharles.Forsyth FT_BASE_DEF( FT_Error ) ft_object_create_from_type(FT_Object * pobject,FT_Type type,FT_Pointer init_data,FT_Library library)378*37da2899SCharles.Forsyth ft_object_create_from_type( FT_Object *pobject, 379*37da2899SCharles.Forsyth FT_Type type, 380*37da2899SCharles.Forsyth FT_Pointer init_data, 381*37da2899SCharles.Forsyth FT_Library library ) 382*37da2899SCharles.Forsyth { 383*37da2899SCharles.Forsyth FT_Class clazz; 384*37da2899SCharles.Forsyth FT_Error error; 385*37da2899SCharles.Forsyth 386*37da2899SCharles.Forsyth clazz = ft_class_find_by_type( type, library ); 387*37da2899SCharles.Forsyth if ( clazz ) 388*37da2899SCharles.Forsyth error = ft_object_create( pobject, clazz, init_data ); 389*37da2899SCharles.Forsyth else 390*37da2899SCharles.Forsyth { 391*37da2899SCharles.Forsyth *pobject = NULL; 392*37da2899SCharles.Forsyth error = FT_Err_Out_Of_Memory; 393*37da2899SCharles.Forsyth } 394*37da2899SCharles.Forsyth 395*37da2899SCharles.Forsyth return error; 396*37da2899SCharles.Forsyth } 397