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 (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
;
57 g_hash_table_destroy (properties
);
65 Type::LookupEventName (int id
)
67 Type
*parent_type
= Type::Find (parent
);
68 int parent_event_count
= (parent_type
== NULL
? 0 : parent_type
->total_event_count
);
76 for (int i
= 0; events
[i
] != NULL
; i
++) {
77 current_id
= i
+ parent_event_count
;
83 if (parent
== Type::INVALID
|| parent_type
== NULL
) {
84 printf ("Event lookup of event id %i in type '%s' failed.\n", id
, name
);
88 result
= parent_type
->LookupEventName (id
);
91 printf ("Event lookup of event %i in (more exactly) type '%s' failed.\n", id
, name
);
97 Type::LookupEvent (const char *event_name
)
99 Type
*parent_type
= Type::Find (parent
);
102 if (events
!= NULL
) {
103 for (int i
= 0; events
[i
] != NULL
; i
++) {
104 if (!g_ascii_strcasecmp (events
[i
], event_name
))
105 return i
+ (parent_type
== NULL
? 0 : parent_type
->total_event_count
);
109 if (parent
== Type::INVALID
|| parent_type
== NULL
) {
110 printf ("Event lookup of event '%s' in type '%s' failed.\n", event_name
, name
);
114 result
= parent_type
->LookupEvent (event_name
);
117 printf ("Event lookup of event '%s' in (more exactly) type '%s' failed.\n", event_name
, name
);
123 Type::IsSubclassOf (Deployment
*deployment
, Type::Kind type
, Type::Kind super
)
125 return deployment
->GetTypes ()->IsSubclassOf (type
, super
);
129 Type::IsSubclassOf (Type::Kind type
, Type::Kind super
)
131 return IsSubclassOf (Deployment::GetCurrent (), type
, super
);
135 Type::IsSubclassOf (Deployment
*deployment
, Type::Kind super
)
137 return deployment
->GetTypes ()->IsSubclassOf (type
, super
);
141 Type::IsSubclassOf (Type::Kind super
)
143 return IsSubclassOf (Deployment::GetCurrent (), type
, super
);
147 Types::IsSubclassOrSuperclassOf (Type::Kind unknown
, Type::Kind known
)
149 return IsSubclassOf(unknown
, known
) || IsSubclassOf (known
, unknown
);
153 Types::IsSubclassOrSuperclassOf (Types
*arg
, Type::Kind unknown
, Type::Kind known
)
155 Types
*types
= arg
== NULL
? Deployment::GetCurrent ()->GetTypes () : arg
;
156 return types
->IsSubclassOf(unknown
, known
) || types
->IsSubclassOf (known
, unknown
);
161 Types::IsSubclassOf (Type::Kind type
, Type::Kind super
)
166 if (type
== Type::INVALID
)
174 g_return_val_if_fail (t
!= NULL
, false);
177 parent
= t
->GetParent ();
182 if (parent
== Type::INVALID
)
195 Type::IsAssignableFrom (Type::Kind type
)
197 return Deployment::GetCurrent ()->GetTypes ()->IsAssignableFrom (GetKind (), type
);
201 Type::IsAssignableFrom (Type::Kind destination
, Type::Kind type
)
203 return Deployment::GetCurrent ()->GetTypes ()->IsAssignableFrom (destination
, type
);
207 Types::IsAssignableFrom (Type::Kind destination
, Type::Kind type
)
209 if (destination
== type
)
212 if (IsSubclassOf (type
, destination
))
215 // more expensive.. interface checks
216 Type
*destination_type
= Find (destination
);
217 if (!destination_type
->IsInterface())
220 Type
*type_type
= Find (type
);
221 while (type_type
&& type_type
->GetKind() != Type::INVALID
) {
222 for (int i
= 0; i
< type_type
->GetInterfaceCount(); i
++) {
223 // should this be IsAssignableFrom instead of ==? ugh
224 if (type_type
->GetInterface(i
) == destination
)
227 type_type
= Find (type_type
->GetParent());
234 Type::Find (Deployment
*deployment
, const char *name
)
236 return deployment
->GetTypes ()->Find (name
);
240 Type::Find (const char *name
)
242 return Find (Deployment::GetCurrent (), name
);
246 Type::Find (Deployment
*deployment
, const char *name
, bool ignore_case
)
248 return deployment
->GetTypes ()->Find (name
, ignore_case
);
252 Type::Find (const char *name
, bool ignore_case
)
254 return Find (Deployment::GetCurrent (), name
, ignore_case
);
258 Type::Find (Deployment
*deployment
, Type::Kind type
)
260 if (type
< Type::INVALID
|| type
== Type::LASTTYPE
)
263 return deployment
->GetTypes ()->Find (type
);
267 Type::Find (Type::Kind type
)
269 if (type
< Type::INVALID
|| type
== Type::LASTTYPE
)
272 return Find (Deployment::GetCurrent (), type
);
276 Type::CreateInstance ()
279 g_warning ("Unable to create an instance of type: %s\n", name
);
283 return create_inst ();
287 Type::GetContentPropertyName ()
294 if (content_property
)
295 return content_property
;
297 parent_type
= Find (parent
);
299 if (parent_type
== NULL
)
302 return parent_type
->GetContentPropertyName ();
306 Type::LookupProperty (const char *name
)
308 DependencyProperty
*property
= NULL
;
310 g_return_val_if_fail (name
!= NULL
, NULL
);
312 if (properties
!= NULL
) {
313 char *key
= g_ascii_strdown (name
, -1);
314 property
= (DependencyProperty
*) g_hash_table_lookup (properties
, key
);
325 Type::AddProperty (DependencyProperty
*property
)
327 DependencyProperty
*existing
= NULL
;
329 g_return_if_fail (property
!= NULL
);
331 if (properties
== NULL
) {
332 properties
= g_hash_table_new (g_str_hash
, g_str_equal
);
334 existing
= (DependencyProperty
*) g_hash_table_lookup (properties
, property
->GetHashKey ());
337 if (existing
== NULL
|| existing
->IsCustom ()) {
338 // Allow overwriting of custom properties
339 g_hash_table_insert (properties
, (gpointer
) property
->GetHashKey (), property
);
341 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.",
342 property
->GetName (), Type::Find (property
->GetPropertyType ())->GetName(), GetName());
347 property_add (gpointer key
, gpointer value
, gpointer user_data
)
349 g_hash_table_insert ((GHashTable
*) user_data
, key
, value
);
353 Type::CopyProperties (bool inherited
)
355 GHashTable
*props
= g_hash_table_new (g_str_hash
, g_str_equal
);
359 if (type
->properties
)
360 g_hash_table_foreach (type
->properties
, property_add
, props
);
362 if (!inherited
|| type
->GetParent () == Type::INVALID
)
365 type
= Type::Find (type
->GetParent ());
372 type_get_value_type (Type::Kind type
)
374 Type
*t
= Type::Find (type
);
379 return t
->IsValueType ();
383 type_get_name (Type::Kind type
)
385 Type
*t
= Type::Find (type
);
390 return t
->GetName ();
394 type_is_dependency_object (Type::Kind type
)
396 return Type::IsSubclassOf (type
, Type::DEPENDENCY_OBJECT
);
400 type_create_instance (Type
*type
)
403 g_warning ("Unable to create instance of type %p.", type
);
407 return type
->CreateInstance ();
411 type_create_instance_from_kind (Type::Kind kind
)
413 Type
*t
= Type::Find (kind
);
416 g_warning ("Unable to create instance of type %d. Type not found.", kind
);
420 return t
->CreateInstance ();
429 //printf ("Types::Types (). this: %p\n", this);
430 types
.SetCount ((int) Type::LASTTYPE
+ 1);
431 RegisterNativeTypes ();
437 RegisterNativeProperties ();
441 Types::DeleteProperties ()
443 /* this can't be done in the destructor, since deleting the properties might end up accessing the types */
444 for (int i
= 0; i
< properties
.GetCount (); i
++)
445 delete (DependencyProperty
*) properties
[i
];
446 properties
.SetCount (0);
452 for (int i
= 0; i
< properties
.GetCount (); i
++)
453 ((DependencyProperty
*) properties
[i
])->Dispose ();
458 for (int i
= 0; i
< types
.GetCount (); i
++)
459 delete (Type
*) types
[i
];
463 Types::AddProperty (DependencyProperty
*property
)
467 g_return_if_fail (property
!= NULL
);
469 type
= Find (property
->GetOwnerType ());
471 g_return_if_fail (type
!= NULL
);
473 property
->SetId (properties
.Add (property
));
474 type
->AddProperty (property
);
478 Types::GetProperty (int id
)
480 g_return_val_if_fail (properties
.GetCount () > id
, NULL
);
481 return (DependencyProperty
*) properties
[id
];
485 Types::Find (Type::Kind type
)
487 if ((int) type
+ 1 > types
.GetCount ())
490 return (Type
*) types
[(int) type
];
494 Types::Find (const char *name
)
496 return Types::Find (name
, true);
500 Types::Find (const char *name
, bool ignore_case
)
504 for (int i
= 1; i
< types
.GetCount (); i
++) { // 0 = INVALID, shouldn't compare against that
505 if (i
== Type::LASTTYPE
)
508 t
= (Type
*) types
[i
];
509 if ((ignore_case
&& !g_ascii_strcasecmp (t
->GetName (), name
)) || !strcmp (t
->GetName (), name
))
517 Types::RegisterType (const char *name
, void *gc_handle
, Type::Kind parent
, bool is_interface
, bool ctor_visible
, Type::Kind
* interfaces
, int interface_count
)
519 Type
*type
= new Type (Type::INVALID
, parent
, false, is_interface
, g_strdup (name
), 0, Find (parent
)->GetEventCount (), NULL
, interface_count
, interfaces
, ctor_visible
, NULL
, NULL
);
521 // 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);
523 type
->SetKind ((Type::Kind
) types
.Add (type
));
525 return type
->GetKind ();