Dynamic scope: child position is MAX_INT
[babeltrace.git] / types / types.c
CommitLineData
6dc2ca62 1/*
f6625916 2 * declarations.c
ccd7e1c8 3 *
d79865b9 4 * BabelTrace - Converter
6dc2ca62
MD
5 *
6 * Types registry.
7 *
c054553d 8 * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
de0ba614 9 *
ccd7e1c8
MD
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
de0ba614 16 *
ccd7e1c8
MD
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
6dc2ca62
MD
19 */
20
4c8bfb7e 21#include <babeltrace/format.h>
6a36ddca 22#include <limits.h>
6dc2ca62 23#include <glib.h>
d1708134
MD
24#include <errno.h>
25
c054553d 26static
e1151715 27struct definition *
f6625916
MD
28 lookup_typedef_declaration_scope(GQuark declaration_name,
29 struct declaration_scope *scope)
d1708134 30{
f6625916
MD
31 return g_hash_table_lookup(scope->typedef_declarations,
32 (gconstpointer) (unsigned long) declaration_name);
d1708134
MD
33}
34
f6625916
MD
35struct definition *lookup_typedef_declaration(GQuark declaration_name,
36 struct declaration_scope *scope)
c054553d 37{
e1151715 38 struct definition *definition;
c054553d
MD
39
40 while (scope) {
f6625916
MD
41 definition = lookup_typedef_declaration_scope(declaration_name,
42 scope);
e1151715
MD
43 if (definition)
44 return definition;
c054553d
MD
45 scope = scope->parent_scope;
46 }
47 return NULL;
48}
49
f6625916
MD
50int register_typedef_declaration(GQuark name, struct declaration *declaration,
51 struct declaration_scope *scope)
d1708134 52{
64893f33 53 if (!name)
6ee5115e
MD
54 return -EPERM;
55
c054553d 56 /* Only lookup in local scope */
f6625916 57 if (lookup_typedef_declaration_scope(name, scope))
d1708134
MD
58 return -EEXIST;
59
f6625916 60 g_hash_table_insert(scope->typedef_declarations,
64893f33 61 (gpointer) (unsigned long) name,
f6625916
MD
62 declaration);
63 declaration_ref(declaration);
ac88af75
MD
64 return 0;
65}
66
67static
e1151715 68struct definition *
f6625916
MD
69 lookup_field_definition_scope(GQuark field_name,
70 struct definition_scope *scope)
ac88af75 71{
e1151715 72 return g_hash_table_lookup(scope->definitions,
ac88af75
MD
73 (gconstpointer) (unsigned long) field_name);
74}
75
05c749e5
MD
76/*
77 * Returns the index at which the paths differ.
78 * If the value returned equals len, it means the paths are identical
79 * from index 0 to len-1.
80 */
81static int compare_paths(GArray *a, GArray *b, int len)
82{
83 int i;
84
85 assert(len <= a->len);
86 assert(len <= b->len);
87
88 for (i = 0; i < len; i++) {
89 GQuark qa, qb;
90
91 qa = g_array_index(a, GQuark, i);
92 qb = g_array_index(b, GQuark, i);
93 if (qa != qb)
94 return i;
95 }
96 return i;
97}
98
99static int is_path_child_of(GArray *path, GArray *maybe_parent)
100{
101 if (path->len <= maybe_parent->len)
102 return 0;
103 if (compare_paths(path, maybe_parent, maybe_parent->len)
104 == maybe_parent->len)
105 return 1;
106 else
107 return 0;
108}
109
110static struct definition_scope *
111 get_definition_scope(struct definition *definition)
112{
113 switch (definition->declaration->id) {
114 case CTF_TYPE_STRUCT:
115 {
116 struct definition_struct *def =
117 container_of(definition, struct definition_struct, p);
118 return def->scope;
119 }
120 case CTF_TYPE_VARIANT:
121 {
122 struct definition_variant *def =
123 container_of(definition, struct definition_variant, p);
124 return def->scope;
125 }
126 case CTF_TYPE_ARRAY:
127 {
128 struct definition_array *def =
129 container_of(definition, struct definition_array, p);
130 return def->scope;
131 }
132 case CTF_TYPE_SEQUENCE:
133 {
134 struct definition_sequence *def =
135 container_of(definition, struct definition_sequence, p);
136 return def->scope;
137 }
138
139 case CTF_TYPE_INTEGER:
140 case CTF_TYPE_FLOAT:
141 case CTF_TYPE_ENUM:
142 case CTF_TYPE_STRING:
143 case CTF_TYPE_UNKNOWN:
144 default:
145 return NULL;
146 }
147}
148
149/*
150 * OK, here is the fun. We want to lookup a field that is:
9e29e16e
MD
151 * - either in the same dynamic scope:
152 * - either in the current scope, but prior to the current field.
153 * - or in a parent scope (or parent of parent ...) still in a field
154 * prior to the current field position within the parents.
155 * - or in a different dynamic scope:
156 * - either in a upper dynamic scope (walk down a targeted scope from
157 * the dynamic scope root)
158 * - or in a lower dynamic scope (failure)
159 * The dynamic scope roots are linked together, so we can access the
160 * parent dynamic scope from the child dynamic scope by walking up to
161 * the parent.
05c749e5
MD
162 * If we cannot find such a field that is prior to our current path, we
163 * return NULL.
164 *
165 * cur_path: the path leading to the variant definition.
166 * lookup_path: the path leading to the enum we want to look for.
167 * scope: the definition scope containing the variant definition.
168 */
e1151715 169struct definition *
05c749e5
MD
170 lookup_definition(GArray *cur_path,
171 GArray *lookup_path,
172 struct definition_scope *scope)
ac88af75 173{
05c749e5
MD
174 struct definition *definition, *lookup_definition;
175 GQuark last;
176 int index;
ac88af75
MD
177
178 while (scope) {
05c749e5
MD
179 /* going up in the hierarchy. Check where we come from. */
180 assert(is_path_child_of(cur_path, scope->scope_path));
181 assert(cur_path->len - scope->scope_path->len == 1);
182 last = g_array_index(cur_path, GQuark, cur_path->len - 1);
183 definition = lookup_field_definition_scope(last, scope);
184 assert(definition);
185 index = definition->index;
186lookup:
187 if (is_path_child_of(lookup_path, scope->scope_path)) {
188 /* Means we can lookup the field in this scope */
189 last = g_array_index(lookup_path, GQuark,
190 scope->scope_path->len);
191 lookup_definition = lookup_field_definition_scope(last, scope);
192 if (!lookup_definition || ((index != -1) && lookup_definition->index >= index))
193 return NULL;
194 /* Found it! And it is prior to the current field. */
195 if (lookup_path->len - scope->scope_path->len == 1) {
196 /* Direct child */
197 return lookup_definition;
198 } else {
199 scope = get_definition_scope(lookup_definition);
200 /* Check if the definition has a sub-scope */
201 if (!scope)
202 return NULL;
203 /*
204 * Don't compare index anymore, because we are
205 * going within a scope that has been validated
206 * to be entirely prior to the current scope.
207 */
208 cur_path = NULL;
209 index = -1;
210 goto lookup;
211 }
212 } else {
213 assert(index != -1);
214 /* lookup_path is within an upper scope */
215 cur_path = scope->scope_path;
216 scope = scope->parent_scope;
217 }
ac88af75
MD
218 }
219 return NULL;
220}
221
e1151715 222int register_field_definition(GQuark field_name, struct definition *definition,
f6625916 223 struct definition_scope *scope)
ac88af75
MD
224{
225 if (!field_name)
226 return -EPERM;
227
228 /* Only lookup in local scope */
e1151715 229 if (lookup_field_definition_scope(field_name, scope))
ac88af75
MD
230 return -EEXIST;
231
e1151715 232 g_hash_table_insert(scope->definitions,
ac88af75 233 (gpointer) (unsigned long) field_name,
e1151715
MD
234 definition);
235 definition_ref(definition);
d1708134
MD
236 return 0;
237}
238
f6625916 239void declaration_ref(struct declaration *declaration)
4c8bfb7e 240{
f6625916 241 declaration->ref++;
4c8bfb7e
MD
242}
243
f6625916 244void declaration_unref(struct declaration *declaration)
4c8bfb7e 245{
f6625916
MD
246 if (!--declaration->ref)
247 declaration->declaration_free(declaration);
4c8bfb7e
MD
248}
249
e1151715 250void definition_ref(struct definition *definition)
d1708134 251{
e1151715 252 definition->ref++;
d1708134
MD
253}
254
e1151715 255void definition_unref(struct definition *definition)
d1708134 256{
e1151715 257 if (!--definition->ref)
f6625916 258 definition->declaration->definition_free(definition);
c054553d
MD
259}
260
f6625916
MD
261struct declaration_scope *
262 new_declaration_scope(struct declaration_scope *parent_scope)
c054553d 263{
f6625916 264 struct declaration_scope *scope = g_new(struct declaration_scope, 1);
c054553d 265
f6625916 266 scope->typedef_declarations = g_hash_table_new_full(g_direct_hash,
c13cbf74 267 g_direct_equal, NULL,
e1151715 268 (GDestroyNotify) definition_unref);
f6625916 269 scope->struct_declarations = g_hash_table_new_full(g_direct_hash,
c13cbf74 270 g_direct_equal, NULL,
f6625916
MD
271 (GDestroyNotify) declaration_unref);
272 scope->variant_declarations = g_hash_table_new_full(g_direct_hash,
c13cbf74 273 g_direct_equal, NULL,
f6625916
MD
274 (GDestroyNotify) declaration_unref);
275 scope->enum_declarations = g_hash_table_new_full(g_direct_hash,
c054553d 276 g_direct_equal, NULL,
f6625916 277 (GDestroyNotify) declaration_unref);
64893f33
MD
278 scope->parent_scope = parent_scope;
279 return scope;
280}
281
f6625916 282void free_declaration_scope(struct declaration_scope *scope)
64893f33 283{
f6625916
MD
284 g_hash_table_destroy(scope->enum_declarations);
285 g_hash_table_destroy(scope->variant_declarations);
286 g_hash_table_destroy(scope->struct_declarations);
287 g_hash_table_destroy(scope->typedef_declarations);
64893f33
MD
288 g_free(scope);
289}
290
c13cbf74 291static
f6625916
MD
292struct declaration_struct *lookup_struct_declaration_scope(GQuark struct_name,
293 struct declaration_scope *scope)
c13cbf74 294{
f6625916 295 return g_hash_table_lookup(scope->struct_declarations,
c13cbf74
MD
296 (gconstpointer) (unsigned long) struct_name);
297}
298
f6625916
MD
299struct declaration_struct *lookup_struct_declaration(GQuark struct_name,
300 struct declaration_scope *scope)
c13cbf74 301{
f6625916 302 struct declaration_struct *declaration;
c13cbf74
MD
303
304 while (scope) {
f6625916
MD
305 declaration = lookup_struct_declaration_scope(struct_name, scope);
306 if (declaration)
307 return declaration;
c13cbf74
MD
308 scope = scope->parent_scope;
309 }
310 return NULL;
311}
312
f6625916
MD
313int register_struct_declaration(GQuark struct_name,
314 struct declaration_struct *struct_declaration,
315 struct declaration_scope *scope)
c13cbf74
MD
316{
317 if (!struct_name)
318 return -EPERM;
319
320 /* Only lookup in local scope */
f6625916 321 if (lookup_struct_declaration_scope(struct_name, scope))
c13cbf74
MD
322 return -EEXIST;
323
f6625916 324 g_hash_table_insert(scope->struct_declarations,
c13cbf74 325 (gpointer) (unsigned long) struct_name,
f6625916
MD
326 struct_declaration);
327 declaration_ref(&struct_declaration->p);
c13cbf74
MD
328 return 0;
329}
330
331static
f6625916
MD
332struct declaration_variant *
333 lookup_variant_declaration_scope(GQuark variant_name,
334 struct declaration_scope *scope)
c13cbf74 335{
f6625916 336 return g_hash_table_lookup(scope->variant_declarations,
c13cbf74
MD
337 (gconstpointer) (unsigned long) variant_name);
338}
339
f6625916
MD
340struct declaration_variant *
341 lookup_variant_declaration(GQuark variant_name,
342 struct declaration_scope *scope)
c13cbf74 343{
f6625916 344 struct declaration_variant *declaration;
c13cbf74
MD
345
346 while (scope) {
f6625916
MD
347 declaration = lookup_variant_declaration_scope(variant_name, scope);
348 if (declaration)
349 return declaration;
c13cbf74
MD
350 scope = scope->parent_scope;
351 }
352 return NULL;
353}
354
f6625916
MD
355int register_variant_declaration(GQuark variant_name,
356 struct declaration_variant *variant_declaration,
357 struct declaration_scope *scope)
c13cbf74
MD
358{
359 if (!variant_name)
360 return -EPERM;
361
362 /* Only lookup in local scope */
f6625916 363 if (lookup_variant_declaration_scope(variant_name, scope))
c13cbf74
MD
364 return -EEXIST;
365
f6625916 366 g_hash_table_insert(scope->variant_declarations,
c13cbf74 367 (gpointer) (unsigned long) variant_name,
f6625916
MD
368 variant_declaration);
369 declaration_ref(&variant_declaration->p);
c13cbf74
MD
370 return 0;
371}
372
373static
f6625916
MD
374struct declaration_enum *
375 lookup_enum_declaration_scope(GQuark enum_name,
376 struct declaration_scope *scope)
c13cbf74 377{
f6625916 378 return g_hash_table_lookup(scope->enum_declarations,
c13cbf74
MD
379 (gconstpointer) (unsigned long) enum_name);
380}
381
f6625916
MD
382struct declaration_enum *
383 lookup_enum_declaration(GQuark enum_name,
384 struct declaration_scope *scope)
c13cbf74 385{
f6625916 386 struct declaration_enum *declaration;
c13cbf74
MD
387
388 while (scope) {
f6625916
MD
389 declaration = lookup_enum_declaration_scope(enum_name, scope);
390 if (declaration)
391 return declaration;
c13cbf74
MD
392 scope = scope->parent_scope;
393 }
394 return NULL;
395}
396
f6625916
MD
397int register_enum_declaration(GQuark enum_name,
398 struct declaration_enum *enum_declaration,
399 struct declaration_scope *scope)
c13cbf74
MD
400{
401 if (!enum_name)
402 return -EPERM;
403
404 /* Only lookup in local scope */
f6625916 405 if (lookup_enum_declaration_scope(enum_name, scope))
c13cbf74
MD
406 return -EEXIST;
407
f6625916 408 g_hash_table_insert(scope->enum_declarations,
c13cbf74 409 (gpointer) (unsigned long) enum_name,
f6625916
MD
410 enum_declaration);
411 declaration_ref(&enum_declaration->p);
c13cbf74
MD
412 return 0;
413}
414
9e29e16e
MD
415static struct definition_scope *
416 _new_definition_scope(struct definition_scope *parent_scope,
417 int scope_path_len)
64893f33 418{
e1151715 419 struct definition_scope *scope = g_new(struct definition_scope, 1);
64893f33 420
e1151715 421 scope->definitions = g_hash_table_new_full(g_direct_hash,
ac88af75 422 g_direct_equal, NULL,
e1151715 423 (GDestroyNotify) definition_unref);
c054553d 424 scope->parent_scope = parent_scope;
05c749e5
MD
425 scope->scope_path = g_array_sized_new(FALSE, TRUE, sizeof(GQuark),
426 scope_path_len);
427 g_array_set_size(scope->scope_path, scope_path_len);
9e29e16e
MD
428 return scope;
429}
430
431struct definition_scope *
432 new_definition_scope(struct definition_scope *parent_scope,
433 GQuark field_name)
434{
435 struct definition_scope *scope;
436 int scope_path_len = 1;
437
438 if (parent_scope)
439 scope_path_len += parent_scope->scope_path->len;
440 scope = _new_definition_scope(parent_scope, scope_path_len);
441 if (parent_scope)
442 memcpy(scope->scope_path, parent_scope->scope_path,
05c749e5
MD
443 sizeof(GQuark) * (scope_path_len - 1));
444 g_array_index(scope->scope_path, GQuark, scope_path_len - 1) =
445 field_name;
c054553d
MD
446 return scope;
447}
448
6a36ddca
MD
449void set_dynamic_definition_scope(struct definition *definition,
450 struct definition_scope *scope,
41253107 451 GQuark root_name)
9e29e16e 452{
41253107
MD
453 g_array_set_size(scope->scope_path, 1);
454 g_array_index(scope->scope_path, GQuark, 0) = root_name;
6a36ddca
MD
455 /*
456 * Use INT_MAX order to ensure that all fields of the parent
457 * scope are seen as being prior to this scope.
458 */
459 definition->index = INT_MAX;
9e29e16e
MD
460}
461
e1151715 462void free_definition_scope(struct definition_scope *scope)
c054553d 463{
05c749e5 464 g_array_free(scope->scope_path, TRUE);
e1151715 465 g_hash_table_destroy(scope->definitions);
c054553d 466 g_free(scope);
d1708134 467}
This page took 0.04347 seconds and 4 git commands to generate.