Version 1.0.0-rc6
[babeltrace.git] / types / types.c
1 /*
2 * types.c
3 *
4 * BabelTrace - Converter
5 *
6 * Types registry.
7 *
8 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
9 *
10 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 */
22
23 #include <babeltrace/format.h>
24 #include <babeltrace/babeltrace-internal.h>
25 #include <babeltrace/types.h>
26 #include <limits.h>
27 #include <glib.h>
28 #include <errno.h>
29
30 static
31 GQuark prefix_quark(const char *prefix, GQuark quark)
32 {
33 GQuark nq;
34 GString *str;
35 char *quark_str;
36
37 str = g_string_new(prefix);
38 g_string_append(str, g_quark_to_string(quark));
39 quark_str = g_string_free(str, FALSE);
40 nq = g_quark_from_string(quark_str);
41 g_free(quark_str);
42 return nq;
43 }
44
45 static
46 struct declaration *
47 lookup_declaration_scope(GQuark declaration_name,
48 struct declaration_scope *scope)
49 {
50 return g_hash_table_lookup(scope->typedef_declarations,
51 (gconstpointer) (unsigned long) declaration_name);
52 }
53
54 struct declaration *lookup_declaration(GQuark declaration_name,
55 struct declaration_scope *scope)
56 {
57 struct declaration *declaration;
58
59 while (scope) {
60 declaration = lookup_declaration_scope(declaration_name,
61 scope);
62 if (declaration)
63 return declaration;
64 scope = scope->parent_scope;
65 }
66 return NULL;
67 }
68
69 int register_declaration(GQuark name, struct declaration *declaration,
70 struct declaration_scope *scope)
71 {
72 if (!name)
73 return -EPERM;
74
75 /* Only lookup in local scope */
76 if (lookup_declaration_scope(name, scope))
77 return -EEXIST;
78
79 g_hash_table_insert(scope->typedef_declarations,
80 (gpointer) (unsigned long) name,
81 declaration);
82 declaration_ref(declaration);
83 return 0;
84 }
85
86 static
87 struct definition *
88 lookup_field_definition_scope(GQuark field_name,
89 struct definition_scope *scope)
90 {
91 return g_hash_table_lookup(scope->definitions,
92 (gconstpointer) (unsigned long) field_name);
93 }
94
95 /*
96 * Returns the index at which the paths differ.
97 * If the value returned equals len, it means the paths are identical
98 * from index 0 to len-1.
99 */
100 static int compare_paths(GArray *a, GArray *b, int len)
101 {
102 int i;
103
104 assert(len <= a->len);
105 assert(len <= b->len);
106
107 for (i = 0; i < len; i++) {
108 GQuark qa, qb;
109
110 qa = g_array_index(a, GQuark, i);
111 qb = g_array_index(b, GQuark, i);
112 if (qa != qb)
113 return i;
114 }
115 return i;
116 }
117
118 static int is_path_child_of(GArray *path, GArray *maybe_parent)
119 {
120 int i, ret;
121
122 if (babeltrace_debug) {
123 int need_dot = 0;
124
125 printf_debug("Is path \"");
126 for (i = 0; i < path->len; need_dot = 1, i++)
127 printf("%s%s", need_dot ? "." : "",
128 g_quark_to_string(g_array_index(path, GQuark, i)));
129 need_dot = 0;
130 printf("\" child of \"");
131 for (i = 0; i < maybe_parent->len; need_dot = 1, i++)
132 printf("%s%s", need_dot ? "." : "",
133 g_quark_to_string(g_array_index(maybe_parent, GQuark, i)));
134 printf("\" ? ");
135 }
136
137 if (path->len <= maybe_parent->len) {
138 ret = 0;
139 goto end;
140 }
141 if (compare_paths(path, maybe_parent, maybe_parent->len)
142 == maybe_parent->len)
143 ret = 1;
144 else
145 ret = 0;
146 end:
147 if (babeltrace_debug)
148 printf("%s\n", ret ? "Yes" : "No");
149 return ret;
150 }
151
152 static struct definition_scope *
153 get_definition_scope(const struct definition *definition)
154 {
155 return definition->scope;
156 }
157
158 /*
159 * OK, here is the fun. We want to lookup a field that is:
160 * - either in the same dynamic scope:
161 * - either in the current scope, but prior to the current field.
162 * - or in a parent scope (or parent of parent ...) still in a field
163 * prior to the current field position within the parents.
164 * - or in a different dynamic scope:
165 * - either in a upper dynamic scope (walk down a targeted scope from
166 * the dynamic scope root)
167 * - or in a lower dynamic scope (failure)
168 * The dynamic scope roots are linked together, so we can access the
169 * parent dynamic scope from the child dynamic scope by walking up to
170 * the parent.
171 * If we cannot find such a field that is prior to our current path, we
172 * return NULL.
173 *
174 * cur_path: the path leading to the variant definition.
175 * lookup_path: the path leading to the enum we want to look for.
176 * scope: the definition scope containing the variant definition.
177 */
178 struct definition *
179 lookup_path_definition(GArray *cur_path,
180 GArray *lookup_path,
181 struct definition_scope *scope)
182 {
183 struct definition *definition, *lookup_definition;
184 GQuark last;
185 int index;
186
187 /* Going up in the hierarchy. Check where we come from. */
188 assert(is_path_child_of(cur_path, scope->scope_path));
189 assert(cur_path->len - scope->scope_path->len == 1);
190
191 /*
192 * First, check if the target name is size one, present in
193 * our parent path, located prior to us.
194 */
195 if (lookup_path->len == 1) {
196 last = g_array_index(lookup_path, GQuark, 0);
197 lookup_definition = lookup_field_definition_scope(last, scope);
198 last = g_array_index(cur_path, GQuark, cur_path->len - 1);
199 definition = lookup_field_definition_scope(last, scope);
200 assert(definition);
201 if (lookup_definition && lookup_definition->index < definition->index)
202 return lookup_definition;
203 else
204 return NULL;
205 }
206
207 while (scope) {
208 if (is_path_child_of(cur_path, scope->scope_path) &&
209 cur_path->len - scope->scope_path->len == 1) {
210 last = g_array_index(cur_path, GQuark, cur_path->len - 1);
211 definition = lookup_field_definition_scope(last, scope);
212 assert(definition);
213 index = definition->index;
214 } else {
215 /*
216 * Getting to a dynamic scope parent. We are
217 * guaranteed that the parent is entirely
218 * located before the child.
219 */
220 index = -1;
221 }
222 lookup:
223 if (is_path_child_of(lookup_path, scope->scope_path)) {
224 /* Means we can lookup the field in this scope */
225 last = g_array_index(lookup_path, GQuark,
226 scope->scope_path->len);
227 lookup_definition = lookup_field_definition_scope(last, scope);
228 if (!lookup_definition || ((index != -1) && lookup_definition->index >= index))
229 return NULL;
230 /* Found it! And it is prior to the current field. */
231 if (lookup_path->len - scope->scope_path->len == 1) {
232 /* Direct child */
233 return lookup_definition;
234 } else {
235 scope = get_definition_scope(lookup_definition);
236 /* Check if the definition has a sub-scope */
237 if (!scope)
238 return NULL;
239 /*
240 * Don't compare index anymore, because we are
241 * going within a scope that has been validated
242 * to be entirely prior to the current scope.
243 */
244 cur_path = NULL;
245 index = -1;
246 goto lookup;
247 }
248 } else {
249 /* lookup_path is within an upper scope */
250 cur_path = scope->scope_path;
251 scope = scope->parent_scope;
252 }
253 }
254 return NULL;
255 }
256
257 int register_field_definition(GQuark field_name, struct definition *definition,
258 struct definition_scope *scope)
259 {
260 if (!scope || !field_name)
261 return -EPERM;
262
263 /* Only lookup in local scope */
264 if (lookup_field_definition_scope(field_name, scope))
265 return -EEXIST;
266
267 g_hash_table_insert(scope->definitions,
268 (gpointer) (unsigned long) field_name,
269 definition);
270 /* Don't keep reference on definition */
271 return 0;
272 }
273
274 void declaration_ref(struct declaration *declaration)
275 {
276 declaration->ref++;
277 }
278
279 void declaration_unref(struct declaration *declaration)
280 {
281 if (!declaration)
282 return;
283 if (!--declaration->ref)
284 declaration->declaration_free(declaration);
285 }
286
287 void definition_ref(struct definition *definition)
288 {
289 definition->ref++;
290 }
291
292 void definition_unref(struct definition *definition)
293 {
294 if (!definition)
295 return;
296 if (!--definition->ref)
297 definition->declaration->definition_free(definition);
298 }
299
300 struct declaration_scope *
301 new_declaration_scope(struct declaration_scope *parent_scope)
302 {
303 struct declaration_scope *scope = g_new(struct declaration_scope, 1);
304
305 scope->typedef_declarations = g_hash_table_new_full(g_direct_hash,
306 g_direct_equal, NULL,
307 (GDestroyNotify) declaration_unref);
308 scope->struct_declarations = g_hash_table_new_full(g_direct_hash,
309 g_direct_equal, NULL,
310 (GDestroyNotify) declaration_unref);
311 scope->variant_declarations = g_hash_table_new_full(g_direct_hash,
312 g_direct_equal, NULL,
313 (GDestroyNotify) declaration_unref);
314 scope->enum_declarations = g_hash_table_new_full(g_direct_hash,
315 g_direct_equal, NULL,
316 (GDestroyNotify) declaration_unref);
317 scope->parent_scope = parent_scope;
318 return scope;
319 }
320
321 void free_declaration_scope(struct declaration_scope *scope)
322 {
323 g_hash_table_destroy(scope->enum_declarations);
324 g_hash_table_destroy(scope->variant_declarations);
325 g_hash_table_destroy(scope->struct_declarations);
326 g_hash_table_destroy(scope->typedef_declarations);
327 g_free(scope);
328 }
329
330 static
331 struct declaration_struct *lookup_struct_declaration_scope(GQuark struct_name,
332 struct declaration_scope *scope)
333 {
334 return g_hash_table_lookup(scope->struct_declarations,
335 (gconstpointer) (unsigned long) struct_name);
336 }
337
338 struct declaration_struct *lookup_struct_declaration(GQuark struct_name,
339 struct declaration_scope *scope)
340 {
341 struct declaration_struct *declaration;
342
343 while (scope) {
344 declaration = lookup_struct_declaration_scope(struct_name, scope);
345 if (declaration)
346 return declaration;
347 scope = scope->parent_scope;
348 }
349 return NULL;
350 }
351
352 int register_struct_declaration(GQuark struct_name,
353 struct declaration_struct *struct_declaration,
354 struct declaration_scope *scope)
355 {
356 GQuark prefix_name;
357 int ret;
358
359 if (!struct_name)
360 return -EPERM;
361
362 /* Only lookup in local scope */
363 if (lookup_struct_declaration_scope(struct_name, scope))
364 return -EEXIST;
365
366 g_hash_table_insert(scope->struct_declarations,
367 (gpointer) (unsigned long) struct_name,
368 struct_declaration);
369 declaration_ref(&struct_declaration->p);
370
371 /* Also add in typedef/typealias scopes */
372 prefix_name = prefix_quark("struct ", struct_name);
373 ret = register_declaration(prefix_name, &struct_declaration->p, scope);
374 assert(!ret);
375 return 0;
376 }
377
378 static
379 struct declaration_untagged_variant *
380 lookup_variant_declaration_scope(GQuark variant_name,
381 struct declaration_scope *scope)
382 {
383 return g_hash_table_lookup(scope->variant_declarations,
384 (gconstpointer) (unsigned long) variant_name);
385 }
386
387 struct declaration_untagged_variant *
388 lookup_variant_declaration(GQuark variant_name,
389 struct declaration_scope *scope)
390 {
391 struct declaration_untagged_variant *declaration;
392
393 while (scope) {
394 declaration = lookup_variant_declaration_scope(variant_name, scope);
395 if (declaration)
396 return declaration;
397 scope = scope->parent_scope;
398 }
399 return NULL;
400 }
401
402 int register_variant_declaration(GQuark variant_name,
403 struct declaration_untagged_variant *untagged_variant_declaration,
404 struct declaration_scope *scope)
405 {
406 GQuark prefix_name;
407 int ret;
408
409 if (!variant_name)
410 return -EPERM;
411
412 /* Only lookup in local scope */
413 if (lookup_variant_declaration_scope(variant_name, scope))
414 return -EEXIST;
415
416 g_hash_table_insert(scope->variant_declarations,
417 (gpointer) (unsigned long) variant_name,
418 untagged_variant_declaration);
419 declaration_ref(&untagged_variant_declaration->p);
420
421 /* Also add in typedef/typealias scopes */
422 prefix_name = prefix_quark("variant ", variant_name);
423 ret = register_declaration(prefix_name,
424 &untagged_variant_declaration->p, scope);
425 assert(!ret);
426 return 0;
427 }
428
429 static
430 struct declaration_enum *
431 lookup_enum_declaration_scope(GQuark enum_name,
432 struct declaration_scope *scope)
433 {
434 return g_hash_table_lookup(scope->enum_declarations,
435 (gconstpointer) (unsigned long) enum_name);
436 }
437
438 struct declaration_enum *
439 lookup_enum_declaration(GQuark enum_name,
440 struct declaration_scope *scope)
441 {
442 struct declaration_enum *declaration;
443
444 while (scope) {
445 declaration = lookup_enum_declaration_scope(enum_name, scope);
446 if (declaration)
447 return declaration;
448 scope = scope->parent_scope;
449 }
450 return NULL;
451 }
452
453 int register_enum_declaration(GQuark enum_name,
454 struct declaration_enum *enum_declaration,
455 struct declaration_scope *scope)
456 {
457 GQuark prefix_name;
458 int ret;
459
460 if (!enum_name)
461 return -EPERM;
462
463 /* Only lookup in local scope */
464 if (lookup_enum_declaration_scope(enum_name, scope))
465 return -EEXIST;
466
467 g_hash_table_insert(scope->enum_declarations,
468 (gpointer) (unsigned long) enum_name,
469 enum_declaration);
470 declaration_ref(&enum_declaration->p);
471
472 /* Also add in typedef/typealias scopes */
473 prefix_name = prefix_quark("enum ", enum_name);
474 ret = register_declaration(prefix_name, &enum_declaration->p, scope);
475 assert(!ret);
476 return 0;
477 }
478
479 static struct definition_scope *
480 _new_definition_scope(struct definition_scope *parent_scope,
481 int scope_path_len)
482 {
483 struct definition_scope *scope = g_new(struct definition_scope, 1);
484
485 scope->definitions = g_hash_table_new(g_direct_hash,
486 g_direct_equal);
487 scope->parent_scope = parent_scope;
488 scope->scope_path = g_array_sized_new(FALSE, TRUE, sizeof(GQuark),
489 scope_path_len);
490 g_array_set_size(scope->scope_path, scope_path_len);
491 return scope;
492 }
493
494 GQuark new_definition_path(struct definition_scope *parent_scope,
495 GQuark field_name, const char *root_name)
496 {
497 GQuark path;
498 GString *str;
499 gchar *c_str;
500 int i;
501 int need_dot = 0;
502
503 str = g_string_new("");
504 if (root_name) {
505 g_string_append(str, root_name);
506 need_dot = 1;
507 } else if (parent_scope) {
508 for (i = 0; i < parent_scope->scope_path->len; i++) {
509 GQuark q = g_array_index(parent_scope->scope_path,
510 GQuark, i);
511 if (!q)
512 continue;
513 if (need_dot)
514 g_string_append(str, ".");
515 g_string_append(str, g_quark_to_string(q));
516 need_dot = 1;
517 }
518 }
519 if (field_name) {
520 if (need_dot)
521 g_string_append(str, ".");
522 g_string_append(str, g_quark_to_string(field_name));
523 }
524 c_str = g_string_free(str, FALSE);
525 if (c_str[0] == '\0')
526 return 0;
527 path = g_quark_from_string(c_str);
528 printf_debug("new definition path: %s\n", c_str);
529 g_free(c_str);
530 return path;
531 }
532
533 struct definition_scope *
534 new_definition_scope(struct definition_scope *parent_scope,
535 GQuark field_name, const char *root_name)
536 {
537 struct definition_scope *scope;
538
539 if (root_name) {
540 scope = _new_definition_scope(parent_scope, 0);
541 append_scope_path(root_name, scope->scope_path);
542 } else {
543 int scope_path_len = 1;
544
545 assert(parent_scope);
546 scope_path_len += parent_scope->scope_path->len;
547 scope = _new_definition_scope(parent_scope, scope_path_len);
548 memcpy(scope->scope_path->data, parent_scope->scope_path->data,
549 sizeof(GQuark) * (scope_path_len - 1));
550 g_array_index(scope->scope_path, GQuark, scope_path_len - 1) =
551 field_name;
552 }
553 if (babeltrace_debug) {
554 int i, need_dot = 0;
555
556 printf_debug("new definition scope: ");
557 for (i = 0; i < scope->scope_path->len; need_dot = 1, i++)
558 printf("%s%s", need_dot ? "." : "",
559 g_quark_to_string(g_array_index(scope->scope_path, GQuark, i)));
560 printf("\n");
561 }
562 return scope;
563 }
564
565 /*
566 * in: path (dot separated), out: q (GArray of GQuark)
567 */
568 void append_scope_path(const char *path, GArray *q)
569 {
570 const char *ptrbegin, *ptrend = path;
571 GQuark quark;
572
573 for (;;) {
574 char *str;
575 size_t len;
576
577 ptrbegin = ptrend;
578 ptrend = strchr(ptrbegin, '.');
579 if (!ptrend)
580 break;
581 len = ptrend - ptrbegin;
582 /* Don't accept two consecutive dots */
583 assert(len != 0);
584 str = g_new(char, len + 1); /* include \0 */
585 memcpy(str, ptrbegin, len);
586 str[len] = '\0';
587 quark = g_quark_from_string(str);
588 g_array_append_val(q, quark);
589 g_free(str);
590 ptrend++; /* skip current dot */
591 }
592 /* last. Check for trailing dot (and discard). */
593 if (ptrbegin[0] != '\0') {
594 quark = g_quark_from_string(ptrbegin);
595 g_array_append_val(q, quark);
596 }
597 }
598
599 void free_definition_scope(struct definition_scope *scope)
600 {
601 g_array_free(scope->scope_path, TRUE);
602 g_hash_table_destroy(scope->definitions);
603 g_free(scope);
604 }
605
606 struct definition *lookup_definition(const struct definition *definition,
607 const char *field_name)
608 {
609 struct definition_scope *scope = get_definition_scope(definition);
610
611 if (!scope)
612 return NULL;
613
614 return lookup_field_definition_scope(g_quark_from_string(field_name),
615 scope);
616 }
617
618 struct definition_integer *lookup_integer(const struct definition *definition,
619 const char *field_name,
620 int signedness)
621 {
622 struct definition *lookup;
623 struct definition_integer *lookup_integer;
624
625 lookup = lookup_definition(definition, field_name);
626 if (!lookup)
627 return NULL;
628 if (lookup->declaration->id != CTF_TYPE_INTEGER)
629 return NULL;
630 lookup_integer = container_of(lookup, struct definition_integer, p);
631 if (lookup_integer->declaration->signedness != signedness)
632 return NULL;
633 return lookup_integer;
634 }
635
636 struct definition_enum *lookup_enum(const struct definition *definition,
637 const char *field_name,
638 int signedness)
639 {
640 struct definition *lookup;
641 struct definition_enum *lookup_enum;
642
643 lookup = lookup_definition(definition, field_name);
644 if (!lookup)
645 return NULL;
646 if (lookup->declaration->id != CTF_TYPE_ENUM)
647 return NULL;
648 lookup_enum = container_of(lookup, struct definition_enum, p);
649 if (lookup_enum->integer->declaration->signedness != signedness)
650 return NULL;
651 return lookup_enum;
652 }
653
654 struct definition *lookup_variant(const struct definition *definition,
655 const char *field_name)
656 {
657 struct definition *lookup;
658 struct definition_variant *lookup_variant;
659
660 lookup = lookup_definition(definition, field_name);
661 if (!lookup)
662 return NULL;
663 if (lookup->declaration->id != CTF_TYPE_VARIANT)
664 return NULL;
665 lookup_variant = container_of(lookup, struct definition_variant, p);
666 lookup = variant_get_current_field(lookup_variant);
667 assert(lookup);
668 return lookup;
669 }
This page took 0.041531 seconds and 4 git commands to generate.