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