1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * type.cpp: Our type system
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
20 #include "deployment.h"
21 #include "dependencyproperty.h"
26 Type::Type (Deployment
*deployment
, Type::Kind type
, Type::Kind parent
, bool is_value_type
, bool is_interface
,
28 int event_count
, int total_event_count
, const char **events
,
29 int interface_count
, const Type::Kind
*interfaces
, bool ctor_visible
,
30 create_inst_func
*create_inst
, const char *content_property
)
33 this->parent
= parent
;
34 this->is_value_type
= is_value_type
;
35 this->is_interface
= is_interface
;
37 this->event_count
= event_count
;
38 this->total_event_count
= total_event_count
;
39 this->events
= events
;
40 this->ctor_visible
= ctor_visible
;
41 this->create_inst
= create_inst
;
42 this->content_property
= content_property
;
43 this->properties
= NULL
;
44 this->interface_count
= interface_count
;
45 if (this->interface_count
) {
46 this->interfaces
= new Type::Kind
[interface_count
];
47 memcpy (this->interfaces
, interfaces
, interface_count
* sizeof (Type::Kind
));
50 this->interfaces
= NULL
;
52 this->deployment
= deployment
;
58 g_hash_table_destroy (properties
);
66 Type::LookupEvent (const char *event_name
)
68 Type
*parent_type
= Type::Find (deployment
, parent
);
72 for (int i
= 0; events
[i
] != NULL
; i
++) {
73 if (!g_ascii_strcasecmp (events
[i
], event_name
))
74 return i
+ (parent_type
== NULL
? 0 : parent_type
->total_event_count
);
78 if (parent
== Type::INVALID
|| parent_type
== NULL
) {
80 printf ("Event lookup of event '%s' in type '%s' failed.\n", event_name
, name
);
85 result
= parent_type
->LookupEvent (event_name
);
89 printf ("Event lookup of event '%s' in (more exactly) type '%s' failed.\n", event_name
, name
);
96 Type::IsSubclassOf (Deployment
*deployment
, Type::Kind type
, Type::Kind super
)
98 return deployment
->GetTypes ()->IsSubclassOf (type
, super
);
102 Type::IsSubclassOf (Type::Kind super
)
104 return deployment
->GetTypes ()->IsSubclassOf (type
, super
);
109 Types::IsSubclassOrSuperclassOf (Type::Kind unknown
, Type::Kind known
)
111 return IsSubclassOf(unknown
, known
) || IsSubclassOf (known
, unknown
);
115 Types::IsSubclassOrSuperclassOf (Types
*arg
, Type::Kind unknown
, Type::Kind known
)
117 Types
*types
= arg
== NULL
? Deployment::GetCurrent ()->GetTypes () : arg
;
118 return types
->IsSubclassOf(unknown
, known
) || types
->IsSubclassOf (known
, unknown
);
123 Types::IsSubclassOf (Type::Kind type
, Type::Kind super
)
128 if (type
== Type::INVALID
)
136 g_return_val_if_fail (t
!= NULL
, false);
144 if (parent
== Type::INVALID
)
157 Type::IsAssignableFrom (Type::Kind type
)
159 return deployment
->GetTypes ()->IsAssignableFrom (GetKind (), type
);
162 Type::IsAssignableFrom (Deployment
*deployment
, Type::Kind destination
, Type::Kind type
)
164 return deployment
->GetTypes ()->IsAssignableFrom (destination
, type
);
168 Types::IsAssignableFrom (Type::Kind destination
, Type::Kind type
)
170 if (destination
== type
)
173 if (IsSubclassOf (type
, destination
))
176 // more expensive.. interface checks
177 Type
*destination_type
= Find (destination
);
178 if (!destination_type
->IsInterface())
181 Type
*type_type
= Find (type
);
182 while (type_type
&& type_type
->GetKind() != Type::INVALID
) {
183 for (int i
= 0; i
< type_type
->GetInterfaceCount(); i
++) {
184 // should this be IsAssignableFrom instead of ==? ugh
185 if (type_type
->GetInterface(i
) == destination
)
188 type_type
= Find (type_type
->parent
);
195 Type::Find (Deployment
*deployment
, const char *name
)
197 return deployment
->GetTypes ()->Find (name
);
201 Type::Find (Deployment
*deployment
, const char *name
, bool ignore_case
)
203 return deployment
->GetTypes ()->Find (name
, ignore_case
);
207 Type::Find (Deployment
*deployment
, Type::Kind type
)
209 if (type
< Type::INVALID
|| type
== Type::LASTTYPE
)
212 return deployment
->GetTypes ()->Find (type
);
216 Type::CreateInstance ()
219 g_warning ("Unable to create an instance of type: %s\n", name
);
223 return create_inst ();
227 Type::GetContentPropertyName ()
234 if (content_property
)
235 return content_property
;
237 parent_type
= Find (deployment
, parent
);
239 if (parent_type
== NULL
)
242 return parent_type
->GetContentPropertyName ();
246 Type::LookupProperty (const char *name
)
248 DependencyProperty
*property
= NULL
;
250 g_return_val_if_fail (name
!= NULL
, NULL
);
252 if (properties
!= NULL
) {
253 char *key
= g_ascii_strdown (name
, -1);
254 property
= (DependencyProperty
*) g_hash_table_lookup (properties
, key
);
265 Type::AddProperty (DependencyProperty
*property
)
267 DependencyProperty
*existing
= NULL
;
269 g_return_if_fail (property
!= NULL
);
271 if (properties
== NULL
) {
272 properties
= g_hash_table_new (g_str_hash
, g_str_equal
);
274 existing
= (DependencyProperty
*) g_hash_table_lookup (properties
, property
->GetHashKey ());
277 if (existing
== NULL
|| existing
->IsCustom ()) {
278 // Allow overwriting of custom properties
279 g_hash_table_insert (properties
, (gpointer
) property
->GetHashKey (), property
);
281 g_warning ("Type::AddProperty (): Trying to register the property '%s' (of type %s) in the owner type '%s', and there already is a property registered on that type with the same name.",
282 property
->GetName (), Type::Find (deployment
, property
->GetPropertyType ())->GetName(), GetName());
287 Type::GetParentType ()
289 if (parent
== Type::INVALID
)
292 return deployment
->GetTypes ()->Find (parent
);
296 property_add (gpointer key
, gpointer value
, gpointer user_data
)
298 g_hash_table_insert ((GHashTable
*) user_data
, key
, value
);
302 Type::CopyProperties (bool inherited
)
304 GHashTable
*props
= g_hash_table_new (g_str_hash
, g_str_equal
);
308 if (type
->properties
)
309 g_hash_table_foreach (type
->properties
, property_add
, props
);
311 if (!inherited
|| !type
->HasParent ())
314 type
= type
->GetParentType ();
321 type_get_value_type (Type::Kind type
)
323 Type
*t
= Type::Find (Deployment::GetCurrent (), type
);
328 return t
->IsValueType ();
332 type_is_dependency_object (Type::Kind type
)
334 return Type::IsSubclassOf (Deployment::GetCurrent (), type
, Type::DEPENDENCY_OBJECT
);
338 type_create_instance (Type
*type
)
341 g_warning ("Unable to create instance of type %p.", type
);
345 return type
->CreateInstance ();
349 type_create_instance_from_kind (Type::Kind kind
)
351 Type
*t
= Type::Find (Deployment::GetCurrent (), kind
);
354 g_warning ("Unable to create instance of type %d. Type not found.", kind
);
358 return t
->CreateInstance ();
367 //printf ("Types::Types (). this: %p\n", this);
368 types
.SetCount ((int) Type::LASTTYPE
+ 1);
369 RegisterNativeTypes ();
375 RegisterNativeProperties ();
379 Types::DeleteProperties ()
381 /* this can't be done in the destructor, since deleting the properties might end up accessing the types */
382 for (int i
= 0; i
< properties
.GetCount (); i
++)
383 delete (DependencyProperty
*) properties
[i
];
384 properties
.SetCount (0);
390 for (int i
= 0; i
< properties
.GetCount (); i
++)
391 ((DependencyProperty
*) properties
[i
])->Dispose ();
396 for (int i
= 0; i
< types
.GetCount (); i
++)
397 delete (Type
*) types
[i
];
401 Types::AddProperty (DependencyProperty
*property
)
405 g_return_if_fail (property
!= NULL
);
407 type
= Find (property
->GetOwnerType ());
409 g_return_if_fail (type
!= NULL
);
411 property
->SetId (properties
.Add (property
));
412 type
->AddProperty (property
);
416 Types::GetProperty (int id
)
418 g_return_val_if_fail (properties
.GetCount () > id
, NULL
);
419 return (DependencyProperty
*) properties
[id
];
423 Types::Find (const char *name
)
425 return Types::Find (name
, true);
429 Types::Find (const char *name
, bool ignore_case
)
433 for (int i
= 1; i
< types
.GetCount (); i
++) { // 0 = INVALID, shouldn't compare against that
434 if (i
== Type::LASTTYPE
)
437 t
= (Type
*) types
[i
];
438 if ((ignore_case
&& !g_ascii_strcasecmp (t
->GetName (), name
)) || !strcmp (t
->GetName (), name
))
446 Types::RegisterType (const char *name
, void *gc_handle
, Type::Kind parent
, bool is_interface
, bool ctor_visible
, Type::Kind
* interfaces
, int interface_count
)
448 Type
*type
= new Type (Deployment::GetCurrent (), Type::INVALID
, parent
, false, is_interface
, g_strdup (name
), 0, Find (parent
)->GetEventCount (), NULL
, interface_count
, interfaces
, ctor_visible
, NULL
, NULL
);
450 // printf ("Types::RegisterType (%s, %p, %i (%s)). this: %p, size: %i, count: %i\n", name, gc_handle, parent, Type::Find (this, parent) ? Type::Find (this, parent)->name : NULL, this, size, count);
452 type
->SetKind ((Type::Kind
) types
.Add (type
));
454 return type
->GetKind ();