2009-10-09 Chris Toshok <toshok@ximian.com>
[moon.git] / src / namescope.cpp
blob4daaf479532a5564b53df6f8ea0e138a1fff581b
1 /*
2 * namescope.cpp
4 * Copyright 2007 Novell, Inc. (http://www.novell.com)
6 * See the LICENSE file included with the distribution for details.
7 *
8 */
10 #include <config.h>
11 #include <glib.h>
12 #include <stdio.h>
14 #include "namescope.h"
16 NameScope::NameScope ()
18 SetObjectType (Type::NAMESCOPE);
19 is_locked = false;
20 names = NULL;
21 temporary = false;
24 gboolean
25 NameScope::remove_handler (gpointer key, gpointer value, gpointer data)
27 DependencyObject *depobj = (DependencyObject*)value;
28 depobj->RemoveHandler (EventObject::DestroyedEvent, NameScope::ObjectDestroyedEvent, data);
29 return TRUE;
32 NameScope::~NameScope ()
34 if (names) {
35 g_hash_table_foreach_remove (names, remove_handler, this);
36 g_hash_table_destroy (names);
40 static void
41 register_name (char *key, DependencyObject *obj, NameScope* ns)
43 ns->RegisterName (key, obj);
46 void
47 NameScope::CloneCore (Types *types, DependencyObject *fromObj)
49 NameScope *ns = (NameScope*)fromObj;
51 g_hash_table_foreach (ns->names, (GHFunc)register_name, this);
53 is_locked = ns->is_locked;
54 temporary = ns->temporary;
57 void
58 NameScope::Dispose ()
60 if (names)
61 g_hash_table_foreach_remove (names, remove_handler, this);
63 DependencyObject::Dispose ();
66 static gboolean
67 remove_object_from_namescope (gpointer key, gpointer value, gpointer user_data)
69 return value == user_data;
72 void
73 NameScope::ObjectDestroyedEvent (EventObject *sender, EventArgs *args, gpointer closure)
75 NameScope *ns = (NameScope*)closure;
76 // XXX this method worries me.. using GetName like this.
77 DependencyObject *depobj = (DependencyObject*)sender;
78 const char *name = depobj->GetName ();
79 if (name != NULL) {
80 g_hash_table_remove (ns->names, name);
81 } else {
82 g_hash_table_foreach_remove (ns->names, remove_object_from_namescope, depobj);
86 void
87 NameScope::RegisterName (const char *name, DependencyObject *object)
89 if (GetIsLocked ())
90 return;
92 if (!names) {
93 names = g_hash_table_new_full (g_str_hash, g_str_equal,
94 (GDestroyNotify)g_free,
95 NULL);
98 DependencyObject *existing_object = (DependencyObject*)g_hash_table_lookup (names, name);
99 if (existing_object == object)
100 return;
102 if (existing_object) {
103 existing_object->RemoveHandler (EventObject::DestroyedEvent, ObjectDestroyedEvent, this);
106 object->AddHandler (EventObject::DestroyedEvent, NameScope::ObjectDestroyedEvent, this);
107 g_hash_table_insert (names, g_strdup (name), object);
110 void
111 NameScope::UnregisterName (const char *name)
113 if (GetIsLocked ())
114 return;
116 if (!names)
117 return;
119 DependencyObject *depobj = (DependencyObject*)g_hash_table_lookup (names, name);
120 if (depobj) {
121 depobj->RemoveHandler (EventObject::DestroyedEvent, ObjectDestroyedEvent, this);
123 g_hash_table_remove (names, name);
127 DependencyObject*
128 NameScope::FindName (const char *name)
130 if (!names)
131 return NULL;
133 if (name == NULL) {
134 g_warning ("NameScope::FindName (null)");
135 return NULL;
137 return (DependencyObject *) g_hash_table_lookup (names, name);
140 void
141 NameScope::merge_name (gpointer key, gpointer value, gpointer user_data)
143 char *name = (char*)key;
144 DependencyObject *obj = (DependencyObject*)value;
145 NameScope *scope = (NameScope*)user_data;
147 scope->RegisterName (name, obj);
150 struct DuplicatesData {
151 NameScope *ns;
152 bool duplicate_found;
153 char *duplicate_name;
156 static void
157 look_for_duplicates (gpointer key, gpointer value, gpointer user_data)
159 DuplicatesData *data = (DuplicatesData*)user_data;
161 if (data->duplicate_found)
162 return;
164 char *name = (char*)key;
165 void *o = data->ns->FindName (name);
166 if (o && o != value) {
167 data->duplicate_found = true;
168 data->duplicate_name = g_strdup (name);
172 void
173 NameScope::MergeTemporaryScope (NameScope *temp, MoonError *error)
175 if (!temp || !temp->names)
176 return;
178 DuplicatesData data;
179 data.ns = this;
180 data.duplicate_found = false;
181 data.duplicate_name = NULL;
183 g_hash_table_foreach (temp->names, look_for_duplicates, &data);
184 if (data.duplicate_found) {
185 MoonError::FillIn (error, MoonError::ARGUMENT, 2028,
186 g_strdup_printf ("The name already exists in the tree: %s.",
187 data.duplicate_name));
188 g_free (data.duplicate_name);
189 return;
192 g_hash_table_foreach (temp->names, merge_name, this);
195 static void
196 dump_namescope_helper (gpointer key, gpointer value, gpointer user_data)
198 fprintf (stderr, " %s => %s\n", (char*)key, ((DependencyObject*)value)->GetTypeName());
202 void
203 NameScope::Dump ()
205 fprintf (stderr, " ns = %p\n", this);
206 g_hash_table_foreach (names, dump_namescope_helper, NULL);